]> git.saurik.com Git - wxWidgets.git/blob - src/msw/utils.cpp
Compilation without threads.
[wxWidgets.git] / src / msw / utils.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/utils.cpp
3 // Purpose: Various utilities
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #ifndef WX_PRECOMP
28 #include "wx/utils.h"
29 #include "wx/app.h"
30 #include "wx/intl.h"
31 #include "wx/log.h"
32 #endif //WX_PRECOMP
33
34 #include "wx/msw/registry.h"
35 #include "wx/apptrait.h"
36 #include "wx/dynlib.h"
37 #include "wx/dynload.h"
38 #include "wx/scopeguard.h"
39
40 #include "wx/confbase.h" // for wxExpandEnvVars()
41
42 #include "wx/msw/private.h" // includes <windows.h>
43 #include "wx/msw/missing.h" // for CHARSET_HANGUL
44
45 #if defined(__CYGWIN__)
46 //CYGWIN gives annoying warning about runtime stuff if we don't do this
47 # define USE_SYS_TYPES_FD_SET
48 # include <sys/types.h>
49 #endif
50
51 // Doesn't work with Cygwin at present
52 #if wxUSE_SOCKETS && (defined(__GNUWIN32_OLD__) || defined(__WXWINCE__) || defined(__CYGWIN32__))
53 // apparently we need to include winsock.h to get WSADATA and other stuff
54 // used in wxGetFullHostName() with the old mingw32 versions
55 #include <winsock.h>
56 #endif
57
58 #if !defined(__GNUWIN32__) && !defined(__SALFORDC__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
59 #include <direct.h>
60
61 #ifndef __MWERKS__
62 #include <dos.h>
63 #endif
64 #endif //GNUWIN32
65
66 #if defined(__CYGWIN__)
67 #include <sys/unistd.h>
68 #include <sys/stat.h>
69 #include <sys/cygwin.h> // for cygwin_conv_to_full_win32_path()
70 #endif //GNUWIN32
71
72 #ifdef __BORLANDC__ // Please someone tell me which version of Borland needs
73 // this (3.1 I believe) and how to test for it.
74 // If this works for Borland 4.0 as well, then no worries.
75 #include <dir.h>
76 #endif
77
78 // VZ: there is some code using NetXXX() functions to get the full user name:
79 // I don't think it's a good idea because they don't work under Win95 and
80 // seem to return the same as wxGetUserId() under NT. If you really want
81 // to use them, just #define USE_NET_API
82 #undef USE_NET_API
83
84 #ifdef USE_NET_API
85 #include <lm.h>
86 #endif // USE_NET_API
87
88 #if defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
89 #ifndef __UNIX__
90 #include <io.h>
91 #endif
92
93 #ifndef __GNUWIN32__
94 #include <shellapi.h>
95 #endif
96 #endif
97
98 #ifndef __WATCOMC__
99 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
100 #include <errno.h>
101 #endif
102 #endif
103
104 // For wxKillAllChildren
105 #include <tlhelp32.h>
106
107 // ----------------------------------------------------------------------------
108 // constants
109 // ----------------------------------------------------------------------------
110
111 // In the WIN.INI file
112 #if (!defined(USE_NET_API) && !defined(__WXWINCE__)) || defined(__WXMICROWIN__)
113 static const wxChar WX_SECTION[] = wxT("wxWindows");
114 #endif
115
116 #if (!defined(USE_NET_API) && !defined(__WXWINCE__))
117 static const wxChar eUSERNAME[] = wxT("UserName");
118 #endif
119
120 // ============================================================================
121 // implementation
122 // ============================================================================
123
124 // ----------------------------------------------------------------------------
125 // get host name and related
126 // ----------------------------------------------------------------------------
127
128 // Get hostname only (without domain name)
129 bool wxGetHostName(wxChar *WXUNUSED_IN_WINCE(buf),
130 int WXUNUSED_IN_WINCE(maxSize))
131 {
132 #if defined(__WXWINCE__)
133 // TODO-CE
134 return false;
135 #elif defined(__WIN32__) && !defined(__WXMICROWIN__)
136 DWORD nSize = maxSize;
137 if ( !::GetComputerName(buf, &nSize) )
138 {
139 wxLogLastError(wxT("GetComputerName"));
140
141 return false;
142 }
143
144 return true;
145 #else
146 wxChar *sysname;
147 const wxChar *default_host = wxT("noname");
148
149 if ((sysname = wxGetenv(wxT("SYSTEM_NAME"))) == NULL) {
150 GetProfileString(WX_SECTION, eHOSTNAME, default_host, buf, maxSize - 1);
151 } else
152 wxStrncpy(buf, sysname, maxSize - 1);
153 buf[maxSize] = wxT('\0');
154 return *buf ? true : false;
155 #endif
156 }
157
158 // get full hostname (with domain name if possible)
159 bool wxGetFullHostName(wxChar *buf, int maxSize)
160 {
161 #if !defined( __WXMICROWIN__) && wxUSE_DYNAMIC_LOADER && wxUSE_SOCKETS
162 // TODO should use GetComputerNameEx() when available
163
164 // we don't want to always link with Winsock DLL as we might not use it at
165 // all, so load it dynamically here if needed (and don't complain if it is
166 // missing, we handle this)
167 wxLogNull noLog;
168
169 wxDynamicLibrary dllWinsock(_T("ws2_32.dll"), wxDL_VERBATIM);
170 if ( dllWinsock.IsLoaded() )
171 {
172 typedef int (PASCAL *WSAStartup_t)(WORD, WSADATA *);
173 typedef int (PASCAL *gethostname_t)(char *, int);
174 typedef hostent* (PASCAL *gethostbyname_t)(const char *);
175 typedef hostent* (PASCAL *gethostbyaddr_t)(const char *, int , int);
176 typedef int (PASCAL *WSACleanup_t)(void);
177
178 #define LOAD_WINSOCK_FUNC(func) \
179 func ## _t \
180 pfn ## func = (func ## _t)dllWinsock.GetSymbol(_T(#func))
181
182 LOAD_WINSOCK_FUNC(WSAStartup);
183
184 WSADATA wsa;
185 if ( pfnWSAStartup && pfnWSAStartup(MAKEWORD(1, 1), &wsa) == 0 )
186 {
187 LOAD_WINSOCK_FUNC(gethostname);
188
189 wxString host;
190 if ( pfngethostname )
191 {
192 char bufA[256];
193 if ( pfngethostname(bufA, WXSIZEOF(bufA)) == 0 )
194 {
195 // gethostname() won't usually include the DNS domain name,
196 // for this we need to work a bit more
197 if ( !strchr(bufA, '.') )
198 {
199 LOAD_WINSOCK_FUNC(gethostbyname);
200
201 struct hostent *pHostEnt = pfngethostbyname
202 ? pfngethostbyname(bufA)
203 : NULL;
204
205 if ( pHostEnt )
206 {
207 // Windows will use DNS internally now
208 LOAD_WINSOCK_FUNC(gethostbyaddr);
209
210 pHostEnt = pfngethostbyaddr
211 ? pfngethostbyaddr(pHostEnt->h_addr,
212 4, AF_INET)
213 : NULL;
214 }
215
216 if ( pHostEnt )
217 {
218 host = wxString::FromAscii(pHostEnt->h_name);
219 }
220 }
221 }
222 }
223
224 LOAD_WINSOCK_FUNC(WSACleanup);
225 if ( pfnWSACleanup )
226 pfnWSACleanup();
227
228
229 if ( !host.empty() )
230 {
231 wxStrncpy(buf, host, maxSize);
232
233 return true;
234 }
235 }
236 }
237 #endif // !__WXMICROWIN__
238
239 return wxGetHostName(buf, maxSize);
240 }
241
242 // Get user ID e.g. jacs
243 bool wxGetUserId(wxChar *WXUNUSED_IN_WINCE(buf),
244 int WXUNUSED_IN_WINCE(maxSize))
245 {
246 #if defined(__WXWINCE__)
247 // TODO-CE
248 return false;
249 #elif defined(__WIN32__) && !defined(__WXMICROWIN__)
250 DWORD nSize = maxSize;
251 if ( ::GetUserName(buf, &nSize) == 0 )
252 {
253 // actually, it does happen on Win9x if the user didn't log on
254 DWORD res = ::GetEnvironmentVariable(wxT("username"), buf, maxSize);
255 if ( res == 0 )
256 {
257 // not found
258 return false;
259 }
260 }
261
262 return true;
263 #else // __WXMICROWIN__
264 wxChar *user;
265 const wxChar *default_id = wxT("anonymous");
266
267 // Can't assume we have NIS (PC-NFS) or some other ID daemon
268 // So we ...
269 if ( (user = wxGetenv(wxT("USER"))) == NULL &&
270 (user = wxGetenv(wxT("LOGNAME"))) == NULL )
271 {
272 // Use wxWidgets configuration data (comming soon)
273 GetProfileString(WX_SECTION, eUSERID, default_id, buf, maxSize - 1);
274 }
275 else
276 {
277 wxStrncpy(buf, user, maxSize - 1);
278 }
279
280 return *buf ? true : false;
281 #endif
282 }
283
284 // Get user name e.g. Julian Smart
285 bool wxGetUserName(wxChar *buf, int maxSize)
286 {
287 wxCHECK_MSG( buf && ( maxSize > 0 ), false,
288 _T("empty buffer in wxGetUserName") );
289 #if defined(__WXWINCE__)
290 wxLogNull noLog;
291 wxRegKey key(wxRegKey::HKCU, wxT("ControlPanel\\Owner"));
292 if(!key.Open(wxRegKey::Read))
293 return false;
294 wxString name;
295 if(!key.QueryValue(wxT("Owner"),name))
296 return false;
297 wxStrncpy(buf, name.c_str(), maxSize-1);
298 buf[maxSize-1] = _T('\0');
299 return true;
300 #elif defined(USE_NET_API)
301 CHAR szUserName[256];
302 if ( !wxGetUserId(szUserName, WXSIZEOF(szUserName)) )
303 return false;
304
305 // TODO how to get the domain name?
306 CHAR *szDomain = "";
307
308 // the code is based on the MSDN example (also see KB article Q119670)
309 WCHAR wszUserName[256]; // Unicode user name
310 WCHAR wszDomain[256];
311 LPBYTE ComputerName;
312
313 USER_INFO_2 *ui2; // User structure
314
315 // Convert ANSI user name and domain to Unicode
316 MultiByteToWideChar( CP_ACP, 0, szUserName, strlen(szUserName)+1,
317 wszUserName, WXSIZEOF(wszUserName) );
318 MultiByteToWideChar( CP_ACP, 0, szDomain, strlen(szDomain)+1,
319 wszDomain, WXSIZEOF(wszDomain) );
320
321 // Get the computer name of a DC for the domain.
322 if ( NetGetDCName( NULL, wszDomain, &ComputerName ) != NERR_Success )
323 {
324 wxLogError(wxT("Can not find domain controller"));
325
326 goto error;
327 }
328
329 // Look up the user on the DC
330 NET_API_STATUS status = NetUserGetInfo( (LPWSTR)ComputerName,
331 (LPWSTR)&wszUserName,
332 2, // level - we want USER_INFO_2
333 (LPBYTE *) &ui2 );
334 switch ( status )
335 {
336 case NERR_Success:
337 // ok
338 break;
339
340 case NERR_InvalidComputer:
341 wxLogError(wxT("Invalid domain controller name."));
342
343 goto error;
344
345 case NERR_UserNotFound:
346 wxLogError(wxT("Invalid user name '%s'."), szUserName);
347
348 goto error;
349
350 default:
351 wxLogSysError(wxT("Can't get information about user"));
352
353 goto error;
354 }
355
356 // Convert the Unicode full name to ANSI
357 WideCharToMultiByte( CP_ACP, 0, ui2->usri2_full_name, -1,
358 buf, maxSize, NULL, NULL );
359
360 return true;
361
362 error:
363 wxLogError(wxT("Couldn't look up full user name."));
364
365 return false;
366 #else // !USE_NET_API
367 // Could use NIS, MS-Mail or other site specific programs
368 // Use wxWidgets configuration data
369 bool ok = GetProfileString(WX_SECTION, eUSERNAME, wxEmptyString, buf, maxSize - 1) != 0;
370 if ( !ok )
371 {
372 ok = wxGetUserId(buf, maxSize);
373 }
374
375 if ( !ok )
376 {
377 wxStrncpy(buf, wxT("Unknown User"), maxSize);
378 }
379
380 return true;
381 #endif // Win32/16
382 }
383
384 const wxChar* wxGetHomeDir(wxString *pstr)
385 {
386 wxString& strDir = *pstr;
387
388 // first branch is for Cygwin
389 #if defined(__UNIX__) && !defined(__WINE__)
390 const wxChar *szHome = wxGetenv("HOME");
391 if ( szHome == NULL ) {
392 // we're homeless...
393 wxLogWarning(_("can't find user's HOME, using current directory."));
394 strDir = wxT(".");
395 }
396 else
397 strDir = szHome;
398
399 // add a trailing slash if needed
400 if ( strDir.Last() != wxT('/') )
401 strDir << wxT('/');
402
403 #ifdef __CYGWIN__
404 // Cygwin returns unix type path but that does not work well
405 static wxChar windowsPath[MAX_PATH];
406 cygwin_conv_to_full_win32_path(strDir, windowsPath);
407 strDir = windowsPath;
408 #endif
409 #elif defined(__WXWINCE__)
410 strDir = wxT("\\");
411 #else
412 strDir.clear();
413
414 // If we have a valid HOME directory, as is used on many machines that
415 // have unix utilities on them, we should use that.
416 const wxChar *szHome = wxGetenv(wxT("HOME"));
417
418 if ( szHome != NULL )
419 {
420 strDir = szHome;
421 }
422 else // no HOME, try HOMEDRIVE/PATH
423 {
424 szHome = wxGetenv(wxT("HOMEDRIVE"));
425 if ( szHome != NULL )
426 strDir << szHome;
427 szHome = wxGetenv(wxT("HOMEPATH"));
428
429 if ( szHome != NULL )
430 {
431 strDir << szHome;
432
433 // the idea is that under NT these variables have default values
434 // of "%systemdrive%:" and "\\". As we don't want to create our
435 // config files in the root directory of the system drive, we will
436 // create it in our program's dir. However, if the user took care
437 // to set HOMEPATH to something other than "\\", we suppose that he
438 // knows what he is doing and use the supplied value.
439 if ( wxStrcmp(szHome, wxT("\\")) == 0 )
440 strDir.clear();
441 }
442 }
443
444 if ( strDir.empty() )
445 {
446 // If we have a valid USERPROFILE directory, as is the case in
447 // Windows NT, 2000 and XP, we should use that as our home directory.
448 szHome = wxGetenv(wxT("USERPROFILE"));
449
450 if ( szHome != NULL )
451 strDir = szHome;
452 }
453
454 if ( !strDir.empty() )
455 {
456 // sometimes the value of HOME may be "%USERPROFILE%", so reexpand the
457 // value once again, it shouldn't hurt anyhow
458 strDir = wxExpandEnvVars(strDir);
459 }
460 else // fall back to the program directory
461 {
462 // extract the directory component of the program file name
463 wxSplitPath(wxGetFullModuleName(), &strDir, NULL, NULL);
464 }
465 #endif // UNIX/Win
466
467 return strDir.c_str();
468 }
469
470 wxChar *wxGetUserHome(const wxString& WXUNUSED(user))
471 {
472 // VZ: the old code here never worked for user != "" anyhow! Moreover, it
473 // returned sometimes a malloc()'d pointer, sometimes a pointer to a
474 // static buffer and sometimes I don't even know what.
475 static wxString s_home;
476
477 return (wxChar *)wxGetHomeDir(&s_home);
478 }
479
480 bool wxGetDiskSpace(const wxString& WXUNUSED_IN_WINCE(path),
481 wxDiskspaceSize_t *WXUNUSED_IN_WINCE(pTotal),
482 wxDiskspaceSize_t *WXUNUSED_IN_WINCE(pFree))
483 {
484 #ifdef __WXWINCE__
485 // TODO-CE
486 return false;
487 #else
488 if ( path.empty() )
489 return false;
490
491 // old w32api don't have ULARGE_INTEGER
492 #if defined(__WIN32__) && \
493 (!defined(__GNUWIN32__) || wxCHECK_W32API_VERSION( 0, 3 ))
494 // GetDiskFreeSpaceEx() is not available under original Win95, check for
495 // it
496 typedef BOOL (WINAPI *GetDiskFreeSpaceEx_t)(LPCTSTR,
497 PULARGE_INTEGER,
498 PULARGE_INTEGER,
499 PULARGE_INTEGER);
500
501 GetDiskFreeSpaceEx_t
502 pGetDiskFreeSpaceEx = (GetDiskFreeSpaceEx_t)::GetProcAddress
503 (
504 ::GetModuleHandle(_T("kernel32.dll")),
505 #if wxUSE_UNICODE
506 "GetDiskFreeSpaceExW"
507 #else
508 "GetDiskFreeSpaceExA"
509 #endif
510 );
511
512 if ( pGetDiskFreeSpaceEx )
513 {
514 ULARGE_INTEGER bytesFree, bytesTotal;
515
516 // may pass the path as is, GetDiskFreeSpaceEx() is smart enough
517 if ( !pGetDiskFreeSpaceEx(path,
518 &bytesFree,
519 &bytesTotal,
520 NULL) )
521 {
522 wxLogLastError(_T("GetDiskFreeSpaceEx"));
523
524 return false;
525 }
526
527 // ULARGE_INTEGER is a union of a 64 bit value and a struct containing
528 // two 32 bit fields which may be or may be not named - try to make it
529 // compile in all cases
530 #if defined(__BORLANDC__) && !defined(_ANONYMOUS_STRUCT)
531 #define UL(ul) ul.u
532 #else // anon union
533 #define UL(ul) ul
534 #endif
535 if ( pTotal )
536 {
537 #if wxUSE_LONGLONG
538 *pTotal = wxDiskspaceSize_t(UL(bytesTotal).HighPart, UL(bytesTotal).LowPart);
539 #else
540 *pTotal = wxDiskspaceSize_t(UL(bytesTotal).LowPart);
541 #endif
542 }
543
544 if ( pFree )
545 {
546 #if wxUSE_LONGLONG
547 *pFree = wxLongLong(UL(bytesFree).HighPart, UL(bytesFree).LowPart);
548 #else
549 *pFree = wxDiskspaceSize_t(UL(bytesFree).LowPart);
550 #endif
551 }
552 }
553 else
554 #endif // Win32
555 {
556 // there's a problem with drives larger than 2GB, GetDiskFreeSpaceEx()
557 // should be used instead - but if it's not available, fall back on
558 // GetDiskFreeSpace() nevertheless...
559
560 DWORD lSectorsPerCluster,
561 lBytesPerSector,
562 lNumberOfFreeClusters,
563 lTotalNumberOfClusters;
564
565 // FIXME: this is wrong, we should extract the root drive from path
566 // instead, but this is the job for wxFileName...
567 if ( !::GetDiskFreeSpace(path,
568 &lSectorsPerCluster,
569 &lBytesPerSector,
570 &lNumberOfFreeClusters,
571 &lTotalNumberOfClusters) )
572 {
573 wxLogLastError(_T("GetDiskFreeSpace"));
574
575 return false;
576 }
577
578 wxDiskspaceSize_t lBytesPerCluster = (wxDiskspaceSize_t) lSectorsPerCluster;
579 lBytesPerCluster *= lBytesPerSector;
580
581 if ( pTotal )
582 {
583 *pTotal = lBytesPerCluster;
584 *pTotal *= lTotalNumberOfClusters;
585 }
586
587 if ( pFree )
588 {
589 *pFree = lBytesPerCluster;
590 *pFree *= lNumberOfFreeClusters;
591 }
592 }
593
594 return true;
595 #endif
596 // __WXWINCE__
597 }
598
599 // ----------------------------------------------------------------------------
600 // env vars
601 // ----------------------------------------------------------------------------
602
603 bool wxGetEnv(const wxString& WXUNUSED_IN_WINCE(var),
604 wxString *WXUNUSED_IN_WINCE(value))
605 {
606 #ifdef __WXWINCE__
607 // no environment variables under CE
608 return false;
609 #else // Win32
610 // first get the size of the buffer
611 DWORD dwRet = ::GetEnvironmentVariable(var, NULL, 0);
612 if ( !dwRet )
613 {
614 // this means that there is no such variable
615 return false;
616 }
617
618 if ( value )
619 {
620 (void)::GetEnvironmentVariable(var, wxStringBuffer(*value, dwRet),
621 dwRet);
622 }
623
624 return true;
625 #endif // WinCE/32
626 }
627
628 bool wxSetEnv(const wxString& WXUNUSED_IN_WINCE(var),
629 const wxChar *WXUNUSED_IN_WINCE(value))
630 {
631 // some compilers have putenv() or _putenv() or _wputenv() but it's better
632 // to always use Win32 function directly instead of dealing with them
633 #ifdef __WXWINCE__
634 // no environment variables under CE
635 return false;
636 #else
637 if ( !::SetEnvironmentVariable(var, value) )
638 {
639 wxLogLastError(_T("SetEnvironmentVariable"));
640
641 return false;
642 }
643
644 return true;
645 #endif
646 }
647
648 // ----------------------------------------------------------------------------
649 // process management
650 // ----------------------------------------------------------------------------
651
652 // structure used to pass parameters from wxKill() to wxEnumFindByPidProc()
653 struct wxFindByPidParams
654 {
655 wxFindByPidParams() { hwnd = 0; pid = 0; }
656
657 // the HWND used to return the result
658 HWND hwnd;
659
660 // the PID we're looking from
661 DWORD pid;
662
663 DECLARE_NO_COPY_CLASS(wxFindByPidParams)
664 };
665
666 // wxKill helper: EnumWindows() callback which is used to find the first (top
667 // level) window belonging to the given process
668 BOOL CALLBACK wxEnumFindByPidProc(HWND hwnd, LPARAM lParam)
669 {
670 DWORD pid;
671 (void)::GetWindowThreadProcessId(hwnd, &pid);
672
673 wxFindByPidParams *params = (wxFindByPidParams *)lParam;
674 if ( pid == params->pid )
675 {
676 // remember the window we found
677 params->hwnd = hwnd;
678
679 // return FALSE to stop the enumeration
680 return FALSE;
681 }
682
683 // continue enumeration
684 return TRUE;
685 }
686
687 int wxKillAllChildren(long pid, wxSignal sig, wxKillError *krc);
688
689 int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags)
690 {
691 if (flags & wxKILL_CHILDREN)
692 wxKillAllChildren(pid, sig, krc);
693
694 // get the process handle to operate on
695 HANDLE hProcess = ::OpenProcess(SYNCHRONIZE |
696 PROCESS_TERMINATE |
697 PROCESS_QUERY_INFORMATION,
698 FALSE, // not inheritable
699 (DWORD)pid);
700 if ( hProcess == NULL )
701 {
702 if ( krc )
703 {
704 // recognize wxKILL_ACCESS_DENIED as special because this doesn't
705 // mean that the process doesn't exist and this is important for
706 // wxProcess::Exists()
707 *krc = ::GetLastError() == ERROR_ACCESS_DENIED
708 ? wxKILL_ACCESS_DENIED
709 : wxKILL_NO_PROCESS;
710 }
711
712 return -1;
713 }
714
715 wxON_BLOCK_EXIT1(::CloseHandle, hProcess);
716
717 bool ok = true;
718 switch ( sig )
719 {
720 case wxSIGKILL:
721 // kill the process forcefully returning -1 as error code
722 if ( !::TerminateProcess(hProcess, (UINT)-1) )
723 {
724 wxLogSysError(_("Failed to kill process %d"), pid);
725
726 if ( krc )
727 {
728 // this is not supposed to happen if we could open the
729 // process
730 *krc = wxKILL_ERROR;
731 }
732
733 ok = false;
734 }
735 break;
736
737 case wxSIGNONE:
738 // do nothing, we just want to test for process existence
739 if ( krc )
740 *krc = wxKILL_OK;
741 return 0;
742
743 default:
744 // any other signal means "terminate"
745 {
746 wxFindByPidParams params;
747 params.pid = (DWORD)pid;
748
749 // EnumWindows() has nice semantics: it returns 0 if it found
750 // something or if an error occurred and non zero if it
751 // enumerated all the window
752 if ( !::EnumWindows(wxEnumFindByPidProc, (LPARAM)&params) )
753 {
754 // did we find any window?
755 if ( params.hwnd )
756 {
757 // tell the app to close
758 //
759 // NB: this is the harshest way, the app won't have an
760 // opportunity to save any files, for example, but
761 // this is probably what we want here. If not we
762 // can also use SendMesageTimeout(WM_CLOSE)
763 if ( !::PostMessage(params.hwnd, WM_QUIT, 0, 0) )
764 {
765 wxLogLastError(_T("PostMessage(WM_QUIT)"));
766 }
767 }
768 else // it was an error then
769 {
770 wxLogLastError(_T("EnumWindows"));
771
772 ok = false;
773 }
774 }
775 else // no windows for this PID
776 {
777 if ( krc )
778 *krc = wxKILL_ERROR;
779
780 ok = false;
781 }
782 }
783 }
784
785 // the return code
786 DWORD rc wxDUMMY_INITIALIZE(0);
787 if ( ok )
788 {
789 // as we wait for a short time, we can use just WaitForSingleObject()
790 // and not MsgWaitForMultipleObjects()
791 switch ( ::WaitForSingleObject(hProcess, 500 /* msec */) )
792 {
793 case WAIT_OBJECT_0:
794 // process terminated
795 if ( !::GetExitCodeProcess(hProcess, &rc) )
796 {
797 wxLogLastError(_T("GetExitCodeProcess"));
798 }
799 break;
800
801 default:
802 wxFAIL_MSG( _T("unexpected WaitForSingleObject() return") );
803 // fall through
804
805 case WAIT_FAILED:
806 wxLogLastError(_T("WaitForSingleObject"));
807 // fall through
808
809 case WAIT_TIMEOUT:
810 if ( krc )
811 *krc = wxKILL_ERROR;
812
813 rc = STILL_ACTIVE;
814 break;
815 }
816 }
817
818
819 // the return code is the same as from Unix kill(): 0 if killed
820 // successfully or -1 on error
821 if ( !ok || rc == STILL_ACTIVE )
822 return -1;
823
824 if ( krc )
825 *krc = wxKILL_OK;
826
827 return 0;
828 }
829
830 typedef HANDLE (WINAPI *CreateToolhelp32Snapshot_t)(DWORD,DWORD);
831 typedef BOOL (WINAPI *Process32_t)(HANDLE,LPPROCESSENTRY32);
832
833 CreateToolhelp32Snapshot_t lpfCreateToolhelp32Snapshot;
834 Process32_t lpfProcess32First, lpfProcess32Next;
835
836 static void InitToolHelp32()
837 {
838 static bool s_initToolHelpDone = false;
839
840 if (s_initToolHelpDone)
841 return;
842
843 s_initToolHelpDone = true;
844
845 lpfCreateToolhelp32Snapshot = NULL;
846 lpfProcess32First = NULL;
847 lpfProcess32Next = NULL;
848
849 #if wxUSE_DYNLIB_CLASS
850
851 wxDynamicLibrary dllKernel(_T("kernel32.dll"), wxDL_VERBATIM);
852
853 // Get procedure addresses.
854 // We are linking to these functions of Kernel32
855 // explicitly, because otherwise a module using
856 // this code would fail to load under Windows NT,
857 // which does not have the Toolhelp32
858 // functions in the Kernel 32.
859 lpfCreateToolhelp32Snapshot =
860 (CreateToolhelp32Snapshot_t)dllKernel.RawGetSymbol(_T("CreateToolhelp32Snapshot"));
861
862 lpfProcess32First =
863 (Process32_t)dllKernel.RawGetSymbol(_T("Process32First"));
864
865 lpfProcess32Next =
866 (Process32_t)dllKernel.RawGetSymbol(_T("Process32Next"));
867
868 #endif // wxUSE_DYNLIB_CLASS
869 }
870
871 // By John Skiff
872 int wxKillAllChildren(long pid, wxSignal sig, wxKillError *krc)
873 {
874 InitToolHelp32();
875
876 if (krc)
877 *krc = wxKILL_OK;
878
879 // If not implemented for this platform (e.g. NT 4.0), silently ignore
880 if (!lpfCreateToolhelp32Snapshot || !lpfProcess32First || !lpfProcess32Next)
881 return 0;
882
883 // Take a snapshot of all processes in the system.
884 HANDLE hProcessSnap = lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
885 if (hProcessSnap == INVALID_HANDLE_VALUE) {
886 if (krc)
887 *krc = wxKILL_ERROR;
888 return -1;
889 }
890
891 //Fill in the size of the structure before using it.
892 PROCESSENTRY32 pe;
893 wxZeroMemory(pe);
894 pe.dwSize = sizeof(PROCESSENTRY32);
895
896 // Walk the snapshot of the processes, and for each process,
897 // kill it if its parent is pid.
898 if (!lpfProcess32First(hProcessSnap, &pe)) {
899 // Can't get first process.
900 if (krc)
901 *krc = wxKILL_ERROR;
902 CloseHandle (hProcessSnap);
903 return -1;
904 }
905
906 do {
907 if (pe.th32ParentProcessID == (DWORD) pid) {
908 if (wxKill(pe.th32ProcessID, sig, krc))
909 return -1;
910 }
911 } while (lpfProcess32Next (hProcessSnap, &pe));
912
913
914 return 0;
915 }
916
917 // Execute a program in an Interactive Shell
918 bool wxShell(const wxString& command)
919 {
920 wxString cmd;
921
922 #ifdef __WXWINCE__
923 cmd = command;
924 #else
925 wxChar *shell = wxGetenv(wxT("COMSPEC"));
926 if ( !shell )
927 shell = (wxChar*) wxT("\\COMMAND.COM");
928
929 if ( !command )
930 {
931 // just the shell
932 cmd = shell;
933 }
934 else
935 {
936 // pass the command to execute to the command processor
937 cmd.Printf(wxT("%s /c %s"), shell, command.c_str());
938 }
939 #endif
940
941 return wxExecute(cmd, wxEXEC_SYNC) == 0;
942 }
943
944 // Shutdown or reboot the PC
945 bool wxShutdown(wxShutdownFlags WXUNUSED_IN_WINCE(wFlags))
946 {
947 #ifdef __WXWINCE__
948 // TODO-CE
949 return false;
950 #elif defined(__WIN32__)
951 bool bOK = true;
952
953 if ( wxGetOsVersion(NULL, NULL) == wxOS_WINDOWS_NT ) // if is NT or 2K
954 {
955 // Get a token for this process.
956 HANDLE hToken;
957 bOK = ::OpenProcessToken(GetCurrentProcess(),
958 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
959 &hToken) != 0;
960 if ( bOK )
961 {
962 TOKEN_PRIVILEGES tkp;
963
964 // Get the LUID for the shutdown privilege.
965 ::LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
966 &tkp.Privileges[0].Luid);
967
968 tkp.PrivilegeCount = 1; // one privilege to set
969 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
970
971 // Get the shutdown privilege for this process.
972 ::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
973 (PTOKEN_PRIVILEGES)NULL, 0);
974
975 // Cannot test the return value of AdjustTokenPrivileges.
976 bOK = ::GetLastError() == ERROR_SUCCESS;
977 }
978 }
979
980 if ( bOK )
981 {
982 UINT flags = EWX_SHUTDOWN | EWX_FORCE;
983 switch ( wFlags )
984 {
985 case wxSHUTDOWN_POWEROFF:
986 flags |= EWX_POWEROFF;
987 break;
988
989 case wxSHUTDOWN_REBOOT:
990 flags |= EWX_REBOOT;
991 break;
992
993 default:
994 wxFAIL_MSG( _T("unknown wxShutdown() flag") );
995 return false;
996 }
997
998 bOK = ::ExitWindowsEx(flags, 0) != 0;
999 }
1000
1001 return bOK;
1002 #endif // Win32/16
1003 }
1004
1005 // ----------------------------------------------------------------------------
1006 // misc
1007 // ----------------------------------------------------------------------------
1008
1009 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
1010 wxMemorySize wxGetFreeMemory()
1011 {
1012 #if defined(__WIN64__)
1013 MEMORYSTATUSEX memStatex;
1014 memStatex.dwLength = sizeof (memStatex);
1015 ::GlobalMemoryStatusEx (&memStatex);
1016 return (wxMemorySize)memStatex.ullAvailPhys;
1017 #else /* if defined(__WIN32__) */
1018 MEMORYSTATUS memStatus;
1019 memStatus.dwLength = sizeof(MEMORYSTATUS);
1020 ::GlobalMemoryStatus(&memStatus);
1021 return (wxMemorySize)memStatus.dwAvailPhys;
1022 #endif
1023 }
1024
1025 unsigned long wxGetProcessId()
1026 {
1027 return ::GetCurrentProcessId();
1028 }
1029
1030 // Emit a beeeeeep
1031 void wxBell()
1032 {
1033 ::MessageBeep((UINT)-1); // default sound
1034 }
1035
1036 bool wxIsDebuggerRunning()
1037 {
1038 #if wxUSE_DYNLIB_CLASS
1039 // IsDebuggerPresent() is not available under Win95, so load it dynamically
1040 wxDynamicLibrary dll(_T("kernel32.dll"), wxDL_VERBATIM);
1041
1042 typedef BOOL (WINAPI *IsDebuggerPresent_t)();
1043 if ( !dll.HasSymbol(_T("IsDebuggerPresent")) )
1044 {
1045 // no way to know, assume no
1046 return false;
1047 }
1048
1049 return (*(IsDebuggerPresent_t)dll.GetSymbol(_T("IsDebuggerPresent")))() != 0;
1050 #else
1051 return false;
1052 #endif
1053 }
1054
1055 // ----------------------------------------------------------------------------
1056 // OS version
1057 // ----------------------------------------------------------------------------
1058
1059 wxString wxGetOsDescription()
1060 {
1061 wxString str;
1062
1063 OSVERSIONINFO info;
1064 wxZeroMemory(info);
1065
1066 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1067 if ( ::GetVersionEx(&info) )
1068 {
1069 switch ( info.dwPlatformId )
1070 {
1071 #ifdef VER_PLATFORM_WIN32_CE
1072 case VER_PLATFORM_WIN32_CE:
1073 str.Printf(_("Windows CE (%d.%d)"),
1074 info.dwMajorVersion,
1075 info.dwMinorVersion);
1076 break;
1077 #endif
1078 case VER_PLATFORM_WIN32s:
1079 str = _("Win32s on Windows 3.1");
1080 break;
1081
1082 case VER_PLATFORM_WIN32_WINDOWS:
1083 switch (info.dwMinorVersion)
1084 {
1085 case 0:
1086 if ( info.szCSDVersion[1] == 'B' ||
1087 info.szCSDVersion[1] == 'C' )
1088 {
1089 str = _("Windows 95 OSR2");
1090 }
1091 else
1092 {
1093 str = _("Windows 95");
1094 }
1095 break;
1096 case 10:
1097 if ( info.szCSDVersion[1] == 'B' ||
1098 info.szCSDVersion[1] == 'C' )
1099 {
1100 str = _("Windows 98 SE");
1101 }
1102 else
1103 {
1104 str = _("Windows 98");
1105 }
1106 break;
1107 case 90:
1108 str = _("Windows ME");
1109 break;
1110 default:
1111 str.Printf(_("Windows 9x (%d.%d)"),
1112 info.dwMajorVersion,
1113 info.dwMinorVersion);
1114 break;
1115 }
1116 if ( !wxIsEmpty(info.szCSDVersion) )
1117 {
1118 str << _T(" (") << info.szCSDVersion << _T(')');
1119 }
1120 break;
1121
1122 case VER_PLATFORM_WIN32_NT:
1123 if ( info.dwMajorVersion == 5 )
1124 {
1125 switch ( info.dwMinorVersion )
1126 {
1127 case 0:
1128 str.Printf(_("Windows 2000 (build %lu"),
1129 info.dwBuildNumber);
1130 break;
1131 case 1:
1132 str.Printf(_("Windows XP (build %lu"),
1133 info.dwBuildNumber);
1134 break;
1135 case 2:
1136 str.Printf(_("Windows Server 2003 (build %lu"),
1137 info.dwBuildNumber);
1138 break;
1139 }
1140 }
1141 if ( str.empty() )
1142 {
1143 str.Printf(_("Windows NT %lu.%lu (build %lu"),
1144 info.dwMajorVersion,
1145 info.dwMinorVersion,
1146 info.dwBuildNumber);
1147 }
1148 if ( !wxIsEmpty(info.szCSDVersion) )
1149 {
1150 str << _T(", ") << info.szCSDVersion;
1151 }
1152 str << _T(')');
1153 break;
1154 }
1155 }
1156 else
1157 {
1158 wxFAIL_MSG( _T("GetVersionEx() failed") ); // should never happen
1159 }
1160
1161 return str;
1162 }
1163
1164 bool wxIsPlatform64Bit()
1165 {
1166 #if defined(_WIN64)
1167 return true; // 64-bit programs run only on Win64
1168 #else // Win32
1169 // 32-bit programs run on both 32-bit and 64-bit Windows so check
1170 typedef BOOL (WINAPI *IsWow64Process_t)(HANDLE, BOOL *);
1171
1172 wxDynamicLibrary dllKernel32(_T("kernel32.dll"));
1173 IsWow64Process_t pfnIsWow64Process =
1174 (IsWow64Process_t)dllKernel32.RawGetSymbol(_T("IsWow64Process"));
1175
1176 BOOL wow64 = FALSE;
1177 if ( pfnIsWow64Process )
1178 {
1179 pfnIsWow64Process(::GetCurrentProcess(), &wow64);
1180 }
1181 //else: running under a system without Win64 support
1182
1183 return wow64 != FALSE;
1184 #endif // Win64/Win32
1185 }
1186
1187 wxOperatingSystemId wxGetOsVersion(int *verMaj, int *verMin)
1188 {
1189 OSVERSIONINFO info;
1190 wxZeroMemory(info);
1191
1192 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1193 if ( ::GetVersionEx(&info) )
1194 {
1195 if (verMaj) *verMaj = info.dwMajorVersion;
1196 if (verMin) *verMin = info.dwMinorVersion;
1197 }
1198
1199 #if defined( __WXWINCE__ )
1200 return wxOS_WINDOWS_CE;
1201 #elif defined( __WXMICROWIN__ )
1202 return wxOS_WINDOWS_MICRO;
1203 #else
1204 switch ( info.dwPlatformId )
1205 {
1206 case VER_PLATFORM_WIN32_NT:
1207 return wxOS_WINDOWS_NT;
1208
1209 case VER_PLATFORM_WIN32_WINDOWS:
1210 return wxOS_WINDOWS_9X;
1211 }
1212
1213 return wxOS_UNKNOWN;
1214 #endif
1215 }
1216
1217 wxWinVersion wxGetWinVersion()
1218 {
1219 int verMaj,
1220 verMin;
1221 switch ( wxGetOsVersion(&verMaj, &verMin) )
1222 {
1223 case wxOS_WINDOWS_9X:
1224 if ( verMaj == 4 )
1225 {
1226 switch ( verMin )
1227 {
1228 case 0:
1229 return wxWinVersion_95;
1230
1231 case 10:
1232 return wxWinVersion_98;
1233
1234 case 90:
1235 return wxWinVersion_ME;
1236 }
1237 }
1238 break;
1239
1240 case wxOS_WINDOWS_NT:
1241 switch ( verMaj )
1242 {
1243 case 3:
1244 return wxWinVersion_NT3;
1245
1246 case 4:
1247 return wxWinVersion_NT4;
1248
1249 case 5:
1250 switch ( verMin )
1251 {
1252 case 0:
1253 return wxWinVersion_2000;
1254
1255 case 1:
1256 return wxWinVersion_XP;
1257
1258 case 2:
1259 return wxWinVersion_2003;
1260 }
1261 break;
1262
1263 case 6:
1264 return wxWinVersion_NT6;
1265 }
1266 break;
1267
1268 default:
1269 // Do nothing just to silence GCC warning
1270 break;
1271 }
1272
1273 return wxWinVersion_Unknown;
1274 }
1275
1276 // ----------------------------------------------------------------------------
1277 // sleep functions
1278 // ----------------------------------------------------------------------------
1279
1280 void wxMilliSleep(unsigned long milliseconds)
1281 {
1282 ::Sleep(milliseconds);
1283 }
1284
1285 void wxMicroSleep(unsigned long microseconds)
1286 {
1287 wxMilliSleep(microseconds/1000);
1288 }
1289
1290 void wxSleep(int nSecs)
1291 {
1292 wxMilliSleep(1000*nSecs);
1293 }
1294
1295 // ----------------------------------------------------------------------------
1296 // font encoding <-> Win32 codepage conversion functions
1297 // ----------------------------------------------------------------------------
1298
1299 extern WXDLLIMPEXP_BASE long wxEncodingToCharset(wxFontEncoding encoding)
1300 {
1301 switch ( encoding )
1302 {
1303 // although this function is supposed to return an exact match, do do
1304 // some mappings here for the most common case of "standard" encoding
1305 case wxFONTENCODING_SYSTEM:
1306 return DEFAULT_CHARSET;
1307
1308 case wxFONTENCODING_ISO8859_1:
1309 case wxFONTENCODING_ISO8859_15:
1310 case wxFONTENCODING_CP1252:
1311 return ANSI_CHARSET;
1312
1313 #if !defined(__WXMICROWIN__)
1314 // The following four fonts are multi-byte charsets
1315 case wxFONTENCODING_CP932:
1316 return SHIFTJIS_CHARSET;
1317
1318 case wxFONTENCODING_CP936:
1319 return GB2312_CHARSET;
1320
1321 #ifndef __WXWINCE__
1322 case wxFONTENCODING_CP949:
1323 return HANGUL_CHARSET;
1324 #endif
1325
1326 case wxFONTENCODING_CP950:
1327 return CHINESEBIG5_CHARSET;
1328
1329 // The rest are single byte encodings
1330 case wxFONTENCODING_CP1250:
1331 return EASTEUROPE_CHARSET;
1332
1333 case wxFONTENCODING_CP1251:
1334 return RUSSIAN_CHARSET;
1335
1336 case wxFONTENCODING_CP1253:
1337 return GREEK_CHARSET;
1338
1339 case wxFONTENCODING_CP1254:
1340 return TURKISH_CHARSET;
1341
1342 case wxFONTENCODING_CP1255:
1343 return HEBREW_CHARSET;
1344
1345 case wxFONTENCODING_CP1256:
1346 return ARABIC_CHARSET;
1347
1348 case wxFONTENCODING_CP1257:
1349 return BALTIC_CHARSET;
1350
1351 case wxFONTENCODING_CP874:
1352 return THAI_CHARSET;
1353 #endif // !__WXMICROWIN__
1354
1355 case wxFONTENCODING_CP437:
1356 return OEM_CHARSET;
1357
1358 default:
1359 // no way to translate this encoding into a Windows charset
1360 return -1;
1361 }
1362 }
1363
1364 // we have 2 versions of wxCharsetToCodepage(): the old one which directly
1365 // looks up the vlaues in the registry and the new one which is more
1366 // politically correct and has more chances to work on other Windows versions
1367 // as well but the old version is still needed for !wxUSE_FONTMAP case
1368 #if wxUSE_FONTMAP
1369
1370 #include "wx/fontmap.h"
1371
1372 extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding)
1373 {
1374 // There don't seem to be symbolic names for
1375 // these under Windows so I just copied the
1376 // values from MSDN.
1377
1378 unsigned int ret;
1379
1380 switch (encoding)
1381 {
1382 case wxFONTENCODING_ISO8859_1: ret = 28591; break;
1383 case wxFONTENCODING_ISO8859_2: ret = 28592; break;
1384 case wxFONTENCODING_ISO8859_3: ret = 28593; break;
1385 case wxFONTENCODING_ISO8859_4: ret = 28594; break;
1386 case wxFONTENCODING_ISO8859_5: ret = 28595; break;
1387 case wxFONTENCODING_ISO8859_6: ret = 28596; break;
1388 case wxFONTENCODING_ISO8859_7: ret = 28597; break;
1389 case wxFONTENCODING_ISO8859_8: ret = 28598; break;
1390 case wxFONTENCODING_ISO8859_9: ret = 28599; break;
1391 case wxFONTENCODING_ISO8859_10: ret = 28600; break;
1392 case wxFONTENCODING_ISO8859_11: ret = 874; break;
1393 // case wxFONTENCODING_ISO8859_12, // doesn't exist currently, but put it
1394 case wxFONTENCODING_ISO8859_13: ret = 28603; break;
1395 // case wxFONTENCODING_ISO8859_14: ret = 28604; break; // no correspondence on Windows
1396 case wxFONTENCODING_ISO8859_15: ret = 28605; break;
1397 case wxFONTENCODING_KOI8: ret = 20866; break;
1398 case wxFONTENCODING_KOI8_U: ret = 21866; break;
1399 case wxFONTENCODING_CP437: ret = 437; break;
1400 case wxFONTENCODING_CP850: ret = 850; break;
1401 case wxFONTENCODING_CP852: ret = 852; break;
1402 case wxFONTENCODING_CP855: ret = 855; break;
1403 case wxFONTENCODING_CP866: ret = 866; break;
1404 case wxFONTENCODING_CP874: ret = 874; break;
1405 case wxFONTENCODING_CP932: ret = 932; break;
1406 case wxFONTENCODING_CP936: ret = 936; break;
1407 case wxFONTENCODING_CP949: ret = 949; break;
1408 case wxFONTENCODING_CP950: ret = 950; break;
1409 case wxFONTENCODING_CP1250: ret = 1250; break;
1410 case wxFONTENCODING_CP1251: ret = 1251; break;
1411 case wxFONTENCODING_CP1252: ret = 1252; break;
1412 case wxFONTENCODING_CP1253: ret = 1253; break;
1413 case wxFONTENCODING_CP1254: ret = 1254; break;
1414 case wxFONTENCODING_CP1255: ret = 1255; break;
1415 case wxFONTENCODING_CP1256: ret = 1256; break;
1416 case wxFONTENCODING_CP1257: ret = 1257; break;
1417 case wxFONTENCODING_EUC_JP: ret = 20932; break;
1418 case wxFONTENCODING_MACROMAN: ret = 10000; break;
1419 case wxFONTENCODING_MACJAPANESE: ret = 10001; break;
1420 case wxFONTENCODING_MACCHINESETRAD: ret = 10002; break;
1421 case wxFONTENCODING_MACKOREAN: ret = 10003; break;
1422 case wxFONTENCODING_MACARABIC: ret = 10004; break;
1423 case wxFONTENCODING_MACHEBREW: ret = 10005; break;
1424 case wxFONTENCODING_MACGREEK: ret = 10006; break;
1425 case wxFONTENCODING_MACCYRILLIC: ret = 10007; break;
1426 case wxFONTENCODING_MACTHAI: ret = 10021; break;
1427 case wxFONTENCODING_MACCHINESESIMP: ret = 10008; break;
1428 case wxFONTENCODING_MACCENTRALEUR: ret = 10029; break;
1429 case wxFONTENCODING_MACCROATIAN: ret = 10082; break;
1430 case wxFONTENCODING_MACICELANDIC: ret = 10079; break;
1431 case wxFONTENCODING_MACROMANIAN: ret = 10009; break;
1432 case wxFONTENCODING_UTF7: ret = 65000; break;
1433 case wxFONTENCODING_UTF8: ret = 65001; break;
1434 default: return -1;
1435 }
1436
1437 if (::IsValidCodePage(ret) == 0)
1438 return -1;
1439
1440 CPINFO info;
1441 if (::GetCPInfo(ret, &info) == 0)
1442 return -1;
1443
1444 return (long) ret;
1445 }
1446
1447 extern long wxCharsetToCodepage(const wxChar *name)
1448 {
1449 // first get the font encoding for this charset
1450 if ( !name )
1451 return -1;
1452
1453 wxFontEncoding enc = wxFontMapperBase::Get()->CharsetToEncoding(name, false);
1454 if ( enc == wxFONTENCODING_SYSTEM )
1455 return -1;
1456
1457 // the use the helper function
1458 return wxEncodingToCodepage(enc);
1459 }
1460
1461 #else // !wxUSE_FONTMAP
1462
1463 #include "wx/msw/registry.h"
1464
1465 // this should work if Internet Exploiter is installed
1466 extern long wxCharsetToCodepage(const wxChar *name)
1467 {
1468 if (!name)
1469 return GetACP();
1470
1471 long CP = -1;
1472
1473 wxString path(wxT("MIME\\Database\\Charset\\"));
1474 wxString cn(name);
1475
1476 // follow the alias loop
1477 for ( ;; )
1478 {
1479 wxRegKey key(wxRegKey::HKCR, path + cn);
1480
1481 if (!key.Exists())
1482 break;
1483
1484 // two cases: either there's an AliasForCharset string,
1485 // or there are Codepage and InternetEncoding dwords.
1486 // The InternetEncoding gives us the actual encoding,
1487 // the Codepage just says which Windows character set to
1488 // use when displaying the data.
1489 if (key.HasValue(wxT("InternetEncoding")) &&
1490 key.QueryValue(wxT("InternetEncoding"), &CP))
1491 break;
1492
1493 // no encoding, see if it's an alias
1494 if (!key.HasValue(wxT("AliasForCharset")) ||
1495 !key.QueryValue(wxT("AliasForCharset"), cn))
1496 break;
1497 }
1498
1499 return CP;
1500 }
1501
1502 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
1503
1504 /*
1505 Creates a hidden window with supplied window proc registering the class for
1506 it if necesssary (i.e. the first time only). Caller is responsible for
1507 destroying the window and unregistering the class (note that this must be
1508 done because wxWidgets may be used as a DLL and so may be loaded/unloaded
1509 multiple times into/from the same process so we cna't rely on automatic
1510 Windows class unregistration).
1511
1512 pclassname is a pointer to a caller stored classname, which must initially be
1513 NULL. classname is the desired wndclass classname. If function successfully
1514 registers the class, pclassname will be set to classname.
1515 */
1516 extern "C" WXDLLIMPEXP_BASE HWND
1517 wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc)
1518 {
1519 wxCHECK_MSG( classname && pclassname && wndproc, NULL,
1520 _T("NULL parameter in wxCreateHiddenWindow") );
1521
1522 // register the class fi we need to first
1523 if ( *pclassname == NULL )
1524 {
1525 WNDCLASS wndclass;
1526 wxZeroMemory(wndclass);
1527
1528 wndclass.lpfnWndProc = wndproc;
1529 wndclass.hInstance = wxGetInstance();
1530 wndclass.lpszClassName = classname;
1531
1532 if ( !::RegisterClass(&wndclass) )
1533 {
1534 wxLogLastError(wxT("RegisterClass() in wxCreateHiddenWindow"));
1535
1536 return NULL;
1537 }
1538
1539 *pclassname = classname;
1540 }
1541
1542 // next create the window
1543 HWND hwnd = ::CreateWindow
1544 (
1545 *pclassname,
1546 NULL,
1547 0, 0, 0, 0,
1548 0,
1549 (HWND) NULL,
1550 (HMENU)NULL,
1551 wxGetInstance(),
1552 (LPVOID) NULL
1553 );
1554
1555 if ( !hwnd )
1556 {
1557 wxLogLastError(wxT("CreateWindow() in wxCreateHiddenWindow"));
1558 }
1559
1560 return hwnd;
1561 }