1 ///////////////////////////////////////////////////////////////////////////// 
   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" 
  34 #include "wx/apptrait.h" 
  35 #include "wx/dynlib.h" 
  36 #include "wx/dynload.h" 
  38 #include "wx/confbase.h"        // for wxExpandEnvVars() 
  40 #include "wx/msw/private.h"     // includes <windows.h> 
  41 #include "wx/msw/missing.h"     // CHARSET_HANGUL 
  43 #if defined(__CYGWIN__) 
  44     //CYGWIN gives annoying warning about runtime stuff if we don't do this 
  45 #   define USE_SYS_TYPES_FD_SET 
  46 #   include <sys/types.h> 
  49 // Doesn't work with Cygwin at present 
  50 #if wxUSE_SOCKETS && (defined(__GNUWIN32_OLD__) || defined(__WXWINCE__) || defined(__CYGWIN32__)) 
  51     // apparently we need to include winsock.h to get WSADATA and other stuff 
  52     // used in wxGetFullHostName() with the old mingw32 versions 
  58 #if !defined(__GNUWIN32__) && !defined(__SALFORDC__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
  66 #if defined(__CYGWIN__) 
  67     #include <sys/unistd.h> 
  69     #include <sys/cygwin.h> // for cygwin_conv_to_full_win32_path() 
  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. 
  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 
  88 #if defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
  99     #if !(defined(_MSC_VER) && (_MSC_VER > 800)) 
 104 // For wxKillAllChildren 
 105 #include <tlhelp32.h> 
 107 // ---------------------------------------------------------------------------- 
 109 // ---------------------------------------------------------------------------- 
 111 // In the WIN.INI file 
 112 static const wxChar WX_SECTION
[] = wxT("wxWindows"); 
 113 static const wxChar eUSERNAME
[]  = wxT("UserName"); 
 115 // ============================================================================ 
 117 // ============================================================================ 
 119 // ---------------------------------------------------------------------------- 
 120 // get host name and related 
 121 // ---------------------------------------------------------------------------- 
 123 // Get hostname only (without domain name) 
 124 bool wxGetHostName(wxChar 
*buf
, int maxSize
) 
 126 #if defined(__WXWINCE__) 
 129     wxUnusedVar(maxSize
); 
 131 #elif defined(__WIN32__) && !defined(__WXMICROWIN__) 
 132     DWORD nSize 
= maxSize
; 
 133     if ( !::GetComputerName(buf
, &nSize
) ) 
 135         wxLogLastError(wxT("GetComputerName")); 
 143     const wxChar 
