/[winpt]/trunk/Src/wptW32API.cpp
ViewVC logotype

Contents of /trunk/Src/wptW32API.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 278 - (show annotations)
Mon Jan 15 22:02:04 2007 UTC (18 years, 1 month ago) by twoaday
File size: 16918 byte(s)
See ChangeLog.


1 /* wptW32API.cpp - Common W32 API functions
2 * Copyright (C) 2001, 2002, 2003, 2005, 2006 Timo Schulz
3 *
4 * This file is part of WinPT.
5 *
6 * WinPT is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * WinPT is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16 #ifdef HAVE_CONFIG_H
17 #include <config.h>
18 #endif
19
20 #include <windows.h>
21 #include <stdio.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <shellapi.h>
25 #include <shlobj.h>
26 #include <commctrl.h>
27 #include <time.h>
28
29 #include "wptNLS.h"
30 #include "wptW32API.h"
31 #include "wptErrors.h"
32 #include "wptVersion.h"
33 #include "wptUTF8.h"
34 #include "wptTypes.h"
35
36
37 extern "C" void _SHFree (void *p);
38
39
40 /* Insert a new item into the menu @hm at position @pos. */
41 void
42 insert_menu_item (HMENU hm, int pos, UINT m_id, const char *text)
43 {
44 MENUITEMINFO mi;
45
46 memset (&mi, 0, sizeof mi);
47 mi.cbSize = sizeof mi;
48 mi.fType = MF_STRING;
49 mi.dwTypeData = (char *)text;
50 mi.cch = strlen (text);
51 mi.wID = m_id;
52 mi.fMask = MIIM_ID|MIIM_DATA| MIIM_TYPE;
53 InsertMenuItem (hm, pos, FALSE, &mi);
54 }
55
56
57 static void
58 set_menu_text_ext (HMENU menu, int by_pos, int m_uid, const char *text)
59 {
60 MENUITEMINFO mii;
61
62 memset (&mii, 0, sizeof mii);
63 mii.cbSize = sizeof mii;
64 mii.fMask = MIIM_TYPE;
65 mii.fType = MFT_STRING;
66 mii.dwTypeData = (char *) text;
67 SetMenuItemInfo (menu, m_uid, by_pos? TRUE : FALSE, &mii);
68 }
69
70
71 /* Set the text of a menu item @m_uid to @text. */
72 void
73 set_menu_text (HMENU menu, UINT m_uid, const char *text)
74 {
75 set_menu_text_ext (menu, 0, m_uid, text);
76 }
77
78
79 /* Set the text of a menu item with the position @pos to @text. */
80 void
81 set_menu_text_bypos (HMENU menu, UINT pos, const char *text)
82 {
83 set_menu_text_ext (menu, 1, pos, text);
84 }
85
86
87 /* Set the state of a menu item @m_uid to @state. */
88 void
89 set_menu_state (HMENU menu, UINT m_uid, UINT state)
90 {
91 MENUITEMINFO mii;
92
93 memset (&mii, 0, sizeof (mii));
94 mii.cbSize = sizeof (mii);
95 mii.fMask = MIIM_STATE;
96 mii.fState = state;
97 SetMenuItemInfo (menu, m_uid, FALSE, &mii);
98 }
99
100
101 /* Retrieve the state of the menu item @m_uid and return it. */
102 UINT
103 get_menu_state (HMENU menu, UINT m_uid)
104 {
105 MENUITEMINFO mii;
106
107 memset (&mii, 0, sizeof (mii));
108 mii.cbSize = sizeof (mii);
109 mii.fMask = MIIM_STATE;
110 GetMenuItemInfo (menu, m_uid, FALSE, &mii);
111 return mii.fState;
112 }
113
114
115 enum {
116 CDLG_FILE_OPEN = 0,
117 CDLG_FILE_SAVE = 1
118 };
119
120 /* Use the common dialog to request a file from the user.
121 id can be either FILE_OPEN or FILE_SAVE.
122 The return value is the file name or NULL if cancel was chosen. */
123 const char *
124 get_filename_dlg (HWND hwnd, int id, const char *title,
125 const char *filter, const char *name)
126 {
127 static char file[2*MAX_PATH+1] = "";
128 char workdir[MAX_PATH+1];
129 char *sel_file = NULL;
130 OPENFILENAME open;
131
132 if (name && strlen (name) < (DIM (file)-1))
133 strcpy (file, name);
134 else
135 memset (file, 0, sizeof (file));
136 if (!filter)
137 filter = "All Files (*.*)\0*.*\0\0";
138
139 GetCurrentDirectory (MAX_PATH, workdir);
140 memset (&open, 0, sizeof (open));
141 open.lStructSize = sizeof (OPENFILENAME);
142 open.hInstance = glob_hinst;
143 open.lpstrTitle = title;
144 open.lpstrFilter = filter;
145 open.hwndOwner = hwnd;
146 open.lpstrFile = file;
147 open.nMaxFile = DIM (file) - 1;
148 if (id == CDLG_FILE_OPEN)
149 open.Flags = OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST;
150 else
151 open.Flags = OFN_OVERWRITEPROMPT;
152
153 if (id == CDLG_FILE_OPEN && GetOpenFileName (&open))
154 sel_file = open.lpstrFile;
155 else if (id == CDLG_FILE_SAVE && GetSaveFileName (&open))
156 sel_file = open.lpstrFile;
157 SetCurrentDirectory (workdir);
158
159 return sel_file;
160 }
161
162 const char*
163 get_filesave_dlg (HWND hwnd, const char *title,
164 const char *filter, const char *name)
165 {
166 return get_filename_dlg (hwnd, CDLG_FILE_SAVE, title, filter, name);
167 }
168
169 const char*
170 get_fileopen_dlg (HWND hwnd, const char *title, const char *filter,
171 const char *name)
172 {
173 return get_filename_dlg (hwnd, CDLG_FILE_OPEN, title, filter, name);
174 }
175
176
177 /* Use the common dialog to allow the user to select a folder.
178 The return value is either the folder path or NULL if cancel was chosen. */
179 const char*
180 get_folder_dlg (HWND hwnd, const char *title, const char *name)
181 {
182 static char folder[MAX_PATH+1] = "";
183 BROWSEINFO bi;
184 ITEMIDLIST *il;
185
186 memset (&bi, 0, sizeof (bi));
187 bi.hwndOwner = hwnd;
188 if (title)
189 bi.lpszTitle = title;
190 if (name && strlen (name) < MAX_PATH-1)
191 strcpy (folder, name);
192 else
193 memset (folder, 0, sizeof (folder));
194 il = SHBrowseForFolder (&bi);
195 if (il != NULL) {
196 SHGetPathFromIDList (il, folder);
197 _SHFree (il);
198 return folder;
199 }
200 return NULL;
201 }
202
203
204 /* Return the clipboard contents as a string or NULL
205 if the clipboard does not contain text. */
206 char*
207 get_clip_text (HWND hwnd)
208 {
209 HANDLE clipmem;
210 char *cliptxt, *p;
211 int len;
212
213 if (OpenClipboard (hwnd) == FALSE)
214 return NULL;
215 clipmem = GetClipboardData (CF_TEXT);
216 if (clipmem == NULL) {
217 p = NULL;
218 goto leave;
219 }
220 cliptxt = (char *) GlobalLock (clipmem);
221 if (cliptxt == NULL) {
222 p = NULL;
223 goto leave;
224 }
225
226 len = strlen (cliptxt);
227 p = new char[len + 1];
228 if (!p)
229 BUG (NULL);
230 memcpy (p, cliptxt, len);
231 p[len] = '\0';
232 GlobalUnlock (clipmem);
233
234 leave:
235 CloseClipboard ();
236 return p;
237 }
238
239
240 /* Set @text as the new clipboard content. */
241 int
242 set_clip_text (HWND hwnd, const char *text, int nbytes)
243 {
244 HANDLE clipmem;
245 int rc = 0;
246 char *p;
247
248 if (OpenClipboard (hwnd) == FALSE)
249 return WPTERR_CLIP_OPEN;
250 EmptyClipboard ();
251
252 clipmem = GlobalAlloc (GHND, nbytes + 1);
253 if (clipmem == NULL)
254 BUG (NULL);
255 p = (char *) GlobalLock (clipmem);
256 if (p == NULL) {
257 CloseClipboard ();
258 GlobalFree (clipmem);
259 return WPTERR_GENERAL;
260 }
261 memcpy (p, text, nbytes);
262 p[nbytes] = '\0';
263
264 SetClipboardData (CF_TEXT, clipmem);
265 GlobalUnlock (clipmem);
266 CloseClipboard ();
267 GlobalFree (clipmem);
268
269 return rc;
270 }
271
272
273 /* Append or prepend some text to the clipboard contents.
274 If as_footer = 1, append the text otherwise prepend. */
275 int
276 set_clip_text2 (HWND hwnd, const char *text, int nbytes, int as_footer)
277 {
278 const char *fmt;
279 char *p, *new_text;
280
281 p = get_clip_text (hwnd);
282 if (!p)
283 return WPTERR_CLIP_GET;
284 if (as_footer == 0)
285 fmt = "%s\r\n%s\r\n\r\n";
286 else
287 fmt = "%s\n%s\n\n";
288 new_text = new char [strlen (p)+strlen (text)+strlen (fmt)+2];
289 if (!new_text)
290 BUG (0);
291 if (as_footer == 0)
292 sprintf (new_text, fmt, text, p);
293 else
294 sprintf (new_text, fmt, p, text);
295 set_clip_text (hwnd, new_text, strlen (new_text)+1);
296 free_if_alloc (p);
297 free_if_alloc (new_text);
298 return 0;
299 }
300
301
302 /* Make a file name out of the path @path, the file @file and
303 an extension. @ext.
304 Return value: the full file name on success. */
305 char*
306 make_filename (const char *path, const char *file, const char *ext)
307 {
308 char *p;
309 size_t size = 0;
310
311 if (path && *path)
312 size += strlen (path);
313 if (file && *file)
314 size += strlen (file);
315 if (ext && *ext)
316 size += strlen (ext);
317 p = new char[size + 4];
318 if (!p)
319 BUG (0);
320 memset (p, 0, size);
321 if (path) {
322 strcat (p, path);
323 if (path[strlen (path) -1] != '\\')
324 strcat (p, "\\");
325 }
326 if (file != NULL)
327 strcat (p, file);
328 if (ext != NULL) {
329 strcat (p, ".");
330 strcat (p, ext);
331 }
332 return p;
333 }
334
335
336 /* Generate a file name from a special dirctory. */
337 char*
338 make_special_filename (int folder, const char *file, const char *ext)
339 {
340 BOOL ec;
341 char path[MAX_PATH], *p;
342 size_t n=0;
343
344 /* MSDN: buf must be at least MAX_PATH=256 bytes */
345 ec = SHGetSpecialFolderPath (HWND_DESKTOP, path, folder, TRUE);
346 if (ec != 1) {
347 log_debug ("SHGetSpecialFolderPath() failed\r\n", (int)GetLastError ());
348 return NULL;
349 }
350
351 n = strlen (path)+1;
352 if (file)
353 n += strlen (file)+1;
354 if (ext)
355 n += strlen (ext)+1;
356 p = new char[n+2];
357 if (!p)
358 BUG (0);
359 memset (p, 0, n+2);
360 strcpy (p, path);
361 if (file) {
362 strcat (p, "\\");
363 strcat (p, file);
364 }
365 if (ext)
366 strcat (p, ext);
367 return p;
368 }
369
370
371 /* return 0 if the file @fname exists, otherwise >0. */
372 int
373 file_exist_check (const char *fname)
374 {
375 struct stat st;
376 if (stat (fname, &st) == -1)
377 return WPTERR_FILE_EXIST;
378 return 0;
379 }
380
381
382 /* Check if the current folder exists.
383 Return 0 for success. */
384 int
385 dir_exist_check (const char *dir)
386 {
387 struct stat statbuf;
388
389 if (stat (dir, &statbuf) == -1)
390 return WPTERR_GENERAL;
391 if (statbuf.st_mode & _S_IFDIR)
392 return 0;
393 return WPTERR_GENERAL;
394 }
395
396
397 /* Return the file size of the given file @fname. */
398 DWORD
399 get_file_size (const char *fname)
400 {
401 DWORD fsize;
402 HANDLE fh;
403
404 fh = CreateFile (fname, GENERIC_READ, FILE_SHARE_READ,
405 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
406 if (fh == INVALID_HANDLE_VALUE)
407 return 0;
408 fsize = GetFileSize (fh, NULL);
409 if (fsize == 0xFFFFFFFF)
410 fsize = 0;
411 CloseHandle (fh);
412 return fsize;
413 }
414
415
416 /* Start a dialog with the exception that before it is checked that the
417 dialog is not already openened. */
418 int
419 dialog_box_param (HINSTANCE hinst, LPCTSTR name, HWND parent, DLGPROC fnc,
420 LPARAM param, LPCTSTR title, int title_id)
421 {
422 if (FindWindowEx (GetDesktopWindow (), NULL, NULL, title))
423 return -1;
424 return DialogBoxParam (hinst, name, parent, fnc, param);
425 }
426
427
428 /* Wrapper for message box which forces the message box into the
429 foreground and it is displayed always on top. */
430 int
431 msg_box (HWND hwnd, const char *text, const char *title, int mode)
432 {
433 mode |= MB_SETFOREGROUND;
434 mode |= MB_TASKMODAL;
435 mode |= MB_TOPMOST;
436 return MessageBox(hwnd, text, title, mode);
437 }
438
439
440 /* Center the hwndChild relative to parent.
441 The style param allows to specificy additional styles (like topmost). */
442 void
443 center_window2 (HWND hwndChild, HWND parent, HWND style)
444 {
445 HWND hwndParent;
446 RECT rChild, rParent;
447 HDC hdc;
448 int wChild, hChild, wParent, hParent;
449 int wScreen, hScreen, xNew, yNew;
450 int flags = SWP_NOSIZE | SWP_NOZORDER;
451
452 hwndParent = parent;
453 if (hwndParent == NULL)
454 hwndParent = GetDesktopWindow ();
455 GetWindowRect (hwndChild, &rChild);
456 wChild = rChild.right - rChild.left;
457 hChild = rChild.bottom - rChild.top;
458
459 GetWindowRect (hwndParent, &rParent);
460 wParent = rParent.right - rParent.left;
461 hParent = rParent.bottom - rParent.top;
462
463 hdc = GetDC (hwndChild);
464 wScreen = GetDeviceCaps (hdc, HORZRES);
465 hScreen = GetDeviceCaps (hdc, VERTRES);
466 ReleaseDC (hwndChild, hdc);
467 xNew = rParent.left + ((wParent - wChild) /2);
468 if (xNew < 0)
469 xNew = 0;
470 else if ((xNew+wChild) > wScreen)
471 xNew = wScreen - wChild;
472 yNew = rParent.top + ((hParent - hChild) /2);
473 if (yNew < 0)
474 yNew = 0;
475 else if ((yNew+hChild) > hScreen)
476 yNew = hScreen - hChild;
477 if (style == HWND_TOPMOST || style == HWND_NOTOPMOST)
478 flags = SWP_NOMOVE | SWP_NOSIZE;
479 SetWindowPos (hwndChild, style? style : NULL, xNew, yNew, 0, 0, flags);
480 }
481
482
483 /* Center the given hwndChild window with no special style. */
484 void
485 center_window (HWND child, HWND parent)
486 {
487 center_window2 (child, parent, NULL);
488 }
489
490
491 /* Retrieve the product verion of the given file @fname.
492 Format: MAJOR.MINOR.PATCH1.PATCH2
493 Return value: 0 on success. */
494 int
495 get_file_version (const char *fname,
496 WORD *major, WORD *minor, WORD *patch1, WORD *patch2)
497 {
498 VS_FIXEDFILEINFO *inf;
499 char file[MAX_PATH+1] = {0};
500 LPVOID buf, data;
501 DWORD arg;
502 DWORD size;
503 UINT qlen;
504
505 strncpy (file, fname, MAX_PATH);
506 size = GetFileVersionInfoSize (file, &arg);
507 if (!size)
508 return -1;
509 buf = (LPVOID)new char[size];
510 if (!buf)
511 BUG (NULL);
512 GetFileVersionInfo (file, 0, size, buf);
513
514 qlen=0;
515 VerQueryValue (buf, "\\", &data, &qlen);
516 if (!qlen) {
517 delete [](char*)buf;
518 return -1;
519 }
520 inf = (VS_FIXEDFILEINFO*)data;
521
522 if (major)
523 *major = HIWORD (inf->dwProductVersionMS);
524 if (minor)
525 *minor = LOWORD (inf->dwProductVersionMS);
526 if (patch1)
527 *patch1 = HIWORD (inf->dwProductVersionLS);
528 if (patch2)
529 *patch2 = LOWORD (inf->dwProductVersionLS);
530
531 delete [](char*)buf;
532 return 0;
533 }
534
535
536 /* Return date in a format which complies with the
537 locale user settings. */
538 const char*
539 get_locale_date (long tm_t, char *buf, DWORD buflen)
540 {
541 SYSTEMTIME st;
542 struct tm *ptm;
543
544 ptm = localtime (&tm_t);
545 memset (&st, 0, sizeof (st));
546 st.wYear = (WORD)ptm->tm_year+1900;
547 st.wMonth = (WORD)ptm->tm_mon+1;
548 st.wDay = (WORD)ptm->tm_mday;
549 if (!GetDateFormat (LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st,
550 NULL, buf, buflen))
551 return NULL;
552 return buf;
553 }
554
555 /* Return the time in a format which complies with the locale user
556 settings. */
557 const char*
558 get_locale_time (long tm_t, char *buf, DWORD buflen)
559 {
560 SYSTEMTIME st;
561 struct tm *ptm;
562
563 ptm = localtime (&tm_t);
564 memset (&st, 0, sizeof (st));
565 st.wMinute = (WORD)ptm->tm_min;
566 st.wHour = (WORD)ptm->tm_hour;
567 st.wSecond = (WORD)ptm->tm_sec;
568
569 if (!GetTimeFormat (LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT, &st,
570 NULL, buf, buflen))
571 return NULL;
572 return buf;
573 }
574
575
576 /* Return a combination of date+time which complies to the
577 local user settings. */
578 const char*
579 get_locale_timedate (long tm_t, char *buf, DWORD buflen)
580 {
581 DWORD nleft = buflen;
582
583 if (!get_locale_date (tm_t, buf, buflen))
584 return NULL;
585 nleft -= strlen (buf)+1;
586 if (nleft < 1)
587 return NULL;
588 strcat (buf, " ");
589 nleft--;
590 if (!get_locale_time (tm_t, buf+strlen (buf), nleft))
591 return NULL;
592 return buf;
593 }
594
595
596 /* Generate a temporary file name by using the users
597 temp path and optionally a name @name provided by the caller.
598 Return value: 0 on success. */
599 int
600 get_temp_name (char *buf, DWORD buflen, const char *name)
601 {
602 char tmp[32];
603
604
605 if (!name) {
606 _snprintf (tmp, DIM (tmp)-1, "%08lX", GetTickCount ());
607 name = tmp;
608 }
609
610 /* In the mobile mode we need to use the current directory
611 as the temp path because no files should be stored outside
612 the USB disk drive. */
613 #ifdef WINPT_MOBILE
614 memset (buf, 0, buflen);
615 strncpy (buf, name, buflen-1);
616 return 0;
617 #endif
618
619 if (!GetTempPath (buflen - strlen (name) -2, buf)) {
620 log_debug ("GetTempPath() failed ec=%d\n", (int)GetLastError ());
621 return -1;
622 }
623
624 strcat (buf, name);
625 return 0;
626 }
627
628
629 void
630 ListBox_AddString_utf8 (HWND lb, const char *txt)
631 {
632 char *utf8_txt;
633
634 utf8_txt = utf8_to_native (txt);
635 SendMessage (lb, LB_ADDSTRING, 0, (LPARAM)(LPCSTR)(utf8_txt));
636 safe_free (utf8_txt);
637 }
638
639
640 void
641 ComboBox_AddString_utf8 (HWND cb, const char *txt)
642 {
643 char *utf8_txt;
644
645 utf8_txt = utf8_to_native (txt);
646 SendMessage ((cb), CB_ADDSTRING, 0, (LPARAM)(LPCSTR)(utf8_txt));
647 safe_free (utf8_txt);
648 }
649
650
651 /* GetDlgItemText replacement with UTF8 support. */
652 int
653 GetDlgItemText_utf8 (HWND dlg, int id, char **r_txt)
654 {
655 int len = GetWindowTextLength (GetDlgItem (dlg, id));
656 char *txt;
657
658 *r_txt = NULL;
659 if (len < 1)
660 return 0;
661 txt = new char[len+2];
662 if (!txt)
663 BUG (NULL);
664 GetDlgItemText (dlg, id, txt, len+1);
665 *r_txt = native_to_utf8 (txt);
666 free_if_alloc (txt);
667 return len;
668 }
669
670
671 /* Return TRUE if the current user has admin privileges. */
672 BOOL
673 user_is_admin (void)
674 {
675 SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
676 HANDLE hd;
677 TOKEN_GROUPS *ptg = NULL;
678 DWORD ngtoken;
679 DWORD i;
680 BOOL admin = FALSE;
681 PSID psid = 0;
682
683 if (GetVersion () & 0x80000000) /* Win9X */
684 return TRUE;
685
686 if (!OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, FALSE, &hd) &&
687 !OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &hd))
688 return FALSE;
689
690 if (!GetTokenInformation (hd, TokenGroups, NULL, 0, &ngtoken) &&
691 GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
692 ptg = (TOKEN_GROUPS*)GlobalAlloc (GPTR, ngtoken);
693 if (!ptg)
694 return FALSE;
695
696 if (!GetTokenInformation (hd, TokenGroups,
697 ptg, ngtoken, &ngtoken)) {
698 GlobalFree (ptg);
699 return FALSE;
700 }
701 AllocateAndInitializeSid (&SystemSidAuthority,
702 2, SECURITY_BUILTIN_DOMAIN_RID,
703 DOMAIN_ALIAS_RID_ADMINS,
704 0, 0, 0, 0, 0, 0,
705 &psid);
706 for (i = 0; i < ptg->GroupCount; i++) {
707 if (EqualSid (ptg->Groups[i].Sid, psid)) {
708 admin = TRUE;
709 break;
710 }
711 }
712 FreeSid (psid);
713 GlobalFree (ptg);
714 }
715
716 CloseHandle (hd);
717 return admin;
718 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26