1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/msw/utils.cpp 
   3 // Purpose:     Various utilities 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  35 #include "wx/msw/registry.h" 
  36 #include "wx/apptrait.h" 
  37 #include "wx/dynlib.h" 
  38 #include "wx/dynload.h" 
  39 #include "wx/scopeguard.h" 
  41 #include "wx/confbase.h"        // for wxExpandEnvVars() 
  43 #include "wx/msw/private.h"     // includes <windows.h> 
  44 #include "wx/msw/missing.h"     // CHARSET_HANGUL 
  46 #if defined(__CYGWIN__) 
  47     //CYGWIN gives annoying warning about runtime stuff if we don't do this 
  48 #   define USE_SYS_TYPES_FD_SET 
  49 #   include <sys/types.h> 
  52 // Doesn't work with Cygwin at present 
  53 #if wxUSE_SOCKETS && (defined(__GNUWIN32_OLD__) || defined(__WXWINCE__) || defined(__CYGWIN32__)) 
  54     // apparently we need to include winsock.h to get WSADATA and other stuff 
  55     // used in wxGetFullHostName() with the old mingw32 versions 
  59 #if !defined(__GNUWIN32__) && !defined(__SALFORDC__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
  67 #if defined(__CYGWIN__) 
  68     #include <sys/unistd.h> 
  70     #include <sys/cygwin.h> // for cygwin_conv_to_full_win32_path() 
  73 #ifdef __BORLANDC__ // Please someone tell me which version of Borland needs 
  74                     // this (3.1 I believe) and how to test for it. 
  75                     // If this works for Borland 4.0 as well, then no worries. 
  79 // VZ: there is some code using NetXXX() functions to get the full user name: 
  80 //     I don't think it's a good idea because they don't work under Win95 and 
  81 //     seem to return the same as wxGetUserId() under NT. If you really want 
  82 //     to use them, just #define USE_NET_API 
  89 #if defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
 100     #if !(defined(_MSC_VER) && (_MSC_VER > 800)) 
 105 // For wxKillAllChildren 
 106 #include <tlhelp32.h> 
 108 // ---------------------------------------------------------------------------- 
 110 // ---------------------------------------------------------------------------- 
 112 // In the WIN.INI file 
 113 #if (!defined(USE_NET_API) && !defined(__WXWINCE__)) || defined(__WXMICROWIN__) 
 114 static const wxChar WX_SECTION
[] = wxT("wxWindows"); 
 117 #if (!defined(USE_NET_API) && !defined(__WXWINCE__)) 
 118 static const wxChar eUSERNAME
[]  = wxT("UserName"); 
 121 // ============================================================================ 
 123 // ============================================================================ 
 125 // ---------------------------------------------------------------------------- 
 126 // get host name and related 
 127 // ---------------------------------------------------------------------------- 
 129 // Get hostname only (without domain name) 
 130 bool wxGetHostName(wxChar 
*WXUNUSED_IN_WINCE(buf
), 
 131                    int WXUNUSED_IN_WINCE(maxSize
)) 
 133 #if defined(__WXWINCE__) 
 136 #elif defined(__WIN32__) && !defined(__WXMICROWIN__) 
 137     DWORD nSize 
= maxSize
; 
 138     if ( !::GetComputerName(buf
, &nSize
) ) 
 140         wxLogLastError(wxT("GetComputerName")); 
 148     const wxChar 