*default_host 
= wxT("noname"); 
 145     if ((sysname 
= wxGetenv(wxT("SYSTEM_NAME"))) == NULL
) { 
 146         GetProfileString(WX_SECTION
, eHOSTNAME
, default_host
, buf
, maxSize 
- 1); 
 148         wxStrncpy(buf
, sysname
, maxSize 
- 1); 
 149     buf
[maxSize
] = wxT('\0'); 
 150     return *buf 
? true : false; 
 154 // get full hostname (with domain name if possible) 
 155 bool wxGetFullHostName(wxChar 
*buf
, int maxSize
) 
 157 #if !defined( __WXMICROWIN__) && wxUSE_DYNAMIC_LOADER && wxUSE_SOCKETS 
 158     // TODO should use GetComputerNameEx() when available 
 160     // we don't want to always link with Winsock DLL as we might not use it at 
 161     // all, so load it dynamically here if needed (and don't complain if it is 
 162     // missing, we handle this) 
 165     wxDynamicLibrary 
dllWinsock(_T("ws2_32.dll"), wxDL_VERBATIM
); 
 166     if ( dllWinsock
.IsLoaded() ) 
 168         typedef int (PASCAL 
*WSAStartup_t
)(WORD
, WSADATA 
*); 
 169         typedef int (PASCAL 
*gethostname_t
)(char *, int); 
 170         typedef hostent
* (PASCAL 
*gethostbyname_t
)(const char *); 
 171         typedef hostent
* (PASCAL 
*gethostbyaddr_t
)(const char *, int , int); 
 172         typedef int (PASCAL 
*WSACleanup_t
)(void); 
 174         #define LOAD_WINSOCK_FUNC(func)                                       \ 
 176                 pfn ## func = (func ## _t)dllWinsock.GetSymbol(_T(#func)) 
 178         LOAD_WINSOCK_FUNC(WSAStartup
); 
 181         if ( pfnWSAStartup 
&& pfnWSAStartup(MAKEWORD(1, 1), &wsa
) == 0 ) 
 183             LOAD_WINSOCK_FUNC(gethostname
); 
 186             if ( pfngethostname 
) 
 189                 if ( pfngethostname(bufA
, WXSIZEOF(bufA
)) == 0 ) 
 191                     // gethostname() won't usually include the DNS domain name, 
 192                     // for this we need to work a bit more 
 193                     if ( !strchr(bufA
, '.') ) 
 195                         LOAD_WINSOCK_FUNC(gethostbyname
); 
 197                         struct hostent 
*pHostEnt 
= pfngethostbyname
 
 198                                                     ? pfngethostbyname(bufA
) 
 203                             // Windows will use DNS internally now 
 204                             LOAD_WINSOCK_FUNC(gethostbyaddr
); 
 206                             pHostEnt 
= pfngethostbyaddr
 
 207                                         ? pfngethostbyaddr(pHostEnt
->h_addr
, 
 214                             host 
= wxString::FromAscii(pHostEnt
->h_name
); 
 220             LOAD_WINSOCK_FUNC(WSACleanup
); 
 227                 wxStrncpy(buf
, host
, maxSize
); 
 233 #endif // !__WXMICROWIN__ 
 235     return wxGetHostName(buf
, maxSize
); 
 238 // Get user ID e.g. jacs 
 239 bool wxGetUserId(wxChar 
*buf
, int maxSize
) 
 241 #if defined(__WXWINCE__) 
 244     wxUnusedVar(maxSize
); 
 246 #elif defined(__WIN32__) && !defined(__WXMICROWIN__) 
 247     DWORD nSize 
= maxSize
; 
 248     if ( ::GetUserName(buf
, &nSize
) == 0 ) 
 250         // actually, it does happen on Win9x if the user didn't log on 
 251         DWORD res 
= ::GetEnvironmentVariable(wxT("username"), buf
, maxSize
); 
 260 #else   // __WXMICROWIN__ 
 262     const wxChar 
*default_id 
= wxT("anonymous"); 
 264     // Can't assume we have NIS (PC-NFS) or some other ID daemon 
 266     if (  (user 
= wxGetenv(wxT("USER"))) == NULL 
&& 
 267             (user 
= wxGetenv(wxT("LOGNAME"))) == NULL 
) 
 269         // Use wxWidgets configuration data (comming soon) 
 270         GetProfileString(WX_SECTION
, eUSERID
, default_id
, buf
, maxSize 
- 1); 
 274         wxStrncpy(buf
, user
, maxSize 
- 1); 
 277     return *buf 
? true : false; 
 281 // Get user name e.g. Julian Smart 
 282 bool wxGetUserName(wxChar 
*buf
, int maxSize
) 
 284 #if defined(__WXWINCE__) 
 287     wxUnusedVar(maxSize
); 
 289 #elif defined(USE_NET_API) 
 290     CHAR szUserName
[256]; 
 291     if ( !wxGetUserId(szUserName
, WXSIZEOF(szUserName
)) ) 
 294     // TODO how to get the domain name? 
 297     // the code is based on the MSDN example (also see KB article Q119670) 
 298     WCHAR wszUserName
[256];          // Unicode user name 
 299     WCHAR wszDomain
[256]; 
 302     USER_INFO_2 
*ui2
;         // User structure 
 304     // Convert ANSI user name and domain to Unicode 
 305     MultiByteToWideChar( CP_ACP
, 0, szUserName
, strlen(szUserName
)+1, 
 306             wszUserName
, WXSIZEOF(wszUserName
) ); 
 307     MultiByteToWideChar( CP_ACP
, 0, szDomain
, strlen(szDomain
)+1, 
 308             wszDomain
, WXSIZEOF(wszDomain
) ); 
 310     // Get the computer name of a DC for the domain. 
 311     if ( NetGetDCName( NULL
, wszDomain
, &ComputerName 
) != NERR_Success 
) 
 313         wxLogError(wxT("Can not find domain controller")); 
 318     // Look up the user on the DC 
 319     NET_API_STATUS status 
= NetUserGetInfo( (LPWSTR
)ComputerName
, 
 320             (LPWSTR
)&wszUserName
, 
 321             2, // level - we want USER_INFO_2 
 329         case NERR_InvalidComputer
: 
 330             wxLogError(wxT("Invalid domain controller name.")); 
 334         case NERR_UserNotFound
: 
 335             wxLogError(wxT("Invalid user name '%s'."), szUserName
); 
 340             wxLogSysError(wxT("Can't get information about user")); 
 345     // Convert the Unicode full name to ANSI 
 346     WideCharToMultiByte( CP_ACP
, 0, ui2
->usri2_full_name
, -1, 
 347             buf
, maxSize
, NULL
, NULL 
); 
 352     wxLogError(wxT("Couldn't look up full user name.")); 
 355 #else  // !USE_NET_API 
 356     // Could use NIS, MS-Mail or other site specific programs 
 357     // Use wxWidgets configuration data 
 358     bool ok 
= GetProfileString(WX_SECTION
, eUSERNAME
, wxEmptyString
, buf
, maxSize 
- 1) != 0; 
 361         ok 
= wxGetUserId(buf
, maxSize
); 
 366         wxStrncpy(buf
, wxT("Unknown User"), maxSize
); 
 373 const wxChar
* wxGetHomeDir(wxString 
*pstr
) 
 375     wxString
& strDir 
= *pstr
; 
 377     // first branch is for Cygwin 
 378 #if defined(__UNIX__) 
 379     const wxChar 
*szHome 
= wxGetenv("HOME"); 
 380     if ( szHome 
== NULL 
) { 
 382       wxLogWarning(_("can't find user's HOME, using current directory.")); 
 388     // add a trailing slash if needed 
 389     if ( strDir
.Last() != wxT('/') ) 
 393         // Cygwin returns unix type path but that does not work well 
 394         static wxChar windowsPath
[MAX_PATH
]; 
 395         cygwin_conv_to_full_win32_path(strDir
, windowsPath
); 
 396         strDir 
= windowsPath
; 
 398 #elif defined(__WXWINCE__) 
 403     // If we have a valid HOME directory, as is used on many machines that 
 404     // have unix utilities on them, we should use that. 
 405     const wxChar 
*szHome 
= wxGetenv(wxT("HOME")); 
 407     if ( szHome 
!= NULL 
) 
 411     else // no HOME, try HOMEDRIVE/PATH 
 413         szHome 
= wxGetenv(wxT("HOMEDRIVE")); 
 414         if ( szHome 
!= NULL 
) 
 416         szHome 
= wxGetenv(wxT("HOMEPATH")); 
 418         if ( szHome 
!= NULL 
) 
 422             // the idea is that under NT these variables have default values 
 423             // of "%systemdrive%:" and "\\". As we don't want to create our 
 424             // config files in the root directory of the system drive, we will 
 425             // create it in our program's dir. However, if the user took care 
 426             // to set HOMEPATH to something other than "\\", we suppose that he 
 427             // knows what he is doing and use the supplied value. 
 428             if ( wxStrcmp(szHome
, wxT("\\")) == 0 ) 
 433     if ( strDir
.empty() ) 
 435         // If we have a valid USERPROFILE directory, as is the case in 
 436         // Windows NT, 2000 and XP, we should use that as our home directory. 
 437         szHome 
= wxGetenv(wxT("USERPROFILE")); 
 439         if ( szHome 
!= NULL 
) 
 443     if ( !strDir
.empty() ) 
 445         // sometimes the value of HOME may be "%USERPROFILE%", so reexpand the 
 446         // value once again, it shouldn't hurt anyhow 
 447         strDir 
= wxExpandEnvVars(strDir
); 
 449     else // fall back to the program directory 
 451         // extract the directory component of the program file name 
 452         wxSplitPath(wxGetFullModuleName(), &strDir
, NULL
, NULL
); 
 456     return strDir
.c_str(); 
 459 wxChar 
*wxGetUserHome(const wxString
& WXUNUSED(user
)) 
 461     // VZ: the old code here never worked for user != "" anyhow! Moreover, it 
 462     //     returned sometimes a malloc()'d pointer, sometimes a pointer to a 
 463     //     static buffer and sometimes I don't even know what. 
 464     static wxString s_home
; 
 466     return (wxChar 
*)wxGetHomeDir(&s_home
); 
 469 bool wxGetDiskSpace(const wxString
& path
, wxLongLong 
*pTotal
, wxLongLong 
*pFree
) 
 481 // old w32api don't have ULARGE_INTEGER 
 482 #if defined(__WIN32__) && \ 
 483     (!defined(__GNUWIN32__) || wxCHECK_W32API_VERSION( 0, 3 )) 
 484     // GetDiskFreeSpaceEx() is not available under original Win95, check for 
 486     typedef BOOL (WINAPI 
*GetDiskFreeSpaceEx_t
)(LPCTSTR
, 
 492         pGetDiskFreeSpaceEx 
= (GetDiskFreeSpaceEx_t
)::GetProcAddress
 
 494                                 ::GetModuleHandle(_T("kernel32.dll")), 
 496                                 "GetDiskFreeSpaceExW" 
 498                                 "GetDiskFreeSpaceExA" 
 502     if ( pGetDiskFreeSpaceEx 
) 
 504         ULARGE_INTEGER bytesFree
, bytesTotal
; 
 506         // may pass the path as is, GetDiskFreeSpaceEx() is smart enough 
 507         if ( !pGetDiskFreeSpaceEx(path
, 
 512             wxLogLastError(_T("GetDiskFreeSpaceEx")); 
 517         // ULARGE_INTEGER is a union of a 64 bit value and a struct containing 
 518         // two 32 bit fields which may be or may be not named - try to make it 
 519         // compile in all cases 
 520 #if defined(__BORLANDC__) && !defined(_ANONYMOUS_STRUCT) 
 527             *pTotal 
= wxLongLong(UL(bytesTotal
).HighPart
, UL(bytesTotal
).LowPart
); 
 532             *pFree 
= wxLongLong(UL(bytesFree
).HighPart
, UL(bytesFree
).LowPart
); 
 538         // there's a problem with drives larger than 2GB, GetDiskFreeSpaceEx() 
 539         // should be used instead - but if it's not available, fall back on 
 540         // GetDiskFreeSpace() nevertheless... 
 542         DWORD lSectorsPerCluster
, 
 544               lNumberOfFreeClusters
, 
 545               lTotalNumberOfClusters
; 
 547         // FIXME: this is wrong, we should extract the root drive from path 
 548         //        instead, but this is the job for wxFileName... 
 549         if ( !::GetDiskFreeSpace(path
, 
 552                                  &lNumberOfFreeClusters
, 
 553                                  &lTotalNumberOfClusters
) ) 
 555             wxLogLastError(_T("GetDiskFreeSpace")); 
 560         wxLongLong lBytesPerCluster 
= lSectorsPerCluster
; 
 561         lBytesPerCluster 
*= lBytesPerSector
; 
 565             *pTotal 
= lBytesPerCluster
; 
 566             *pTotal 
*= lTotalNumberOfClusters
; 
 571             *pFree 
= lBytesPerCluster
; 
 572             *pFree 
*= lNumberOfFreeClusters
; 
 581 // ---------------------------------------------------------------------------- 
 583 // ---------------------------------------------------------------------------- 
 585 bool wxGetEnv(const wxString
& var
, wxString 
*value
) 
 588     // no environment variables under CE 
 593     // first get the size of the buffer 
 594     DWORD dwRet 
= ::GetEnvironmentVariable(var
, NULL
, 0); 
 597         // this means that there is no such variable 
 603         (void)::GetEnvironmentVariable(var
, wxStringBuffer(*value
, dwRet
), 
 611 bool wxSetEnv(const wxString
& var
, const wxChar 
*value
) 
 613     // some compilers have putenv() or _putenv() or _wputenv() but it's better 
 614     // to always use Win32 function directly instead of dealing with them 
 615 #if defined(__WIN32__) && !defined(__WXWINCE__) 
 616     if ( !::SetEnvironmentVariable(var
, value
) ) 
 618         wxLogLastError(_T("SetEnvironmentVariable")); 
 624 #else // no way to set env vars 
 625     // no environment variables under CE 
 632 // ---------------------------------------------------------------------------- 
 633 // process management 
 634 // ---------------------------------------------------------------------------- 
 636 // structure used to pass parameters from wxKill() to wxEnumFindByPidProc() 
 637 struct wxFindByPidParams
 
 639     wxFindByPidParams() { hwnd 
= 0; pid 
= 0; } 
 641     // the HWND used to return the result 
 644     // the PID we're looking from 
 647     DECLARE_NO_COPY_CLASS(wxFindByPidParams
) 
 650 // wxKill helper: EnumWindows() callback which is used to find the first (top 
 651 // level) window belonging to the given process 
 652 BOOL CALLBACK 
wxEnumFindByPidProc(HWND hwnd
, LPARAM lParam
) 
 655     (void)::GetWindowThreadProcessId(hwnd
, &pid
); 
 657     wxFindByPidParams 
*params 
= (wxFindByPidParams 
*)lParam
; 
 658     if ( pid 
== params
->pid 
) 
 660         // remember the window we found 
 663         // return FALSE to stop the enumeration 
 667     // continue enumeration 
 671 int wxKillAllChildren(long pid
, wxSignal sig
, wxKillError 
*krc
); 
 673 int wxKill(long pid
, wxSignal sig
, wxKillError 
*krc
, int flags
) 
 675     if (flags 
& wxKILL_CHILDREN
) 
 676         wxKillAllChildren(pid
, sig
, krc
); 
 678     // get the process handle to operate on 
 679     HANDLE hProcess 
= ::OpenProcess(SYNCHRONIZE 
| 
 681                                     PROCESS_QUERY_INFORMATION
, 
 682                                     FALSE
, // not inheritable 
 684     if ( hProcess 
== NULL 
) 
 688             if ( ::GetLastError() == ERROR_ACCESS_DENIED 
) 
 690                 *krc 
= wxKILL_ACCESS_DENIED
; 
 694                 *krc 
= wxKILL_NO_PROCESS
; 
 705             // kill the process forcefully returning -1 as error code 
 706             if ( !::TerminateProcess(hProcess
, (UINT
)-1) ) 
 708                 wxLogSysError(_("Failed to kill process %d"), pid
); 
 712                     // this is not supposed to happen if we could open the 
 722             // do nothing, we just want to test for process existence 
 726             // any other signal means "terminate" 
 728                 wxFindByPidParams params
; 
 729                 params
.pid 
= (DWORD
)pid
; 
 731                 // EnumWindows() has nice semantics: it returns 0 if it found 
 732                 // something or if an error occurred and non zero if it 
 733                 // enumerated all the window 
 734                 if ( !::EnumWindows(wxEnumFindByPidProc
, (LPARAM
)¶ms
) ) 
 736                     // did we find any window? 
 739                         // tell the app to close 
 741                         // NB: this is the harshest way, the app won't have an 
 742                         //     opportunity to save any files, for example, but 
 743                         //     this is probably what we want here. If not we 
 744                         //     can also use SendMesageTimeout(WM_CLOSE) 
 745                         if ( !::PostMessage(params
.hwnd
, WM_QUIT
, 0, 0) ) 
 747                             wxLogLastError(_T("PostMessage(WM_QUIT)")); 
 750                     else // it was an error then 
 752                         wxLogLastError(_T("EnumWindows")); 
 757                 else // no windows for this PID 
 774         // as we wait for a short time, we can use just WaitForSingleObject() 
 775         // and not MsgWaitForMultipleObjects() 
 776         switch ( ::WaitForSingleObject(hProcess
, 500 /* msec */) ) 
 779                 // process terminated 
 780                 if ( !::GetExitCodeProcess(hProcess
, &rc
) ) 
 782                     wxLogLastError(_T("GetExitCodeProcess")); 
 787                 wxFAIL_MSG( _T("unexpected WaitForSingleObject() return") ); 
 791                 wxLogLastError(_T("WaitForSingleObject")); 
 806         // just to suppress the warnings about uninitialized variable 
 810     ::CloseHandle(hProcess
); 
 812     // the return code is the same as from Unix kill(): 0 if killed 
 813     // successfully or -1 on error 
 815     // be careful to interpret rc correctly: for wxSIGNONE we return success if 
 816     // the process exists, for all the other sig values -- if it doesn't 
 818             ((sig 
== wxSIGNONE
) == (rc 
== STILL_ACTIVE
)) ) 
 832 HANDLE (WINAPI 
*lpfCreateToolhelp32Snapshot
)(DWORD
,DWORD
) ; 
 833 BOOL (WINAPI 
*lpfProcess32First
)(HANDLE
,LPPROCESSENTRY32
) ; 
 834 BOOL (WINAPI 
*lpfProcess32Next
)(HANDLE
,LPPROCESSENTRY32
) ; 
 836 static void InitToolHelp32() 
 838     static bool s_initToolHelpDone 
= false; 
 840     if (s_initToolHelpDone
) 
 843     s_initToolHelpDone 
= true; 
 845     lpfCreateToolhelp32Snapshot 
= NULL
; 
 846     lpfProcess32First 
= NULL
; 
 847     lpfProcess32Next 
= NULL
; 
 849     HINSTANCE hInstLib 
= LoadLibrary( wxT("Kernel32.DLL") ) ; 
 850     if( hInstLib 
== NULL 
) 
 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         (HANDLE(WINAPI 
*)(DWORD
,DWORD
)) 
 861         GetProcAddress( hInstLib
, 
 863         wxT("CreateToolhelp32Snapshot") 
 865         "CreateToolhelp32Snapshot" 
 870         (BOOL(WINAPI 
*)(HANDLE
,LPPROCESSENTRY32
)) 
 871         GetProcAddress( hInstLib
, 
 873         wxT("Process32First") 
 880         (BOOL(WINAPI 
*)(HANDLE
,LPPROCESSENTRY32
)) 
 881         GetProcAddress( hInstLib
, 
 889     FreeLibrary( hInstLib 
) ; 
 893 int wxKillAllChildren(long pid
, wxSignal sig
, wxKillError 
*krc
) 
 900     // If not implemented for this platform (e.g. NT 4.0), silently ignore 
 901     if (!lpfCreateToolhelp32Snapshot 
|| !lpfProcess32First 
|| !lpfProcess32Next
) 
 904     // Take a snapshot of all processes in the system. 
 905     HANDLE hProcessSnap 
= lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0); 
 906     if (hProcessSnap 
== INVALID_HANDLE_VALUE
) { 
 912     //Fill in the size of the structure before using it. 
 915     pe
.dwSize 
= sizeof(PROCESSENTRY32
); 
 917     // Walk the snapshot of the processes, and for each process, 
 918     // kill it if its parent is pid. 
 919     if (!lpfProcess32First(hProcessSnap
, &pe
)) { 
 920         // Can't get first process. 
 923         CloseHandle (hProcessSnap
); 
 928         if (pe
.th32ParentProcessID 
== (DWORD
) pid
) { 
 929             if (wxKill(pe
.th32ProcessID
, sig
, krc
)) 
 932     } while (lpfProcess32Next (hProcessSnap
, &pe
)); 
 938 // Execute a program in an Interactive Shell 
 939 bool wxShell(const wxString
& command
) 
 946     wxChar 
*shell 
= wxGetenv(wxT("COMSPEC")); 
 948         shell 
= (wxChar
*) wxT("\\COMMAND.COM"); 
 957         // pass the command to execute to the command processor 
 958         cmd
.Printf(wxT("%s /c %s"), shell
, command
.c_str()); 
 962     return wxExecute(cmd
, wxEXEC_SYNC
) == 0; 
 965 // Shutdown or reboot the PC 
 966 bool wxShutdown(wxShutdownFlags wFlags
) 
 972 #elif defined(__WIN32__) 
 975     if ( wxGetOsVersion(NULL
, NULL
) == wxWINDOWS_NT 
) // if is NT or 2K 
 977         // Get a token for this process. 
 979         bOK 
= ::OpenProcessToken(GetCurrentProcess(), 
 980                                  TOKEN_ADJUST_PRIVILEGES 
| TOKEN_QUERY
, 
 984             TOKEN_PRIVILEGES tkp
; 
 986             // Get the LUID for the shutdown privilege. 
 987             ::LookupPrivilegeValue(NULL
, SE_SHUTDOWN_NAME
, 
 988                                    &tkp
.Privileges
[0].Luid
); 
 990             tkp
.PrivilegeCount 
= 1;  // one privilege to set 
 991             tkp
.Privileges
[0].Attributes 
= SE_PRIVILEGE_ENABLED
; 
 993             // Get the shutdown privilege for this process. 
 994             ::AdjustTokenPrivileges(hToken
, FALSE
, &tkp
, 0, 
 995                                     (PTOKEN_PRIVILEGES
)NULL
, 0); 
 997             // Cannot test the return value of AdjustTokenPrivileges. 
 998             bOK 
= ::GetLastError() == ERROR_SUCCESS
; 
1004         UINT flags 
= EWX_SHUTDOWN 
| EWX_FORCE
; 
1007             case wxSHUTDOWN_POWEROFF
: 
1008                 flags 
|= EWX_POWEROFF
; 
1011             case wxSHUTDOWN_REBOOT
: 
1012                 flags 
|= EWX_REBOOT
; 
1016                 wxFAIL_MSG( _T("unknown wxShutdown() flag") ); 
1020         bOK 
= ::ExitWindowsEx(flags
, 0) != 0; 
1027 wxPowerType 
wxGetPowerType() 
1030     return wxPOWER_UNKNOWN
; 
1033 wxBatteryState 
wxGetBatteryState() 
1036     return wxBATTERY_UNKNOWN_STATE
; 
1039 // ---------------------------------------------------------------------------- 
1041 // ---------------------------------------------------------------------------- 
1043 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX) 
1044 wxMemorySize 
wxGetFreeMemory() 
1046 #if defined(__WIN64__) 
1047     MEMORYSTATUSEX memStatex
; 
1048     memStatex
.dwLength 
= sizeof (memStatex
); 
1049     ::GlobalMemoryStatusEx (&memStatex
); 
1050     return (wxMemorySize
)memStatex
.ullAvailPhys
; 
1051 #else /* if defined(__WIN32__) */ 
1052     MEMORYSTATUS memStatus
; 
1053     memStatus
.dwLength 
= sizeof(MEMORYSTATUS
); 
1054     ::GlobalMemoryStatus(&memStatus
); 
1055     return (wxMemorySize
)memStatus
.dwAvailPhys
; 
1059 unsigned long wxGetProcessId() 
1061     return ::GetCurrentProcessId(); 
1067     ::MessageBeep((UINT
)-1);        // default sound 
1070 bool wxIsDebuggerRunning() 
1072     // IsDebuggerPresent() is not available under Win95, so load it dynamically 
1073     wxDynamicLibrary 
dll(_T("kernel32.dll"), wxDL_VERBATIM
); 
1075     typedef BOOL (WINAPI 
*IsDebuggerPresent_t
)(); 
1076     if ( !dll
.HasSymbol(_T("IsDebuggerPresent")) ) 
1078         // no way to know, assume no 
1082     return (*(IsDebuggerPresent_t
)dll
.GetSymbol(_T("IsDebuggerPresent")))() != 0; 
1085 // ---------------------------------------------------------------------------- 
1087 // ---------------------------------------------------------------------------- 
1089 wxString 
wxGetOsDescription() 
1096     info
.dwOSVersionInfoSize 
= sizeof(OSVERSIONINFO
); 
1097     if ( ::GetVersionEx(&info
) ) 
1099         switch ( info
.dwPlatformId 
) 
1101             case VER_PLATFORM_WIN32s
: 
1102                 str 
= _("Win32s on Windows 3.1"); 
1105             case VER_PLATFORM_WIN32_WINDOWS
: 
1106                 switch (info
.dwMinorVersion
) 
1109                         if ( info
.szCSDVersion
[1] == 'B' || 
1110                              info
.szCSDVersion
[1] == 'C' ) 
1112                             str 
= _("Windows 95 OSR2"); 
1116                             str 
= _("Windows 95"); 
1120                         if ( info
.szCSDVersion
[1] == 'B' || 
1121                              info
.szCSDVersion
[1] == 'C' ) 
1123                             str 
= _("Windows 98 SE"); 
1127                             str 
= _("Windows 98"); 
1131                         str 
= _("Windows ME"); 
1134                         str
.Printf(_("Windows 9x (%d.%d)"), 
1135                                    info
.dwMajorVersion
, 
1136                                    info
.dwMinorVersion
); 
1139                 if ( !wxIsEmpty(info
.szCSDVersion
) ) 
1141                     str 
<< _T(" (") << info
.szCSDVersion 
<< _T(')'); 
1145             case VER_PLATFORM_WIN32_NT
: 
1146                 if ( info
.dwMajorVersion 
== 5 ) 
1148                     switch ( info
.dwMinorVersion 
) 
1151                             str
.Printf(_("Windows 2000 (build %lu"), 
1152                                        info
.dwBuildNumber
); 
1155                             str
.Printf(_("Windows XP (build %lu"), 
1156                                        info
.dwBuildNumber
); 
1159                             str
.Printf(_("Windows Server 2003 (build %lu"), 
1160                                        info
.dwBuildNumber
); 
1164                 if ( wxIsEmpty(str
) ) 
1166                     str
.Printf(_("Windows NT %lu.%lu (build %lu"), 
1167                            info
.dwMajorVersion
, 
1168                            info
.dwMinorVersion
, 
1169                            info
.dwBuildNumber
); 
1171                 if ( !wxIsEmpty(info
.szCSDVersion
) ) 
1173                     str 
<< _T(", ") << info
.szCSDVersion
; 
1181         wxFAIL_MSG( _T("GetVersionEx() failed") ); // should never happen 
1187 wxToolkitInfo
& wxAppTraits::GetToolkitInfo() 
1189     // cache the version info, it's not going to change 
1191     // NB: this is MT-safe, we may use these static vars from different threads 
1192     //     but as they always have the same value it doesn't matter 
1193     static int s_ver 
= -1, 
1203         info
.dwOSVersionInfoSize 
= sizeof(OSVERSIONINFO
); 
1204         if ( ::GetVersionEx(&info
) ) 
1206             s_major 
= info
.dwMajorVersion
; 
1207             s_minor 
= info
.dwMinorVersion
; 
1209 #ifdef __SMARTPHONE__ 
1210             s_ver 
= wxWINDOWS_SMARTPHONE
; 
1211 #elif defined(__POCKETPC__) 
1212             s_ver 
= wxWINDOWS_POCKETPC
; 
1214             switch ( info
.dwPlatformId 
) 
1216                 case VER_PLATFORM_WIN32s
: 
1220                 case VER_PLATFORM_WIN32_WINDOWS
: 
1224                 case VER_PLATFORM_WIN32_NT
: 
1225                     s_ver 
= wxWINDOWS_NT
; 
1228                 case VER_PLATFORM_WIN32_CE
: 
1229                     s_ver 
= wxWINDOWS_CE
; 
1236     static wxToolkitInfo info
; 
1237     info
.versionMajor 
= s_major
; 
1238     info
.versionMinor 
= s_minor
; 
1240     info
.name 
= _T("wxBase"); 
1244 wxWinVersion 
wxGetWinVersion() 
1248     switch ( wxGetOsVersion(&verMaj
, &verMin
) ) 
1256                         return wxWinVersion_95
; 
1259                         return wxWinVersion_98
; 
1262                         return wxWinVersion_ME
; 
1271                     return wxWinVersion_NT3
; 
1274                     return wxWinVersion_NT4
; 
1280                             return wxWinVersion_2000
; 
1283                             return wxWinVersion_XP
; 
1286                             return wxWinVersion_2003
; 
1291                     return wxWinVersion_NT6
; 
1297     return wxWinVersion_Unknown
; 
1300 // ---------------------------------------------------------------------------- 
1302 // ---------------------------------------------------------------------------- 
1304 void wxMilliSleep(unsigned long milliseconds
) 
1306     ::Sleep(milliseconds
); 
1309 void wxMicroSleep(unsigned long microseconds
) 
1311     wxMilliSleep(microseconds
/1000); 
1314 void wxSleep(int nSecs
) 
1316     wxMilliSleep(1000*nSecs
); 
1319 // ---------------------------------------------------------------------------- 
1320 // font encoding <-> Win32 codepage conversion functions 
1321 // ---------------------------------------------------------------------------- 
1323 extern WXDLLIMPEXP_BASE 
long wxEncodingToCharset(wxFontEncoding encoding
) 
1327         // although this function is supposed to return an exact match, do do 
1328         // some mappings here for the most common case of "standard" encoding 
1329         case wxFONTENCODING_SYSTEM
: 
1330             return DEFAULT_CHARSET
; 
1332         case wxFONTENCODING_ISO8859_1
: 
1333         case wxFONTENCODING_ISO8859_15
: 
1334         case wxFONTENCODING_CP1252
: 
1335             return ANSI_CHARSET
; 
1337 #if !defined(__WXMICROWIN__) 
1338         // The following four fonts are multi-byte charsets 
1339         case wxFONTENCODING_CP932
: 
1340             return SHIFTJIS_CHARSET
; 
1342         case wxFONTENCODING_CP936
: 
1343             return GB2312_CHARSET
; 
1346         case wxFONTENCODING_CP949
: 
1347             return HANGUL_CHARSET
; 
1350         case wxFONTENCODING_CP950
: 
1351             return CHINESEBIG5_CHARSET
; 
1353         // The rest are single byte encodings 
1354         case wxFONTENCODING_CP1250
: 
1355             return EASTEUROPE_CHARSET
; 
1357         case wxFONTENCODING_CP1251
: 
1358             return RUSSIAN_CHARSET
; 
1360         case wxFONTENCODING_CP1253
: 
1361             return GREEK_CHARSET
; 
1363         case wxFONTENCODING_CP1254
: 
1364             return TURKISH_CHARSET
; 
1366         case wxFONTENCODING_CP1255
: 
1367             return HEBREW_CHARSET
; 
1369         case wxFONTENCODING_CP1256
: 
1370             return ARABIC_CHARSET
; 
1372         case wxFONTENCODING_CP1257
: 
1373             return BALTIC_CHARSET
; 
1375         case wxFONTENCODING_CP874
: 
1376             return THAI_CHARSET
; 
1377 #endif // !__WXMICROWIN__ 
1379         case wxFONTENCODING_CP437
: 
1383             // no way to translate this encoding into a Windows charset 
1388 // we have 2 versions of wxCharsetToCodepage(): the old one which directly 
1389 // looks up the vlaues in the registry and the new one which is more 
1390 // politically correct and has more chances to work on other Windows versions 
1391 // as well but the old version is still needed for !wxUSE_FONTMAP case 
1394 #include "wx/fontmap.h" 
1396 extern WXDLLIMPEXP_BASE 
long wxEncodingToCodepage(wxFontEncoding encoding
) 
1398     // There don't seem to be symbolic names for 
1399     // these under Windows so I just copied the 
1400     // values from MSDN. 
1406         case wxFONTENCODING_ISO8859_1
:      ret 
= 28591; break; 
1407         case wxFONTENCODING_ISO8859_2
:      ret 
= 28592; break; 
1408         case wxFONTENCODING_ISO8859_3
:      ret 
= 28593; break; 
1409         case wxFONTENCODING_ISO8859_4
:      ret 
= 28594; break; 
1410         case wxFONTENCODING_ISO8859_5
:      ret 
= 28595; break; 
1411         case wxFONTENCODING_ISO8859_6
:      ret 
= 28596; break; 
1412         case wxFONTENCODING_ISO8859_7
:      ret 
= 28597; break; 
1413         case wxFONTENCODING_ISO8859_8
:      ret 
= 28598; break; 
1414         case wxFONTENCODING_ISO8859_9
:      ret 
= 28599; break; 
1415         case wxFONTENCODING_ISO8859_10
:     ret 
= 28600; break; 
1416         case wxFONTENCODING_ISO8859_11
:     ret 
= 28601; break; 
1417         // case wxFONTENCODING_ISO8859_12,      // doesn't exist currently, but put it 
1418         case wxFONTENCODING_ISO8859_13
:     ret 
= 28603; break; 
1419         case wxFONTENCODING_ISO8859_14
:     ret 
= 28604; break; 
1420         case wxFONTENCODING_ISO8859_15
:     ret 
= 28605; break; 
1421         case wxFONTENCODING_KOI8
:           ret 
= 20866; break; 
1422         case wxFONTENCODING_KOI8_U
:         ret 
= 21866; break; 
1423         case wxFONTENCODING_CP437
:          ret 
= 437; break; 
1424         case wxFONTENCODING_CP850
:          ret 
= 850; break; 
1425         case wxFONTENCODING_CP852
:          ret 
= 852; break; 
1426         case wxFONTENCODING_CP855
:          ret 
= 855; break; 
1427         case wxFONTENCODING_CP866
:          ret 
= 866; break; 
1428         case wxFONTENCODING_CP874
:          ret 
= 874; break; 
1429         case wxFONTENCODING_CP932
:          ret 
= 932; break; 
1430         case wxFONTENCODING_CP936
:          ret 
= 936; break; 
1431         case wxFONTENCODING_CP949
:          ret 
= 949; break; 
1432         case wxFONTENCODING_CP950
:          ret 
= 950; break; 
1433         case wxFONTENCODING_CP1250
:         ret 
= 1250; break; 
1434         case wxFONTENCODING_CP1251
:         ret 
= 1251; break; 
1435         case wxFONTENCODING_CP1252
:         ret 
= 1252; break; 
1436         case wxFONTENCODING_CP1253
:         ret 
= 1253; break; 
1437         case wxFONTENCODING_CP1254
:         ret 
= 1254; break; 
1438         case wxFONTENCODING_CP1255
:         ret 
= 1255; break; 
1439         case wxFONTENCODING_CP1256
:         ret 
= 1256; break; 
1440         case wxFONTENCODING_CP1257
:         ret 
= 1257; break; 
1441         case wxFONTENCODING_EUC_JP
:         ret 
= 20932; break; 
1442         case wxFONTENCODING_MACROMAN
:       ret 
= 10000; break; 
1443         case wxFONTENCODING_MACJAPANESE
:    ret 
= 10001; break; 
1444         case wxFONTENCODING_MACCHINESETRAD
: ret 
= 10002; break; 
1445         case wxFONTENCODING_MACKOREAN
:      ret 
= 10003; break; 
1446         case wxFONTENCODING_MACARABIC
:      ret 
= 10004; break; 
1447         case wxFONTENCODING_MACHEBREW
:      ret 
= 10005; break; 
1448         case wxFONTENCODING_MACGREEK
:       ret 
= 10006; break; 
1449         case wxFONTENCODING_MACCYRILLIC
:    ret 
= 10007; break; 
1450         case wxFONTENCODING_MACTHAI
:        ret 
= 10021; break; 
1451         case wxFONTENCODING_MACCHINESESIMP
: ret 
= 10008; break; 
1452         case wxFONTENCODING_MACCENTRALEUR
:  ret 
= 10029; break; 
1453         case wxFONTENCODING_MACCROATIAN
:    ret 
= 10082; break; 
1454         case wxFONTENCODING_MACICELANDIC
:   ret 
= 10079; break; 
1455         case wxFONTENCODING_MACROMANIAN
:    ret 
= 10009; break; 
1456         case wxFONTENCODING_UTF7
:           ret 
= 65000; break; 
1457         case wxFONTENCODING_UTF8
:           ret 
= 65001; break; 
1461     if (::IsValidCodePage(ret
) == 0) 
1465     if (::GetCPInfo(ret
, &info
) == 0) 
1471 extern long wxCharsetToCodepage(const wxChar 
*name
) 
1473     // first get the font encoding for this charset 
1477     wxFontEncoding enc 
= wxFontMapperBase::Get()->CharsetToEncoding(name
, false); 
1478     if ( enc 
== wxFONTENCODING_SYSTEM 
) 
1481     // the use the helper function 
1482     return wxEncodingToCodepage(enc
); 
1485 #else // !wxUSE_FONTMAP 
1487 #include "wx/msw/registry.h" 
1489 // this should work if Internet Exploiter is installed 
1490 extern long wxCharsetToCodepage(const wxChar 
*name
) 
1497     wxString 
path(wxT("MIME\\Database\\Charset\\")); 
1500     // follow the alias loop 
1503         wxRegKey 
key(wxRegKey::HKCR
, path 
+ cn
); 
1508         // two cases: either there's an AliasForCharset string, 
1509         // or there are Codepage and InternetEncoding dwords. 
1510         // The InternetEncoding gives us the actual encoding, 
1511         // the Codepage just says which Windows character set to 
1512         // use when displaying the data. 
1513         if (key
.HasValue(wxT("InternetEncoding")) && 
1514             key
.QueryValue(wxT("InternetEncoding"), &CP
)) 
1517         // no encoding, see if it's an alias 
1518         if (!key
.HasValue(wxT("AliasForCharset")) || 
1519             !key
.QueryValue(wxT("AliasForCharset"), cn
)) 
1526 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP 
1529   Creates a hidden window with supplied window proc registering the class for 
1530   it if necesssary (i.e. the first time only). Caller is responsible for 
1531   destroying the window and unregistering the class (note that this must be 
1532   done because wxWidgets may be used as a DLL and so may be loaded/unloaded 
1533   multiple times into/from the same process so we cna't rely on automatic 
1534   Windows class unregistration). 
1536   pclassname is a pointer to a caller stored classname, which must initially be 
1537   NULL. classname is the desired wndclass classname. If function successfully 
1538   registers the class, pclassname will be set to classname. 
1540 extern "C" WXDLLIMPEXP_BASE HWND
 
1541 wxCreateHiddenWindow(LPCTSTR 
*pclassname
, LPCTSTR classname
, WNDPROC wndproc
) 
1543     wxCHECK_MSG( classname 
&& pclassname 
&& wndproc
, NULL
, 
1544                     _T("NULL parameter in wxCreateHiddenWindow") ); 
1546     // register the class fi we need to first 
1547     if ( *pclassname 
== NULL 
) 
1550         wxZeroMemory(wndclass
); 
1552         wndclass
.lpfnWndProc   
= wndproc
; 
1553         wndclass
.hInstance     
= wxGetInstance(); 
1554         wndclass
.lpszClassName 
= classname
; 
1556         if ( !::RegisterClass(&wndclass
) ) 
1558             wxLogLastError(wxT("RegisterClass() in wxCreateHiddenWindow")); 
1563         *pclassname 
= classname
; 
1566     // next create the window 
1567     HWND hwnd 
= ::CreateWindow
 
1581         wxLogLastError(wxT("CreateWindow() in wxCreateHiddenWindow"));