*default_host 
= wxT("noname"); 
 150     if ((sysname 
= wxGetenv(wxT("SYSTEM_NAME"))) == NULL
) { 
 151         GetProfileString(WX_SECTION
, eHOSTNAME
, default_host
, buf
, maxSize 
- 1); 
 153         wxStrncpy(buf
, sysname
, maxSize 
- 1); 
 154     buf
[maxSize
] = wxT('\0'); 
 155     return *buf 
? true : false; 
 159 // get full hostname (with domain name if possible) 
 160 bool wxGetFullHostName(wxChar 
*buf
, int maxSize
) 
 162 #if !defined( __WXMICROWIN__) && wxUSE_DYNAMIC_LOADER && wxUSE_SOCKETS 
 163     // TODO should use GetComputerNameEx() when available 
 165     // we don't want to always link with Winsock DLL as we might not use it at 
 166     // all, so load it dynamically here if needed (and don't complain if it is 
 167     // missing, we handle this) 
 170     wxDynamicLibrary 
dllWinsock(_T("ws2_32.dll"), wxDL_VERBATIM
); 
 171     if ( dllWinsock
.IsLoaded() ) 
 173         typedef int (PASCAL 
*WSAStartup_t
)(WORD
, WSADATA 
*); 
 174         typedef int (PASCAL 
*gethostname_t
)(char *, int); 
 175         typedef hostent
* (PASCAL 
*gethostbyname_t
)(const char *); 
 176         typedef hostent
* (PASCAL 
*gethostbyaddr_t
)(const char *, int , int); 
 177         typedef int (PASCAL 
*WSACleanup_t
)(void); 
 179         #define LOAD_WINSOCK_FUNC(func)                                       \ 
 181                 pfn ## func = (func ## _t)dllWinsock.GetSymbol(_T(#func)) 
 183         LOAD_WINSOCK_FUNC(WSAStartup
); 
 186         if ( pfnWSAStartup 
&& pfnWSAStartup(MAKEWORD(1, 1), &wsa
) == 0 ) 
 188             LOAD_WINSOCK_FUNC(gethostname
); 
 191             if ( pfngethostname 
) 
 194                 if ( pfngethostname(bufA
, WXSIZEOF(bufA
)) == 0 ) 
 196                     // gethostname() won't usually include the DNS domain name, 
 197                     // for this we need to work a bit more 
 198                     if ( !strchr(bufA
, '.') ) 
 200                         LOAD_WINSOCK_FUNC(gethostbyname
); 
 202                         struct hostent 
*pHostEnt 
= pfngethostbyname
 
 203                                                     ? pfngethostbyname(bufA
) 
 208                             // Windows will use DNS internally now 
 209                             LOAD_WINSOCK_FUNC(gethostbyaddr
); 
 211                             pHostEnt 
= pfngethostbyaddr
 
 212                                         ? pfngethostbyaddr(pHostEnt
->h_addr
, 
 219                             host 
= wxString::FromAscii(pHostEnt
->h_name
); 
 225             LOAD_WINSOCK_FUNC(WSACleanup
); 
 232                 wxStrncpy(buf
, host
, maxSize
); 
 238 #endif // !__WXMICROWIN__ 
 240     return wxGetHostName(buf
, maxSize
); 
 243 // Get user ID e.g. jacs 
 244 bool wxGetUserId(wxChar 
*WXUNUSED_IN_WINCE(buf
), 
 245                  int WXUNUSED_IN_WINCE(maxSize
)) 
 247 #if defined(__WXWINCE__) 
 250 #elif defined(__WIN32__) && !defined(__WXMICROWIN__) 
 251     DWORD nSize 
= maxSize
; 
 252     if ( ::GetUserName(buf
, &nSize
) == 0 ) 
 254         // actually, it does happen on Win9x if the user didn't log on 
 255         DWORD res 
= ::GetEnvironmentVariable(wxT("username"), buf
, maxSize
); 
 264 #else   // __WXMICROWIN__ 
 266     const wxChar 
*default_id 
= wxT("anonymous"); 
 268     // Can't assume we have NIS (PC-NFS) or some other ID daemon 
 270     if ( (user 
= wxGetenv(wxT("USER"))) == NULL 
&& 
 271          (user 
= wxGetenv(wxT("LOGNAME"))) == NULL 
) 
 273         // Use wxWidgets configuration data (comming soon) 
 274         GetProfileString(WX_SECTION
, eUSERID
, default_id
, buf
, maxSize 
- 1); 
 278         wxStrncpy(buf
, user
, maxSize 
- 1); 
 281     return *buf 
? true : false; 
 285 // Get user name e.g. Julian Smart 
 286 bool wxGetUserName(wxChar 
*buf
, int maxSize
) 
 288     wxCHECK_MSG( buf 
&& ( maxSize 
> 0 ), false, 
 289                     _T("empty buffer in wxGetUserName") ); 
 290 #if defined(__WXWINCE__) 
 292     wxRegKey 
key(wxRegKey::HKCU
, wxT("ControlPanel\\Owner")); 
 293     if(!key
.Open(wxRegKey::Read
)) 
 296     if(!key
.QueryValue(wxT("Owner"),name
)) 
 298     wxStrncpy(buf
, name
.c_str(), maxSize
-1); 
 299     buf
[maxSize
-1] = _T('\0'); 
 301 #elif defined(USE_NET_API) 
 302     CHAR szUserName
[256]; 
 303     if ( !wxGetUserId(szUserName
, WXSIZEOF(szUserName
)) ) 
 306     // TODO how to get the domain name? 
 309     // the code is based on the MSDN example (also see KB article Q119670) 
 310     WCHAR wszUserName
[256];          // Unicode user name 
 311     WCHAR wszDomain
[256]; 
 314     USER_INFO_2 
*ui2
;         // User structure 
 316     // Convert ANSI user name and domain to Unicode 
 317     MultiByteToWideChar( CP_ACP
, 0, szUserName
, strlen(szUserName
)+1, 
 318             wszUserName
, WXSIZEOF(wszUserName
) ); 
 319     MultiByteToWideChar( CP_ACP
, 0, szDomain
, strlen(szDomain
)+1, 
 320             wszDomain
, WXSIZEOF(wszDomain
) ); 
 322     // Get the computer name of a DC for the domain. 
 323     if ( NetGetDCName( NULL
, wszDomain
, &ComputerName 
) != NERR_Success 
) 
 325         wxLogError(wxT("Can not find domain controller")); 
 330     // Look up the user on the DC 
 331     NET_API_STATUS status 
= NetUserGetInfo( (LPWSTR
)ComputerName
, 
 332             (LPWSTR
)&wszUserName
, 
 333             2, // level - we want USER_INFO_2 
 341         case NERR_InvalidComputer
: 
 342             wxLogError(wxT("Invalid domain controller name.")); 
 346         case NERR_UserNotFound
: 
 347             wxLogError(wxT("Invalid user name '%s'."), szUserName
); 
 352             wxLogSysError(wxT("Can't get information about user")); 
 357     // Convert the Unicode full name to ANSI 
 358     WideCharToMultiByte( CP_ACP
, 0, ui2
->usri2_full_name
, -1, 
 359             buf
, maxSize
, NULL
, NULL 
); 
 364     wxLogError(wxT("Couldn't look up full user name.")); 
 367 #else  // !USE_NET_API 
 368     // Could use NIS, MS-Mail or other site specific programs 
 369     // Use wxWidgets configuration data 
 370     bool ok 
= GetProfileString(WX_SECTION
, eUSERNAME
, wxEmptyString
, buf
, maxSize 
- 1) != 0; 
 373         ok 
= wxGetUserId(buf
, maxSize
); 
 378         wxStrncpy(buf
, wxT("Unknown User"), maxSize
); 
 385 const wxChar
* wxGetHomeDir(wxString 
*pstr
) 
 387     wxString
& strDir 
= *pstr
; 
 389     // first branch is for Cygwin 
 390 #if defined(__UNIX__) 
 391     const wxChar 
*szHome 
= wxGetenv("HOME"); 
 392     if ( szHome 
== NULL 
) { 
 394       wxLogWarning(_("can't find user's HOME, using current directory.")); 
 400     // add a trailing slash if needed 
 401     if ( strDir
.Last() != wxT('/') ) 
 405         // Cygwin returns unix type path but that does not work well 
 406         static wxChar windowsPath
[MAX_PATH
]; 
 407         cygwin_conv_to_full_win32_path(strDir
, windowsPath
); 
 408         strDir 
= windowsPath
; 
 410 #elif defined(__WXWINCE__) 
 415     // If we have a valid HOME directory, as is used on many machines that 
 416     // have unix utilities on them, we should use that. 
 417     const wxChar 
*szHome 
= wxGetenv(wxT("HOME")); 
 419     if ( szHome 
!= NULL 
) 
 423     else // no HOME, try HOMEDRIVE/PATH 
 425         szHome 
= wxGetenv(wxT("HOMEDRIVE")); 
 426         if ( szHome 
!= NULL 
) 
 428         szHome 
= wxGetenv(wxT("HOMEPATH")); 
 430         if ( szHome 
!= NULL 
) 
 434             // the idea is that under NT these variables have default values 
 435             // of "%systemdrive%:" and "\\". As we don't want to create our 
 436             // config files in the root directory of the system drive, we will 
 437             // create it in our program's dir. However, if the user took care 
 438             // to set HOMEPATH to something other than "\\", we suppose that he 
 439             // knows what he is doing and use the supplied value. 
 440             if ( wxStrcmp(szHome
, wxT("\\")) == 0 ) 
 445     if ( strDir
.empty() ) 
 447         // If we have a valid USERPROFILE directory, as is the case in 
 448         // Windows NT, 2000 and XP, we should use that as our home directory. 
 449         szHome 
= wxGetenv(wxT("USERPROFILE")); 
 451         if ( szHome 
!= NULL 
) 
 455     if ( !strDir
.empty() ) 
 457         // sometimes the value of HOME may be "%USERPROFILE%", so reexpand the 
 458         // value once again, it shouldn't hurt anyhow 
 459         strDir 
= wxExpandEnvVars(strDir
); 
 461     else // fall back to the program directory 
 463         // extract the directory component of the program file name 
 464         wxSplitPath(wxGetFullModuleName(), &strDir
, NULL
, NULL
); 
 468     return strDir
.c_str(); 
 471 wxChar 
*wxGetUserHome(const wxString
& WXUNUSED(user
)) 
 473     // VZ: the old code here never worked for user != "" anyhow! Moreover, it 
 474     //     returned sometimes a malloc()'d pointer, sometimes a pointer to a 
 475     //     static buffer and sometimes I don't even know what. 
 476     static wxString s_home
; 
 478     return (wxChar 
*)wxGetHomeDir(&s_home
); 
 481 bool wxGetDiskSpace(const wxString
& WXUNUSED_IN_WINCE(path
), 
 482                     wxDiskspaceSize_t 
*WXUNUSED_IN_WINCE(pTotal
), 
 483                     wxDiskspaceSize_t 
*WXUNUSED_IN_WINCE(pFree
)) 
 492 // old w32api don't have ULARGE_INTEGER 
 493 #if defined(__WIN32__) && \ 
 494     (!defined(__GNUWIN32__) || wxCHECK_W32API_VERSION( 0, 3 )) 
 495     // GetDiskFreeSpaceEx() is not available under original Win95, check for 
 497     typedef BOOL (WINAPI 
*GetDiskFreeSpaceEx_t
)(LPCTSTR
, 
 503         pGetDiskFreeSpaceEx 
= (GetDiskFreeSpaceEx_t
)::GetProcAddress
 
 505                                 ::GetModuleHandle(_T("kernel32.dll")), 
 507                                 "GetDiskFreeSpaceExW" 
 509                                 "GetDiskFreeSpaceExA" 
 513     if ( pGetDiskFreeSpaceEx 
) 
 515         ULARGE_INTEGER bytesFree
, bytesTotal
; 
 517         // may pass the path as is, GetDiskFreeSpaceEx() is smart enough 
 518         if ( !pGetDiskFreeSpaceEx(path
, 
 523             wxLogLastError(_T("GetDiskFreeSpaceEx")); 
 528         // ULARGE_INTEGER is a union of a 64 bit value and a struct containing 
 529         // two 32 bit fields which may be or may be not named - try to make it 
 530         // compile in all cases 
 531 #if defined(__BORLANDC__) && !defined(_ANONYMOUS_STRUCT) 
 539             *pTotal 
= wxDiskspaceSize_t(UL(bytesTotal
).HighPart
, UL(bytesTotal
).LowPart
); 
 541             *pTotal 
= wxDiskspaceSize_t(UL(bytesTotal
).LowPart
); 
 548             *pFree 
= wxLongLong(UL(bytesFree
).HighPart
, UL(bytesFree
).LowPart
); 
 550             *pFree 
= wxDiskspaceSize_t(UL(bytesFree
).LowPart
); 
 557         // there's a problem with drives larger than 2GB, GetDiskFreeSpaceEx() 
 558         // should be used instead - but if it's not available, fall back on 
 559         // GetDiskFreeSpace() nevertheless... 
 561         DWORD lSectorsPerCluster
, 
 563               lNumberOfFreeClusters
, 
 564               lTotalNumberOfClusters
; 
 566         // FIXME: this is wrong, we should extract the root drive from path 
 567         //        instead, but this is the job for wxFileName... 
 568         if ( !::GetDiskFreeSpace(path
, 
 571                                  &lNumberOfFreeClusters
, 
 572                                  &lTotalNumberOfClusters
) ) 
 574             wxLogLastError(_T("GetDiskFreeSpace")); 
 579         wxDiskspaceSize_t lBytesPerCluster 
= (wxDiskspaceSize_t
) lSectorsPerCluster
; 
 580         lBytesPerCluster 
*= lBytesPerSector
; 
 584             *pTotal 
= lBytesPerCluster
; 
 585             *pTotal 
*= lTotalNumberOfClusters
; 
 590             *pFree 
= lBytesPerCluster
; 
 591             *pFree 
*= lNumberOfFreeClusters
; 
 600 // ---------------------------------------------------------------------------- 
 602 // ---------------------------------------------------------------------------- 
 604 bool wxGetEnv(const wxString
& WXUNUSED_IN_WINCE(var
), 
 605               wxString 
*WXUNUSED_IN_WINCE(value
)) 
 608     // no environment variables under CE 
 611     // first get the size of the buffer 
 612     DWORD dwRet 
= ::GetEnvironmentVariable(var
, NULL
, 0); 
 615         // this means that there is no such variable 
 621         (void)::GetEnvironmentVariable(var
, wxStringBuffer(*value
, dwRet
), 
 629 bool wxSetEnv(const wxString
& WXUNUSED_IN_WINCE(var
), 
 630               const wxChar 
*WXUNUSED_IN_WINCE(value
)) 
 632     // some compilers have putenv() or _putenv() or _wputenv() but it's better 
 633     // to always use Win32 function directly instead of dealing with them 
 635     // no environment variables under CE 
 638     if ( !::SetEnvironmentVariable(var
, value
) ) 
 640         wxLogLastError(_T("SetEnvironmentVariable")); 
 649 // ---------------------------------------------------------------------------- 
 650 // process management 
 651 // ---------------------------------------------------------------------------- 
 653 // structure used to pass parameters from wxKill() to wxEnumFindByPidProc() 
 654 struct wxFindByPidParams
 
 656     wxFindByPidParams() { hwnd 
= 0; pid 
= 0; } 
 658     // the HWND used to return the result 
 661     // the PID we're looking from 
 664     DECLARE_NO_COPY_CLASS(wxFindByPidParams
) 
 667 // wxKill helper: EnumWindows() callback which is used to find the first (top 
 668 // level) window belonging to the given process 
 669 BOOL CALLBACK 
wxEnumFindByPidProc(HWND hwnd
, LPARAM lParam
) 
 672     (void)::GetWindowThreadProcessId(hwnd
, &pid
); 
 674     wxFindByPidParams 
*params 
= (wxFindByPidParams 
*)lParam
; 
 675     if ( pid 
== params
->pid 
) 
 677         // remember the window we found 
 680         // return FALSE to stop the enumeration 
 684     // continue enumeration 
 688 int wxKillAllChildren(long pid
, wxSignal sig
, wxKillError 
*krc
); 
 690 int wxKill(long pid
, wxSignal sig
, wxKillError 
*krc
, int flags
) 
 692     if (flags 
& wxKILL_CHILDREN
) 
 693         wxKillAllChildren(pid
, sig
, krc
); 
 695     // get the process handle to operate on 
 696     HANDLE hProcess 
= ::OpenProcess(SYNCHRONIZE 
| 
 698                                     PROCESS_QUERY_INFORMATION
, 
 699                                     FALSE
, // not inheritable 
 701     if ( hProcess 
== NULL 
) 
 705             // recognize wxKILL_ACCESS_DENIED as special because this doesn't 
 706             // mean that the process doesn't exist and this is important for 
 707             // wxProcess::Exists() 
 708             *krc 
= ::GetLastError() == ERROR_ACCESS_DENIED
 
 709                         ? wxKILL_ACCESS_DENIED
 
 716     wxON_BLOCK_EXIT1(::CloseHandle
, hProcess
); 
 722             // kill the process forcefully returning -1 as error code 
 723             if ( !::TerminateProcess(hProcess
, (UINT
)-1) ) 
 725                 wxLogSysError(_("Failed to kill process %d"), pid
); 
 729                     // this is not supposed to happen if we could open the 
 739             // do nothing, we just want to test for process existence 
 745             // any other signal means "terminate" 
 747                 wxFindByPidParams params
; 
 748                 params
.pid 
= (DWORD
)pid
; 
 750                 // EnumWindows() has nice semantics: it returns 0 if it found 
 751                 // something or if an error occurred and non zero if it 
 752                 // enumerated all the window 
 753                 if ( !::EnumWindows(wxEnumFindByPidProc
, (LPARAM
)¶ms
) ) 
 755                     // did we find any window? 
 758                         // tell the app to close 
 760                         // NB: this is the harshest way, the app won't have an 
 761                         //     opportunity to save any files, for example, but 
 762                         //     this is probably what we want here. If not we 
 763                         //     can also use SendMesageTimeout(WM_CLOSE) 
 764                         if ( !::PostMessage(params
.hwnd
, WM_QUIT
, 0, 0) ) 
 766                             wxLogLastError(_T("PostMessage(WM_QUIT)")); 
 769                     else // it was an error then 
 771                         wxLogLastError(_T("EnumWindows")); 
 776                 else // no windows for this PID 
 787     DWORD rc 
wxDUMMY_INITIALIZE(0); 
 790         // as we wait for a short time, we can use just WaitForSingleObject() 
 791         // and not MsgWaitForMultipleObjects() 
 792         switch ( ::WaitForSingleObject(hProcess
, 500 /* msec */) ) 
 795                 // process terminated 
 796                 if ( !::GetExitCodeProcess(hProcess
, &rc
) ) 
 798                     wxLogLastError(_T("GetExitCodeProcess")); 
 803                 wxFAIL_MSG( _T("unexpected WaitForSingleObject() return") ); 
 807                 wxLogLastError(_T("WaitForSingleObject")); 
 820     // the return code is the same as from Unix kill(): 0 if killed 
 821     // successfully or -1 on error 
 822     if ( !ok 
|| rc 
== STILL_ACTIVE 
) 
 831 typedef HANDLE (WINAPI 
*CreateToolhelp32Snapshot_t
)(DWORD
,DWORD
); 
 832 typedef BOOL (WINAPI 
*Process32_t
)(HANDLE
,LPPROCESSENTRY32
); 
 834 CreateToolhelp32Snapshot_t lpfCreateToolhelp32Snapshot
; 
 835 Process32_t lpfProcess32First
, lpfProcess32Next
; 
 837 static void InitToolHelp32() 
 839     static bool s_initToolHelpDone 
= false; 
 841     if (s_initToolHelpDone
) 
 844     s_initToolHelpDone 
= true; 
 846     lpfCreateToolhelp32Snapshot 
= NULL
; 
 847     lpfProcess32First 
= NULL
; 
 848     lpfProcess32Next 
= NULL
; 
 850 #if wxUSE_DYNLIB_CLASS 
 852     wxDynamicLibrary 
dllKernel(_T("kernel32.dll"), wxDL_VERBATIM
); 
 854     // Get procedure addresses. 
 855     // We are linking to these functions of Kernel32 
 856     // explicitly, because otherwise a module using 
 857     // this code would fail to load under Windows NT, 
 858     // which does not have the Toolhelp32 
 859     // functions in the Kernel 32. 
 860     lpfCreateToolhelp32Snapshot 
= 
 861         (CreateToolhelp32Snapshot_t
)dllKernel
.RawGetSymbol(_T("CreateToolhelp32Snapshot")); 
 864         (Process32_t
)dllKernel
.RawGetSymbol(_T("Process32First")); 
 867         (Process32_t
)dllKernel
.RawGetSymbol(_T("Process32Next")); 
 869 #endif // wxUSE_DYNLIB_CLASS 
 873 int wxKillAllChildren(long pid
, wxSignal sig
, wxKillError 
*krc
) 
 880     // If not implemented for this platform (e.g. NT 4.0), silently ignore 
 881     if (!lpfCreateToolhelp32Snapshot 
|| !lpfProcess32First 
|| !lpfProcess32Next
) 
 884     // Take a snapshot of all processes in the system. 
 885     HANDLE hProcessSnap 
= lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0); 
 886     if (hProcessSnap 
== INVALID_HANDLE_VALUE
) { 
 892     //Fill in the size of the structure before using it. 
 895     pe
.dwSize 
= sizeof(PROCESSENTRY32
); 
 897     // Walk the snapshot of the processes, and for each process, 
 898     // kill it if its parent is pid. 
 899     if (!lpfProcess32First(hProcessSnap
, &pe
)) { 
 900         // Can't get first process. 
 903         CloseHandle (hProcessSnap
); 
 908         if (pe
.th32ParentProcessID 
== (DWORD
) pid
) { 
 909             if (wxKill(pe
.th32ProcessID
, sig
, krc
)) 
 912     } while (lpfProcess32Next (hProcessSnap
, &pe
)); 
 918 // Execute a program in an Interactive Shell 
 919 bool wxShell(const wxString
& command
) 
 926     wxChar 
*shell 
= wxGetenv(wxT("COMSPEC")); 
 928         shell 
= (wxChar
*) wxT("\\COMMAND.COM"); 
 937         // pass the command to execute to the command processor 
 938         cmd
.Printf(wxT("%s /c %s"), shell
, command
.c_str()); 
 942     return wxExecute(cmd
, wxEXEC_SYNC
) == 0; 
 945 // Shutdown or reboot the PC 
 946 bool wxShutdown(wxShutdownFlags 
WXUNUSED_IN_WINCE(wFlags
)) 
 951 #elif defined(__WIN32__) 
 954     if ( wxGetOsVersion(NULL
, NULL
) == wxWINDOWS_NT 
) // if is NT or 2K 
 956         // Get a token for this process. 
 958         bOK 
= ::OpenProcessToken(GetCurrentProcess(), 
 959                                  TOKEN_ADJUST_PRIVILEGES 
| TOKEN_QUERY
, 
 963             TOKEN_PRIVILEGES tkp
; 
 965             // Get the LUID for the shutdown privilege. 
 966             ::LookupPrivilegeValue(NULL
, SE_SHUTDOWN_NAME
, 
 967                                    &tkp
.Privileges
[0].Luid
); 
 969             tkp
.PrivilegeCount 
= 1;  // one privilege to set 
 970             tkp
.Privileges
[0].Attributes 
= SE_PRIVILEGE_ENABLED
; 
 972             // Get the shutdown privilege for this process. 
 973             ::AdjustTokenPrivileges(hToken
, FALSE
, &tkp
, 0, 
 974                                     (PTOKEN_PRIVILEGES
)NULL
, 0); 
 976             // Cannot test the return value of AdjustTokenPrivileges. 
 977             bOK 
= ::GetLastError() == ERROR_SUCCESS
; 
 983         UINT flags 
= EWX_SHUTDOWN 
| EWX_FORCE
; 
 986             case wxSHUTDOWN_POWEROFF
: 
 987                 flags 
|= EWX_POWEROFF
; 
 990             case wxSHUTDOWN_REBOOT
: 
 995                 wxFAIL_MSG( _T("unknown wxShutdown() flag") ); 
 999         bOK 
= ::ExitWindowsEx(flags
, 0) != 0; 
1006 // ---------------------------------------------------------------------------- 
1008 // ---------------------------------------------------------------------------- 
1010 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX) 
1011 wxMemorySize 
wxGetFreeMemory() 
1013 #if defined(__WIN64__) 
1014     MEMORYSTATUSEX memStatex
; 
1015     memStatex
.dwLength 
= sizeof (memStatex
); 
1016     ::GlobalMemoryStatusEx (&memStatex
); 
1017     return (wxMemorySize
)memStatex
.ullAvailPhys
; 
1018 #else /* if defined(__WIN32__) */ 
1019     MEMORYSTATUS memStatus
; 
1020     memStatus
.dwLength 
= sizeof(MEMORYSTATUS
); 
1021     ::GlobalMemoryStatus(&memStatus
); 
1022     return (wxMemorySize
)memStatus
.dwAvailPhys
; 
1026 unsigned long wxGetProcessId() 
1028     return ::GetCurrentProcessId(); 
1034     ::MessageBeep((UINT
)-1);        // default sound 
1037 bool wxIsDebuggerRunning() 
1039 #if wxUSE_DYNLIB_CLASS 
1040     // IsDebuggerPresent() is not available under Win95, so load it dynamically 
1041     wxDynamicLibrary 
dll(_T("kernel32.dll"), wxDL_VERBATIM
); 
1043     typedef BOOL (WINAPI 
*IsDebuggerPresent_t
)(); 
1044     if ( !dll
.HasSymbol(_T("IsDebuggerPresent")) ) 
1046         // no way to know, assume no 
1050     return (*(IsDebuggerPresent_t
)dll
.GetSymbol(_T("IsDebuggerPresent")))() != 0; 
1056 // ---------------------------------------------------------------------------- 
1058 // ---------------------------------------------------------------------------- 
1060 wxString 
wxGetOsDescription() 
1067     info
.dwOSVersionInfoSize 
= sizeof(OSVERSIONINFO
); 
1068     if ( ::GetVersionEx(&info
) ) 
1070         switch ( info
.dwPlatformId 
) 
1072 #ifdef VER_PLATFORM_WIN32_CE 
1073             case VER_PLATFORM_WIN32_CE
: 
1074                 str
.Printf(_("Windows CE (%d.%d)"), 
1075                            info
.dwMajorVersion
, 
1076                            info
.dwMinorVersion
); 
1079             case VER_PLATFORM_WIN32s
: 
1080                 str 
= _("Win32s on Windows 3.1"); 
1083             case VER_PLATFORM_WIN32_WINDOWS
: 
1084                 switch (info
.dwMinorVersion
) 
1087                         if ( info
.szCSDVersion
[1] == 'B' || 
1088                              info
.szCSDVersion
[1] == 'C' ) 
1090                             str 
= _("Windows 95 OSR2"); 
1094                             str 
= _("Windows 95"); 
1098                         if ( info
.szCSDVersion
[1] == 'B' || 
1099                              info
.szCSDVersion
[1] == 'C' ) 
1101                             str 
= _("Windows 98 SE"); 
1105                             str 
= _("Windows 98"); 
1109                         str 
= _("Windows ME"); 
1112                         str
.Printf(_("Windows 9x (%d.%d)"), 
1113                                    info
.dwMajorVersion
, 
1114                                    info
.dwMinorVersion
); 
1117                 if ( !wxIsEmpty(info
.szCSDVersion
) ) 
1119                     str 
<< _T(" (") << info
.szCSDVersion 
<< _T(')'); 
1123             case VER_PLATFORM_WIN32_NT
: 
1124                 if ( info
.dwMajorVersion 
== 5 ) 
1126                     switch ( info
.dwMinorVersion 
) 
1129                             str
.Printf(_("Windows 2000 (build %lu"), 
1130                                        info
.dwBuildNumber
); 
1133                             str
.Printf(_("Windows XP (build %lu"), 
1134                                        info
.dwBuildNumber
); 
1137                             str
.Printf(_("Windows Server 2003 (build %lu"), 
1138                                        info
.dwBuildNumber
); 
1144                     str
.Printf(_("Windows NT %lu.%lu (build %lu"), 
1145                            info
.dwMajorVersion
, 
1146                            info
.dwMinorVersion
, 
1147                            info
.dwBuildNumber
); 
1149                 if ( !wxIsEmpty(info
.szCSDVersion
) ) 
1151                     str 
<< _T(", ") << info
.szCSDVersion
; 
1159         wxFAIL_MSG( _T("GetVersionEx() failed") ); // should never happen 
1165 bool wxIsPlatform64Bit() 
1168     return true;  // 64-bit programs run only on Win64 
1170     // 32-bit programs run on both 32-bit and 64-bit Windows so check 
1171     typedef BOOL (WINAPI 
*IsWow64Process_t
)(HANDLE
, BOOL 
*); 
1173     wxDynamicLibrary 
dllKernel32(_T("kernel32.dll")); 
1174     IsWow64Process_t 
*pfnIsWow64Process 
= 
1175         (IsWow64Process_t 
*)dllKernel32
.RawGetSymbol(_T("IsWow64Process")); 
1178     if ( pfnIsWow64Process 
) 
1180         (*pfnIsWow64Process
)(::GetCurrentProcess(), &wow64
); 
1182     //else: running under a system without Win64 support 
1184     return wow64 
!= FALSE
; 
1185 #endif // Win64/Win32 
1188 wxOperatingSystemId 
wxGetOsVersion(int *verMaj
, int *verMin
) 
1193     info
.dwOSVersionInfoSize 
= sizeof(OSVERSIONINFO
); 
1194     if ( ::GetVersionEx(&info
) ) 
1196         if (verMaj
) *verMaj 
= info
.dwMajorVersion
; 
1197         if (verMin
) *verMin 
= info
.dwMinorVersion
; 
1200 #if defined(__WXHANDHELD__) || defined( __WXWINCE__ ) 
1201     return wxOS_WINDOWS_WINCE
; 
1202 #elif defined( __WXMICROWIN__ ) 
1203     return wxOS_WINDOWS_MICRO
; 
1205     switch ( info
.dwPlatformId 
) 
1207     case VER_PLATFORM_WIN32_NT
: 
1208         return wxOS_WINDOWS_NT
; 
1210     case VER_PLATFORM_WIN32_WINDOWS
: 
1211         return wxOS_WINDOWS_9X
; 
1214     return wxOS_UNKNOWN
; 
1218 wxWinVersion 
wxGetWinVersion() 
1222     switch ( wxGetOsVersion(&verMaj
, &verMin
) ) 
1230                         return wxWinVersion_95
; 
1233                         return wxWinVersion_98
; 
1236                         return wxWinVersion_ME
; 
1245                     return wxWinVersion_NT3
; 
1248                     return wxWinVersion_NT4
; 
1254                             return wxWinVersion_2000
; 
1257                             return wxWinVersion_XP
; 
1260                             return wxWinVersion_2003
; 
1265                     return wxWinVersion_NT6
; 
1271     return wxWinVersion_Unknown
; 
1274 // ---------------------------------------------------------------------------- 
1276 // ---------------------------------------------------------------------------- 
1278 void wxMilliSleep(unsigned long milliseconds
) 
1280     ::Sleep(milliseconds
); 
1283 void wxMicroSleep(unsigned long microseconds
) 
1285     wxMilliSleep(microseconds
/1000); 
1288 void wxSleep(int nSecs
) 
1290     wxMilliSleep(1000*nSecs
); 
1293 // ---------------------------------------------------------------------------- 
1294 // font encoding <-> Win32 codepage conversion functions 
1295 // ---------------------------------------------------------------------------- 
1297 extern WXDLLIMPEXP_BASE 
long wxEncodingToCharset(wxFontEncoding encoding
) 
1301         // although this function is supposed to return an exact match, do do 
1302         // some mappings here for the most common case of "standard" encoding 
1303         case wxFONTENCODING_SYSTEM
: 
1304             return DEFAULT_CHARSET
; 
1306         case wxFONTENCODING_ISO8859_1
: 
1307         case wxFONTENCODING_ISO8859_15
: 
1308         case wxFONTENCODING_CP1252
: 
1309             return ANSI_CHARSET
; 
1311 #if !defined(__WXMICROWIN__) 
1312         // The following four fonts are multi-byte charsets 
1313         case wxFONTENCODING_CP932
: 
1314             return SHIFTJIS_CHARSET
; 
1316         case wxFONTENCODING_CP936
: 
1317             return GB2312_CHARSET
; 
1320         case wxFONTENCODING_CP949
: 
1321             return HANGUL_CHARSET
; 
1324         case wxFONTENCODING_CP950
: 
1325             return CHINESEBIG5_CHARSET
; 
1327         // The rest are single byte encodings 
1328         case wxFONTENCODING_CP1250
: 
1329             return EASTEUROPE_CHARSET
; 
1331         case wxFONTENCODING_CP1251
: 
1332             return RUSSIAN_CHARSET
; 
1334         case wxFONTENCODING_CP1253
: 
1335             return GREEK_CHARSET
; 
1337         case wxFONTENCODING_CP1254
: 
1338             return TURKISH_CHARSET
; 
1340         case wxFONTENCODING_CP1255
: 
1341             return HEBREW_CHARSET
; 
1343         case wxFONTENCODING_CP1256
: 
1344             return ARABIC_CHARSET
; 
1346         case wxFONTENCODING_CP1257
: 
1347             return BALTIC_CHARSET
; 
1349         case wxFONTENCODING_CP874
: 
1350             return THAI_CHARSET
; 
1351 #endif // !__WXMICROWIN__ 
1353         case wxFONTENCODING_CP437
: 
1357             // no way to translate this encoding into a Windows charset 
1362 // we have 2 versions of wxCharsetToCodepage(): the old one which directly 
1363 // looks up the vlaues in the registry and the new one which is more 
1364 // politically correct and has more chances to work on other Windows versions 
1365 // as well but the old version is still needed for !wxUSE_FONTMAP case 
1368 #include "wx/fontmap.h" 
1370 extern WXDLLIMPEXP_BASE 
long wxEncodingToCodepage(wxFontEncoding encoding
) 
1372     // There don't seem to be symbolic names for 
1373     // these under Windows so I just copied the 
1374     // values from MSDN. 
1380         case wxFONTENCODING_ISO8859_1
:      ret 
= 28591; break; 
1381         case wxFONTENCODING_ISO8859_2
:      ret 
= 28592; break; 
1382         case wxFONTENCODING_ISO8859_3
:      ret 
= 28593; break; 
1383         case wxFONTENCODING_ISO8859_4
:      ret 
= 28594; break; 
1384         case wxFONTENCODING_ISO8859_5
:      ret 
= 28595; break; 
1385         case wxFONTENCODING_ISO8859_6
:      ret 
= 28596; break; 
1386         case wxFONTENCODING_ISO8859_7
:      ret 
= 28597; break; 
1387         case wxFONTENCODING_ISO8859_8
:      ret 
= 28598; break; 
1388         case wxFONTENCODING_ISO8859_9
:      ret 
= 28599; break; 
1389         case wxFONTENCODING_ISO8859_10
:     ret 
= 28600; break; 
1390         case wxFONTENCODING_ISO8859_11
:     ret 
= 28601; break; 
1391         // case wxFONTENCODING_ISO8859_12,      // doesn't exist currently, but put it 
1392         case wxFONTENCODING_ISO8859_13
:     ret 
= 28603; break; 
1393         case wxFONTENCODING_ISO8859_14
:     ret 
= 28604; break; 
1394         case wxFONTENCODING_ISO8859_15
:     ret 
= 28605; break; 
1395         case wxFONTENCODING_KOI8
:           ret 
= 20866; break; 
1396         case wxFONTENCODING_KOI8_U
:         ret 
= 21866; break; 
1397         case wxFONTENCODING_CP437
:          ret 
= 437; break; 
1398         case wxFONTENCODING_CP850
:          ret 
= 850; break; 
1399         case wxFONTENCODING_CP852
:          ret 
= 852; break; 
1400         case wxFONTENCODING_CP855
:          ret 
= 855; break; 
1401         case wxFONTENCODING_CP866
:          ret 
= 866; break; 
1402         case wxFONTENCODING_CP874
:          ret 
= 874; break; 
1403         case wxFONTENCODING_CP932
:          ret 
= 932; break; 
1404         case wxFONTENCODING_CP936
:          ret 
= 936; break; 
1405         case wxFONTENCODING_CP949
:          ret 
= 949; break; 
1406         case wxFONTENCODING_CP950
:          ret 
= 950; break; 
1407         case wxFONTENCODING_CP1250
:         ret 
= 1250; break; 
1408         case wxFONTENCODING_CP1251
:         ret 
= 1251; break; 
1409         case wxFONTENCODING_CP1252
:         ret 
= 1252; break; 
1410         case wxFONTENCODING_CP1253
:         ret 
= 1253; break; 
1411         case wxFONTENCODING_CP1254
:         ret 
= 1254; break; 
1412         case wxFONTENCODING_CP1255
:         ret 
= 1255; break; 
1413         case wxFONTENCODING_CP1256
:         ret 
= 1256; break; 
1414         case wxFONTENCODING_CP1257
:         ret 
= 1257; break; 
1415         case wxFONTENCODING_EUC_JP
:         ret 
= 20932; break; 
1416         case wxFONTENCODING_MACROMAN
:       ret 
= 10000; break; 
1417         case wxFONTENCODING_MACJAPANESE
:    ret 
= 10001; break; 
1418         case wxFONTENCODING_MACCHINESETRAD
: ret 
= 10002; break; 
1419         case wxFONTENCODING_MACKOREAN
:      ret 
= 10003; break; 
1420         case wxFONTENCODING_MACARABIC
:      ret 
= 10004; break; 
1421         case wxFONTENCODING_MACHEBREW
:      ret 
= 10005; break; 
1422         case wxFONTENCODING_MACGREEK
:       ret 
= 10006; break; 
1423         case wxFONTENCODING_MACCYRILLIC
:    ret 
= 10007; break; 
1424         case wxFONTENCODING_MACTHAI
:        ret 
= 10021; break; 
1425         case wxFONTENCODING_MACCHINESESIMP
: ret 
= 10008; break; 
1426         case wxFONTENCODING_MACCENTRALEUR
:  ret 
= 10029; break; 
1427         case wxFONTENCODING_MACCROATIAN
:    ret 
= 10082; break; 
1428         case wxFONTENCODING_MACICELANDIC
:   ret 
= 10079; break; 
1429         case wxFONTENCODING_MACROMANIAN
:    ret 
= 10009; break; 
1430         case wxFONTENCODING_UTF7
:           ret 
= 65000; break; 
1431         case wxFONTENCODING_UTF8
:           ret 
= 65001; break; 
1435     if (::IsValidCodePage(ret
) == 0) 
1439     if (::GetCPInfo(ret
, &info
) == 0) 
1445 extern long wxCharsetToCodepage(const wxChar 
*name
) 
1447     // first get the font encoding for this charset 
1451     wxFontEncoding enc 
= wxFontMapperBase::Get()->CharsetToEncoding(name
, false); 
1452     if ( enc 
== wxFONTENCODING_SYSTEM 
) 
1455     // the use the helper function 
1456     return wxEncodingToCodepage(enc
); 
1459 #else // !wxUSE_FONTMAP 
1461 #include "wx/msw/registry.h" 
1463 // this should work if Internet Exploiter is installed 
1464 extern long wxCharsetToCodepage(const wxChar 
*name
) 
1471     wxString 
path(wxT("MIME\\Database\\Charset\\")); 
1474     // follow the alias loop 
1477         wxRegKey 
key(wxRegKey::HKCR
, path 
+ cn
); 
1482         // two cases: either there's an AliasForCharset string, 
1483         // or there are Codepage and InternetEncoding dwords. 
1484         // The InternetEncoding gives us the actual encoding, 
1485         // the Codepage just says which Windows character set to 
1486         // use when displaying the data. 
1487         if (key
.HasValue(wxT("InternetEncoding")) && 
1488             key
.QueryValue(wxT("InternetEncoding"), &CP
)) 
1491         // no encoding, see if it's an alias 
1492         if (!key
.HasValue(wxT("AliasForCharset")) || 
1493             !key
.QueryValue(wxT("AliasForCharset"), cn
)) 
1500 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP 
1503   Creates a hidden window with supplied window proc registering the class for 
1504   it if necesssary (i.e. the first time only). Caller is responsible for 
1505   destroying the window and unregistering the class (note that this must be 
1506   done because wxWidgets may be used as a DLL and so may be loaded/unloaded 
1507   multiple times into/from the same process so we cna't rely on automatic 
1508   Windows class unregistration). 
1510   pclassname is a pointer to a caller stored classname, which must initially be 
1511   NULL. classname is the desired wndclass classname. If function successfully 
1512   registers the class, pclassname will be set to classname. 
1514 extern "C" WXDLLIMPEXP_BASE HWND
 
1515 wxCreateHiddenWindow(LPCTSTR 
*pclassname
, LPCTSTR classname
, WNDPROC wndproc
) 
1517     wxCHECK_MSG( classname 
&& pclassname 
&& wndproc
, NULL
, 
1518                     _T("NULL parameter in wxCreateHiddenWindow") ); 
1520     // register the class fi we need to first 
1521     if ( *pclassname 
== NULL 
) 
1524         wxZeroMemory(wndclass
); 
1526         wndclass
.lpfnWndProc   
= wndproc
; 
1527         wndclass
.hInstance     
= wxGetInstance(); 
1528         wndclass
.lpszClassName 
= classname
; 
1530         if ( !::RegisterClass(&wndclass
) ) 
1532             wxLogLastError(wxT("RegisterClass() in wxCreateHiddenWindow")); 
1537         *pclassname 
= classname
; 
1540     // next create the window 
1541     HWND hwnd 
= ::CreateWindow
 
1555         wxLogLastError(wxT("CreateWindow() in wxCreateHiddenWindow"));