1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Various utilities 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21 // #pragma implementation "utils.h"   // Note: this is done in utilscmn.cpp now. 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  37     #include "wx/cursor.h" 
  41 #include "wx/msw/private.h"     // includes <windows.h> 
  43 #ifdef __GNUWIN32_OLD__ 
  44     // apparently we need to include winsock.h to get WSADATA and other stuff 
  45     // used in wxGetFullHostName() with the old mingw32 versions 
  51 #if !defined(__GNUWIN32__) && !defined(__SALFORDC__) && !defined(__WXMICROWIN__) 
  59 #if defined(__CYGWIN__) && !defined(__TWIN32__) 
  60     #include <sys/unistd.h> 
  62     #include <sys/cygwin.h> // for cygwin_conv_to_full_win32_path() 
  65 #ifdef __BORLANDC__ // Please someone tell me which version of Borland needs 
  66                     // this (3.1 I believe) and how to test for it. 
  67                     // If this works for Borland 4.0 as well, then no worries. 
  71 // VZ: there is some code using NetXXX() functions to get the full user name: 
  72 //     I don't think it's a good idea because they don't work under Win95 and 
  73 //     seem to return the same as wxGetUserId() under NT. If you really want 
  74 //     to use them, just #define USE_NET_API 
  81 #if defined(__WIN32__) && !defined(__WXMICROWIN__) 
  92     #if !(defined(_MSC_VER) && (_MSC_VER > 800)) 
  97 //// BEGIN for console support: VC++ only 
 100 #include "wx/msw/msvcrt.h" 
 104 #include "wx/ioswrap.h" 
 106 /* Need to undef new if including crtdbg.h */ 
 115 #  if defined(__WXDEBUG__) && wxUSE_GLOBAL_MEMORY_OPERATORS && wxUSE_DEBUG_NEW_ALWAYS 
 116 #  define new new(__TFILE__,__LINE__) 
 121 /// END for console support 
 123 // ---------------------------------------------------------------------------- 
 125 // ---------------------------------------------------------------------------- 
 127 // In the WIN.INI file 
 128 static const wxChar WX_SECTION
[] = wxT("wxWindows"); 
 129 static const wxChar eUSERNAME
[]  = wxT("UserName"); 
 131 // these are only used under Win16 
 132 #if !defined(__WIN32__) && !defined(__WXMICROWIN__) 
 133 static const wxChar eHOSTNAME
[]  = wxT("HostName"); 
 134 static const wxChar eUSERID
[]    = wxT("UserId"); 
 137 #ifndef __WXMICROWIN__ 
 139 // ============================================================================ 
 141 // ============================================================================ 
 143 // ---------------------------------------------------------------------------- 
 144 // get host name and related 
 145 // ---------------------------------------------------------------------------- 
 147 // Get hostname only (without domain name) 
 148 bool wxGetHostName(wxChar 
*buf
, int maxSize
) 
 150 #if defined(__WIN32__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__) 
 151     DWORD nSize 
= maxSize
; 
 152     if ( !::GetComputerName(buf
, &nSize
) ) 
 154         wxLogLastError(wxT("GetComputerName")); 
 162     const wxChar 
*default_host 
= wxT("noname"); 
 164     if ((sysname 
= wxGetenv(wxT("SYSTEM_NAME"))) == NULL
) { 
 165         GetProfileString(WX_SECTION
, eHOSTNAME
, default_host
, buf
, maxSize 
- 1); 
 167         wxStrncpy(buf
, sysname
, maxSize 
- 1); 
 168     buf
[maxSize
] = wxT('\0'); 
 169     return *buf 
? TRUE 
: FALSE
; 
 173 // get full hostname (with domain name if possible) 
 174 bool wxGetFullHostName(wxChar 
*buf
, int maxSize
) 
 176 #if defined(__WIN32__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__) && ! (defined(__GNUWIN32__) && !defined(__MINGW32__)) 
 177     // TODO should use GetComputerNameEx() when available 
 179     // the idea is that if someone had set wxUSE_SOCKETS to 0 the code 
 180     // shouldn't use winsock.dll (a.k.a. ws2_32.dll) at all so only use this 
 181     // code if we link with it anyhow 
 183     //FIXME __DIGITALMARS__ why is using sockets not properly turned off in setup.h ?? 
 184     // find which library should contain sockets for Digital Mars CE April 2003 
 185 #ifndef __DIGITALMARS__ 
 187     if ( WSAStartup(MAKEWORD(1, 1), &wsa
) == 0 ) 
 191         if ( gethostname(bufA
, WXSIZEOF(bufA
)) == 0 ) 
 193             // gethostname() won't usually include the DNS domain name, for 
 194             // this we need to work a bit more 
 195             if ( !strchr(bufA
, '.') ) 
 197                 struct hostent 
*pHostEnt 
=  gethostbyname(bufA
); 
 201                     // Windows will use DNS internally now 
 202                     pHostEnt 
= gethostbyaddr(pHostEnt
->h_addr
, 4, AF_INET
); 
 207                     host 
= wxString::FromAscii(pHostEnt
->h_name
); 
 216             wxStrncpy(buf
, host
, maxSize
); 
 221 #endif //__DIGITALMARS__ 
 223 #endif // wxUSE_SOCKETS 
 227     return wxGetHostName(buf
, maxSize
); 
 230 // Get user ID e.g. jacs 
 231 bool wxGetUserId(wxChar 
*buf
, int maxSize
) 
 233 #if defined(__WIN32__) && !defined(__win32s__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__) 
 234     DWORD nSize 
= maxSize
; 
 235     if ( ::GetUserName(buf
, &nSize
) == 0 ) 
 237         // actually, it does happen on Win9x if the user didn't log on 
 238         DWORD res 
= ::GetEnvironmentVariable(wxT("username"), buf
, maxSize
); 
 247 #else   // Win16 or Win32s 
 249     const wxChar 
*default_id 
= wxT("anonymous"); 
 251     // Can't assume we have NIS (PC-NFS) or some other ID daemon 
 253     if (  (user 
= wxGetenv(wxT("USER"))) == NULL 
&& 
 254             (user 
= wxGetenv(wxT("LOGNAME"))) == NULL 
) 
 256         // Use wxWindows configuration data (comming soon) 
 257         GetProfileString(WX_SECTION
, eUSERID
, default_id
, buf
, maxSize 
- 1); 
 261         wxStrncpy(buf
, user
, maxSize 
- 1); 
 264     return *buf 
? TRUE 
: FALSE
; 
 268 // Get user name e.g. Julian Smart 
 269 bool wxGetUserName(wxChar 
*buf
, int maxSize
) 
 271 #if wxUSE_PENWINDOWS && !defined(__WATCOMC__) && !defined(__GNUWIN32__) 
 272     extern HANDLE g_hPenWin
; // PenWindows Running? 
 275         // PenWindows Does have a user concept! 
 276         // Get the current owner of the recognizer 
 277         GetPrivateProfileString("Current", "User", default_name
, wxBuffer
, maxSize 
- 1, "PENWIN.INI"); 
 278         strncpy(buf
, wxBuffer
, maxSize 
- 1); 
 284         CHAR szUserName
[256]; 
 285         if ( !wxGetUserId(szUserName
, WXSIZEOF(szUserName
)) ) 
 288         // TODO how to get the domain name? 
 291         // the code is based on the MSDN example (also see KB article Q119670) 
 292         WCHAR wszUserName
[256];          // Unicode user name 
 293         WCHAR wszDomain
[256]; 
 296         USER_INFO_2 
*ui2
;         // User structure 
 298         // Convert ANSI user name and domain to Unicode 
 299         MultiByteToWideChar( CP_ACP
, 0, szUserName
, strlen(szUserName
)+1, 
 300                 wszUserName
, WXSIZEOF(wszUserName
) ); 
 301         MultiByteToWideChar( CP_ACP
, 0, szDomain
, strlen(szDomain
)+1, 
 302                 wszDomain
, WXSIZEOF(wszDomain
) ); 
 304         // Get the computer name of a DC for the domain. 
 305         if ( NetGetDCName( NULL
, wszDomain
, &ComputerName 
) != NERR_Success 
) 
 307             wxLogError(wxT("Can not find domain controller")); 
 312         // Look up the user on the DC 
 313         NET_API_STATUS status 
= NetUserGetInfo( (LPWSTR
)ComputerName
, 
 314                 (LPWSTR
)&wszUserName
, 
 315                 2, // level - we want USER_INFO_2 
 323             case NERR_InvalidComputer
: 
 324                 wxLogError(wxT("Invalid domain controller name.")); 
 328             case NERR_UserNotFound
: 
 329                 wxLogError(wxT("Invalid user name '%s'."), szUserName
); 
 334                 wxLogSysError(wxT("Can't get information about user")); 
 339         // Convert the Unicode full name to ANSI 
 340         WideCharToMultiByte( CP_ACP
, 0, ui2
->usri2_full_name
, -1, 
 341                 buf
, maxSize
, NULL
, NULL 
); 
 346         wxLogError(wxT("Couldn't look up full user name.")); 
 349 #else  // !USE_NET_API 
 350         // Could use NIS, MS-Mail or other site specific programs 
 351         // Use wxWindows configuration data 
 352         bool ok 
= GetProfileString(WX_SECTION
, eUSERNAME
, wxT(""), buf
, maxSize 
- 1) != 0; 
 355             ok 
= wxGetUserId(buf
, maxSize
); 
 360             wxStrncpy(buf
, wxT("Unknown User"), maxSize
); 
 368 const wxChar
* wxGetHomeDir(wxString 
*pstr
) 
 370   wxString
& strDir 
= *pstr
; 
 372   #if defined(__UNIX__) && !defined(__TWIN32__) 
 373     const wxChar 
*szHome 
= wxGetenv("HOME"); 
 374     if ( szHome 
== NULL 
) { 
 376       wxLogWarning(_("can't find user's HOME, using current directory.")); 
 382     // add a trailing slash if needed 
 383     if ( strDir
.Last() != wxT('/') ) 
 387       // Cygwin returns unix type path but that does not work well 
 388       static wxChar windowsPath
[MAX_PATH
]; 
 389       cygwin_conv_to_full_win32_path(strDir
, windowsPath
); 
 390       strDir 
= windowsPath
; 
 396       // If we have a valid HOME directory, as is used on many machines that 
 397       // have unix utilities on them, we should use that. 
 398       const wxChar 
*szHome 
= wxGetenv(wxT("HOME")); 
 400       if ( szHome 
!= NULL 
) 
 404       else // no HOME, try HOMEDRIVE/PATH 
 406           szHome 
= wxGetenv(wxT("HOMEDRIVE")); 
 407           if ( szHome 
!= NULL 
) 
 409           szHome 
= wxGetenv(wxT("HOMEPATH")); 
 411           if ( szHome 
!= NULL 
) 
 415             // the idea is that under NT these variables have default values 
 416             // of "%systemdrive%:" and "\\". As we don't want to create our 
 417             // config files in the root directory of the system drive, we will 
 418             // create it in our program's dir. However, if the user took care 
 419             // to set HOMEPATH to something other than "\\", we suppose that he 
 420             // knows what he is doing and use the supplied value. 
 421             if ( wxStrcmp(szHome
, wxT("\\")) == 0 ) 
 426       if ( strDir
.empty() ) 
 428           // If we have a valid USERPROFILE directory, as is the case in 
 429           // Windows NT, 2000 and XP, we should use that as our home directory. 
 430           szHome 
= wxGetenv(wxT("USERPROFILE")); 
 432           if ( szHome 
!= NULL 
) 
 436       if ( !strDir
.empty() ) 
 438           return strDir
.c_str(); 
 440       //else: fall back to the prograrm directory 
 442       // Win16 has no idea about home, so use the executable directory instead 
 445     // 260 was taken from windef.h 
 451     ::GetModuleFileName(::GetModuleHandle(NULL
), 
 452                         strPath
.GetWriteBuf(MAX_PATH
), MAX_PATH
); 
 453     strPath
.UngetWriteBuf(); 
 455     // extract the dir name 
 456     wxSplitPath(strPath
, &strDir
, NULL
, NULL
); 
 460   return strDir
.c_str(); 
 463 wxChar 
*wxGetUserHome(const wxString
& WXUNUSED(user
)) 
 465     // VZ: the old code here never worked for user != "" anyhow! Moreover, it 
 466     //     returned sometimes a malloc()'d pointer, sometimes a pointer to a 
 467     //     static buffer and sometimes I don't even know what. 
 468     static wxString s_home
; 
 470     return (wxChar 
*)wxGetHomeDir(&s_home
); 
 473 bool wxDirExists(const wxString
& dir
) 
 475 #ifdef __WXMICROWIN__ 
 476     return wxPathExist(dir
); 
 477 #elif defined(__WIN32__) 
 478     DWORD attribs 
= GetFileAttributes(dir
); 
 479     return ((attribs 
!= (DWORD
)-1) && (attribs 
& FILE_ATTRIBUTE_DIRECTORY
)); 
 482         struct ffblk fileInfo
; 
 484         struct find_t fileInfo
; 
 486     // In Borland findfirst has a different argument 
 487     // ordering from _dos_findfirst. But _dos_findfirst 
 488     // _should_ be ok in both MS and Borland... why not? 
 490         return (findfirst(dir
, &fileInfo
, _A_SUBDIR
) == 0 && 
 491                (fileInfo
.ff_attrib 
& _A_SUBDIR
) != 0); 
 493         return (_dos_findfirst(dir
, _A_SUBDIR
, &fileInfo
) == 0) && 
 494                ((fileInfo
.attrib 
& _A_SUBDIR
) != 0); 
 499 bool wxGetDiskSpace(const wxString
& path
, wxLongLong 
*pTotal
, wxLongLong 
*pFree
) 
 504 // old w32api don't have ULARGE_INTEGER 
 505 #if defined(__WIN32__) && \ 
 506     (!defined(__GNUWIN32__) || wxCHECK_W32API_VERSION( 0, 3 )) 
 507     // GetDiskFreeSpaceEx() is not available under original Win95, check for 
 509     typedef BOOL (WINAPI 
*GetDiskFreeSpaceEx_t
)(LPCTSTR
, 
 515         pGetDiskFreeSpaceEx 
= (GetDiskFreeSpaceEx_t
)::GetProcAddress
 
 517                                 ::GetModuleHandle(_T("kernel32.dll")), 
 519                                 "GetDiskFreeSpaceExW" 
 521                                 "GetDiskFreeSpaceExA" 
 525     if ( pGetDiskFreeSpaceEx 
) 
 527         ULARGE_INTEGER bytesFree
, bytesTotal
; 
 529         // may pass the path as is, GetDiskFreeSpaceEx() is smart enough 
 530         if ( !pGetDiskFreeSpaceEx(path
, 
 535             wxLogLastError(_T("GetDiskFreeSpaceEx")); 
 540         // ULARGE_INTEGER is a union of a 64 bit value and a struct containing 
 541         // two 32 bit fields which may be or may be not named - try to make it 
 542         // compile in all cases 
 543 #if defined(__BORLANDC__) && !defined(_ANONYMOUS_STRUCT) 
 550             *pTotal 
= wxLongLong(UL(bytesTotal
).HighPart
, UL(bytesTotal
).LowPart
); 
 555             *pFree 
= wxLongLong(UL(bytesFree
).HighPart
, UL(bytesFree
).LowPart
); 
 561         // there's a problem with drives larger than 2GB, GetDiskFreeSpaceEx() 
 562         // should be used instead - but if it's not available, fall back on 
 563         // GetDiskFreeSpace() nevertheless... 
 565         DWORD lSectorsPerCluster
, 
 567               lNumberOfFreeClusters
, 
 568               lTotalNumberOfClusters
; 
 570         // FIXME: this is wrong, we should extract the root drive from path 
 571         //        instead, but this is the job for wxFileName... 
 572         if ( !::GetDiskFreeSpace(path
, 
 575                                  &lNumberOfFreeClusters
, 
 576                                  &lTotalNumberOfClusters
) ) 
 578             wxLogLastError(_T("GetDiskFreeSpace")); 
 583         wxLongLong lBytesPerCluster 
= lSectorsPerCluster
; 
 584         lBytesPerCluster 
*= lBytesPerSector
; 
 588             *pTotal 
= lBytesPerCluster
; 
 589             *pTotal 
*= lTotalNumberOfClusters
; 
 594             *pFree 
= lBytesPerCluster
; 
 595             *pFree 
*= lNumberOfFreeClusters
; 
 602 // ---------------------------------------------------------------------------- 
 604 // ---------------------------------------------------------------------------- 
 606 bool wxGetEnv(const wxString
& var
, wxString 
*value
) 
 609     const wxChar
* ret 
= wxGetenv(var
); 
 620     // first get the size of the buffer 
 621     DWORD dwRet 
= ::GetEnvironmentVariable(var
, NULL
, 0); 
 624         // this means that there is no such variable 
 630         (void)::GetEnvironmentVariable(var
, value
->GetWriteBuf(dwRet
), dwRet
); 
 631         value
->UngetWriteBuf(); 
 638 bool wxSetEnv(const wxString
& var
, const wxChar 
*value
) 
 640     // some compilers have putenv() or _putenv() or _wputenv() but it's better 
 641     // to always use Win32 function directly instead of dealing with them 
 642 #if defined(__WIN32__) 
 643     if ( !::SetEnvironmentVariable(var
, value
) ) 
 645         wxLogLastError(_T("SetEnvironmentVariable")); 
 651 #else // no way to set env vars 
 656 // ---------------------------------------------------------------------------- 
 657 // process management 
 658 // ---------------------------------------------------------------------------- 
 660 // structure used to pass parameters from wxKill() to wxEnumFindByPidProc() 
 661 struct wxFindByPidParams
 
 663     wxFindByPidParams() { hwnd 
= 0; pid 
= 0; } 
 665     // the HWND used to return the result 
 668     // the PID we're looking from 
 671     DECLARE_NO_COPY_CLASS(wxFindByPidParams
) 
 674 // wxKill helper: EnumWindows() callback which is used to find the first (top 
 675 // level) window belonging to the given process 
 676 BOOL CALLBACK 
wxEnumFindByPidProc(HWND hwnd
, LPARAM lParam
) 
 679     (void)::GetWindowThreadProcessId(hwnd
, &pid
); 
 681     wxFindByPidParams 
*params 
= (wxFindByPidParams 
*)lParam
; 
 682     if ( pid 
== params
->pid 
) 
 684         // remember the window we found 
 687         // return FALSE to stop the enumeration 
 691     // continue enumeration 
 695 int wxKill(long pid
, wxSignal sig
, wxKillError 
*krc
) 
 697     // get the process handle to operate on 
 698     HANDLE hProcess 
= ::OpenProcess(SYNCHRONIZE 
| 
 700                                     PROCESS_QUERY_INFORMATION
, 
 701                                     FALSE
, // not inheritable 
 703     if ( hProcess 
== NULL 
) 
 707             if ( ::GetLastError() == ERROR_ACCESS_DENIED 
) 
 709                 *krc 
= wxKILL_ACCESS_DENIED
; 
 713                 *krc 
= wxKILL_NO_PROCESS
; 
 724             // kill the process forcefully returning -1 as error code 
 725             if ( !::TerminateProcess(hProcess
, (UINT
)-1) ) 
 727                 wxLogSysError(_("Failed to kill process %d"), pid
); 
 731                     // this is not supposed to happen if we could open the 
 741             // 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 occured 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 
 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 
 793         // as we wait for a short time, we can use just WaitForSingleObject() 
 794         // and not MsgWaitForMultipleObjects() 
 795         switch ( ::WaitForSingleObject(hProcess
, 500 /* msec */) ) 
 798                 // process terminated 
 799                 if ( !::GetExitCodeProcess(hProcess
, &rc
) ) 
 801                     wxLogLastError(_T("GetExitCodeProcess")); 
 806                 wxFAIL_MSG( _T("unexpected WaitForSingleObject() return") ); 
 810                 wxLogLastError(_T("WaitForSingleObject")); 
 825         // just to suppress the warnings about uninitialized variable 
 829     ::CloseHandle(hProcess
); 
 831     // the return code is the same as from Unix kill(): 0 if killed 
 832     // successfully or -1 on error 
 834     // be careful to interpret rc correctly: for wxSIGNONE we return success if 
 835     // the process exists, for all the other sig values -- if it doesn't 
 837             ((sig 
== wxSIGNONE
) == (rc 
== STILL_ACTIVE
)) ) 
 851 // Execute a program in an Interactive Shell 
 852 bool wxShell(const wxString
& command
) 
 854     wxChar 
*shell 
= wxGetenv(wxT("COMSPEC")); 
 856         shell 
= (wxChar
*) wxT("\\COMMAND.COM"); 
 866         // pass the command to execute to the command processor 
 867         cmd
.Printf(wxT("%s /c %s"), shell
, command
.c_str()); 
 870     return wxExecute(cmd
, wxEXEC_SYNC
) == 0; 
 873 // Shutdown or reboot the PC 
 874 bool wxShutdown(wxShutdownFlags wFlags
) 
 879     if ( wxGetOsVersion(NULL
, NULL
) == wxWINDOWS_NT 
) // if is NT or 2K 
 881         // Get a token for this process. 
 883         bOK 
= ::OpenProcessToken(GetCurrentProcess(), 
 884                                  TOKEN_ADJUST_PRIVILEGES 
| TOKEN_QUERY
, 
 888             TOKEN_PRIVILEGES tkp
; 
 890             // Get the LUID for the shutdown privilege. 
 891             ::LookupPrivilegeValue(NULL
, SE_SHUTDOWN_NAME
, 
 892                                    &tkp
.Privileges
[0].Luid
); 
 894             tkp
.PrivilegeCount 
= 1;  // one privilege to set 
 895             tkp
.Privileges
[0].Attributes 
= SE_PRIVILEGE_ENABLED
; 
 897             // Get the shutdown privilege for this process. 
 898             ::AdjustTokenPrivileges(hToken
, FALSE
, &tkp
, 0, 
 899                                     (PTOKEN_PRIVILEGES
)NULL
, 0); 
 901             // Cannot test the return value of AdjustTokenPrivileges. 
 902             bOK 
= ::GetLastError() == ERROR_SUCCESS
; 
 908         UINT flags 
= EWX_SHUTDOWN 
| EWX_FORCE
; 
 911             case wxSHUTDOWN_POWEROFF
: 
 912                 flags 
|= EWX_POWEROFF
; 
 915             case wxSHUTDOWN_REBOOT
: 
 920                 wxFAIL_MSG( _T("unknown wxShutdown() flag") ); 
 924         bOK 
= ::ExitWindowsEx(EWX_SHUTDOWN 
| EWX_FORCE 
| EWX_REBOOT
, 0) != 0; 
 933 // ---------------------------------------------------------------------------- 
 935 // ---------------------------------------------------------------------------- 
 937 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX) 
 938 long wxGetFreeMemory() 
 940 #if defined(__WIN32__) && !defined(__BORLANDC__) && !defined(__TWIN32__) 
 941     MEMORYSTATUS memStatus
; 
 942     memStatus
.dwLength 
= sizeof(MEMORYSTATUS
); 
 943     GlobalMemoryStatus(&memStatus
); 
 944     return memStatus
.dwAvailPhys
; 
 946     return (long)GetFreeSpace(0); 
 950 unsigned long wxGetProcessId() 
 953     return ::GetCurrentProcessId(); 
 962     ::MessageBeep((UINT
)-1);        // default sound 
 965 wxString 
wxGetOsDescription() 
 973     info
.dwOSVersionInfoSize 
= sizeof(OSVERSIONINFO
); 
 974     if ( ::GetVersionEx(&info
) ) 
 976         switch ( info
.dwPlatformId 
) 
 978             case VER_PLATFORM_WIN32s
: 
 979                 str 
= _("Win32s on Windows 3.1"); 
 982             case VER_PLATFORM_WIN32_WINDOWS
: 
 983                 str
.Printf(_("Windows 9%c"), 
 984                            info
.dwMinorVersion 
== 0 ? _T('5') : _T('8')); 
 985                 if ( !wxIsEmpty(info
.szCSDVersion
) ) 
 987                     str 
<< _T(" (") << info
.szCSDVersion 
<< _T(')'); 
 991             case VER_PLATFORM_WIN32_NT
: 
 992                 str
.Printf(_T("Windows NT %lu.%lu (build %lu"), 
 996                 if ( !wxIsEmpty(info
.szCSDVersion
) ) 
 998                     str 
<< _T(", ") << info
.szCSDVersion
; 
1006         wxFAIL_MSG( _T("GetVersionEx() failed") ); // should never happen 
1011     return _("Windows 3.1"); 
1015 int wxGetOsVersion(int *majorVsn
, int *minorVsn
) 
1017 #if defined(__WIN32__)  
1018     static int ver 
= -1, major 
= -1, minor 
= -1; 
1026         info
.dwOSVersionInfoSize 
= sizeof(OSVERSIONINFO
); 
1027         if ( ::GetVersionEx(&info
) ) 
1029             major 
= info
.dwMajorVersion
; 
1030             minor 
= info
.dwMinorVersion
; 
1032             switch ( info
.dwPlatformId 
) 
1034                 case VER_PLATFORM_WIN32s
: 
1038                 case VER_PLATFORM_WIN32_WINDOWS
: 
1042                 case VER_PLATFORM_WIN32_NT
: 
1049     if (majorVsn 
&& major 
!= -1) 
1051     if (minorVsn 
&& minor 
!= -1) 
1056     int retValue 
= wxWINDOWS
; 
1057     #ifdef __WINDOWS_386__ 
1058         retValue 
= wxWIN386
; 
1060         #if !defined(__WATCOMC__) && !defined(GNUWIN32) && wxUSE_PENWINDOWS 
1061             extern HANDLE g_hPenWin
; 
1062             retValue 
= g_hPenWin 
? wxPENWINDOWS 
: wxWINDOWS
; 
1075 // ---------------------------------------------------------------------------- 
1077 // ---------------------------------------------------------------------------- 
1083 // Sleep for nSecs seconds. Attempt a Windows implementation using timers. 
1084 static bool gs_inTimer 
= FALSE
; 
1086 class wxSleepTimer 
: public wxTimer
 
1089     virtual void Notify() 
1096 static wxTimer 
*wxTheSleepTimer 
= NULL
; 
1098 void wxUsleep(unsigned long milliseconds
) 
1101     ::Sleep(milliseconds
); 
1105     if (miliseconds 
<= 0) 
1108     wxTheSleepTimer 
= new wxSleepTimer
; 
1110     wxTheSleepTimer
->Start(milliseconds
); 
1113         if (wxTheApp
->Pending()) 
1114             wxTheApp
->Dispatch(); 
1116     delete wxTheSleepTimer
; 
1117     wxTheSleepTimer 
= NULL
; 
1118 #endif // Win32/!Win32 
1121 void wxSleep(int nSecs
) 
1128     wxTheSleepTimer 
= new wxSleepTimer
; 
1130     wxTheSleepTimer
->Start(nSecs
*1000); 
1133         if (wxTheApp
->Pending()) 
1134             wxTheApp
->Dispatch(); 
1136     delete wxTheSleepTimer
; 
1137     wxTheSleepTimer 
= NULL
; 
1140 // Consume all events until no more left 
1141 void wxFlushEvents() 
1146 #endif // wxUSE_TIMER 
1148 #elif defined(__WIN32__) // wxUSE_GUI 
1150 void wxUsleep(unsigned long milliseconds
) 
1152     ::Sleep(milliseconds
); 
1155 void wxSleep(int nSecs
) 
1157     wxUsleep(1000*nSecs
); 
1160 #endif // wxUSE_GUI/!wxUSE_GUI 
1161 #endif // __WXMICROWIN__ 
1163 // ---------------------------------------------------------------------------- 
1164 // deprecated (in favour of wxLog) log functions 
1165 // ---------------------------------------------------------------------------- 
1167 #if WXWIN_COMPATIBILITY_2_2 
1169 // Output a debug mess., in a system dependent fashion. 
1170 #ifndef __WXMICROWIN__ 
1171 void wxDebugMsg(const wxChar 
*fmt 
...) 
1174   static wxChar buffer
[512]; 
1176   if (!wxTheApp
->GetWantDebugOutput()) 
1181   wvsprintf(buffer
,fmt
,ap
); 
1182   OutputDebugString((LPCTSTR
)buffer
); 
1187 // Non-fatal error: pop up message box and (possibly) continue 
1188 void wxError(const wxString
& msg
, const wxString
& title
) 
1190   wxSprintf(wxBuffer
, wxT("%s\nContinue?"), WXSTRINGCAST msg
); 
1191   if (MessageBox(NULL
, (LPCTSTR
)wxBuffer
, (LPCTSTR
)WXSTRINGCAST title
, 
1192              MB_ICONSTOP 
| MB_YESNO
) == IDNO
) 
1196 // Fatal error: pop up message box and abort 
1197 void wxFatalError(const wxString
& msg
, const wxString
& title
) 
1199   wxSprintf(wxBuffer
, wxT("%s: %s"), WXSTRINGCAST title
, WXSTRINGCAST msg
); 
1200   FatalAppExit(0, (LPCTSTR
)wxBuffer
); 
1202 #endif // __WXMICROWIN__ 
1204 #endif // WXWIN_COMPATIBILITY_2_2 
1208 // ---------------------------------------------------------------------------- 
1209 // functions to work with .INI files 
1210 // ---------------------------------------------------------------------------- 
1212 // Reading and writing resources (eg WIN.INI, .Xdefaults) 
1214 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, const wxString
& value
, const wxString
& file
) 
1216   if (file 
!= wxT("")) 
1217 // Don't know what the correct cast should be, but it doesn't 
1218 // compile in BC++/16-bit without this cast. 
1219 #if !defined(__WIN32__) 
1220     return (WritePrivateProfileString((const char*) section
, (const char*) entry
, (const char*) value
, (const char*) file
) != 0); 
1222     return (WritePrivateProfileString((LPCTSTR
)WXSTRINGCAST section
, (LPCTSTR
)WXSTRINGCAST entry
, (LPCTSTR
)value
, (LPCTSTR
)WXSTRINGCAST file
) != 0); 
1225     return (WriteProfileString((LPCTSTR
)WXSTRINGCAST section
, (LPCTSTR
)WXSTRINGCAST entry
, (LPCTSTR
)WXSTRINGCAST value
) != 0); 
1228 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, float value
, const wxString
& file
) 
1231     buf
.Printf(wxT("%.4f"), value
); 
1233     return wxWriteResource(section
, entry
, buf
, file
); 
1236 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, long value
, const wxString
& file
) 
1239     buf
.Printf(wxT("%ld"), value
); 
1241     return wxWriteResource(section
, entry
, buf
, file
); 
1244 bool wxWriteResource(const wxString
& section
, const wxString
& entry
, int value
, const wxString
& file
) 
1247     buf
.Printf(wxT("%d"), value
); 
1249     return wxWriteResource(section
, entry
, buf
, file
); 
1252 bool wxGetResource(const wxString
& section
, const wxString
& entry
, wxChar 
**value
, const wxString
& file
) 
1254     static const wxChar defunkt
[] = wxT("$$default"); 
1255     if (file 
!= wxT("")) 
1257         int n 
= GetPrivateProfileString((LPCTSTR
)WXSTRINGCAST section
, (LPCTSTR
)WXSTRINGCAST entry
, (LPCTSTR
)defunkt
, 
1258                 (LPTSTR
)wxBuffer
, 1000, (LPCTSTR
)WXSTRINGCAST file
); 
1259         if (n 
== 0 || wxStrcmp(wxBuffer
, defunkt
) == 0) 
1264         int n 
= GetProfileString((LPCTSTR
)WXSTRINGCAST section
, (LPCTSTR
)WXSTRINGCAST entry
, (LPCTSTR
)defunkt
, 
1265                 (LPTSTR
)wxBuffer
, 1000); 
1266         if (n 
== 0 || wxStrcmp(wxBuffer
, defunkt
) == 0) 
1269     if (*value
) delete[] (*value
); 
1270     *value 
= copystring(wxBuffer
); 
1274 bool wxGetResource(const wxString
& section
, const wxString
& entry
, float *value
, const wxString
& file
) 
1277     bool succ 
= wxGetResource(section
, entry
, (wxChar 
**)&s
, file
); 
1280         *value 
= (float)wxStrtod(s
, NULL
); 
1287 bool wxGetResource(const wxString
& section
, const wxString
& entry
, long *value
, const wxString
& file
) 
1290     bool succ 
= wxGetResource(section
, entry
, (wxChar 
**)&s
, file
); 
1293         *value 
= wxStrtol(s
, NULL
, 10); 
1300 bool wxGetResource(const wxString
& section
, const wxString
& entry
, int *value
, const wxString
& file
) 
1303     bool succ 
= wxGetResource(section
, entry
, (wxChar 
**)&s
, file
); 
1306         *value 
= (int)wxStrtol(s
, NULL
, 10); 
1312 #endif // wxUSE_RESOURCES 
1314 // --------------------------------------------------------------------------- 
1315 // helper functions for showing a "busy" cursor 
1316 // --------------------------------------------------------------------------- 
1318 static HCURSOR gs_wxBusyCursor 
= 0;     // new, busy cursor 
1319 static HCURSOR gs_wxBusyCursorOld 
= 0;  // old cursor 
1320 static int gs_wxBusyCursorCount 
= 0; 
1322 extern HCURSOR 
wxGetCurrentBusyCursor() 
1324     return gs_wxBusyCursor
; 
1327 // Set the cursor to the busy cursor for all windows 
1328 void wxBeginBusyCursor(wxCursor 
*cursor
) 
1330     if ( gs_wxBusyCursorCount
++ == 0 ) 
1332         gs_wxBusyCursor 
= (HCURSOR
)cursor
->GetHCURSOR(); 
1333 #ifndef __WXMICROWIN__ 
1334         gs_wxBusyCursorOld 
= ::SetCursor(gs_wxBusyCursor
); 
1337     //else: nothing to do, already set 
1340 // Restore cursor to normal 
1341 void wxEndBusyCursor() 
1343     wxCHECK_RET( gs_wxBusyCursorCount 
> 0, 
1344                  wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()") ); 
1346     if ( --gs_wxBusyCursorCount 
== 0 ) 
1348 #ifndef __WXMICROWIN__ 
1349         ::SetCursor(gs_wxBusyCursorOld
); 
1351         gs_wxBusyCursorOld 
= 0; 
1355 // TRUE if we're between the above two calls 
1358   return gs_wxBusyCursorCount 
> 0; 
1361 // Check whether this window wants to process messages, e.g. Stop button 
1362 // in long calculations. 
1363 bool wxCheckForInterrupt(wxWindow 
*wnd
) 
1365     wxCHECK( wnd
, FALSE 
); 
1368     while ( ::PeekMessage(&msg
, GetHwndOf(wnd
), 0, 0, PM_REMOVE
) ) 
1370         ::TranslateMessage(&msg
); 
1371         ::DispatchMessage(&msg
); 
1377 // MSW only: get user-defined resource from the .res file. 
1378 // Returns NULL or newly-allocated memory, so use delete[] to clean up. 
1380 #ifndef __WXMICROWIN__ 
1381 wxChar 
*wxLoadUserResource(const wxString
& resourceName
, const wxString
& resourceType
) 
1383     HRSRC hResource 
= ::FindResource(wxGetInstance(), resourceName
, resourceType
); 
1384     if ( hResource 
== 0 ) 
1387     HGLOBAL hData 
= ::LoadResource(wxGetInstance(), hResource
); 
1391     wxChar 
*theText 
= (wxChar 
*)::LockResource(hData
); 
1395     // Not all compilers put a zero at the end of the resource (e.g. BC++ doesn't). 
1396     // so we need to find the length of the resource. 
1397     int len 
= ::SizeofResource(wxGetInstance(), hResource
); 
1398     wxChar  
*s 
= new wxChar
[len
+1]; 
1399     wxStrncpy(s
,theText
,len
); 
1402     // wxChar *s = copystring(theText); 
1404     // Obsolete in WIN32 
1406     UnlockResource(hData
); 
1410     //  GlobalFree(hData); 
1414 #endif // __WXMICROWIN__ 
1416 // ---------------------------------------------------------------------------- 
1418 // ---------------------------------------------------------------------------- 
1420 // See also the wxGetMousePosition in window.cpp 
1421 // Deprecated: use wxPoint wxGetMousePosition() instead 
1422 void wxGetMousePosition( int* x
, int* y 
) 
1425     GetCursorPos( & pt 
); 
1430 // Return TRUE if we have a colour display 
1431 bool wxColourDisplay() 
1433 #ifdef __WXMICROWIN__ 
1437     // this function is called from wxDC ctor so it is called a *lot* of times 
1438     // hence we optimize it a bit but doign the check only once 
1440     // this should be MT safe as only the GUI thread (holding the GUI mutex) 
1442     static int s_isColour 
= -1; 
1444     if ( s_isColour 
== -1 ) 
1447         int noCols 
= ::GetDeviceCaps(dc
, NUMCOLORS
); 
1449         s_isColour 
= (noCols 
== -1) || (noCols 
> 2); 
1452     return s_isColour 
!= 0; 
1456 // Returns depth of screen 
1457 int wxDisplayDepth() 
1460     return GetDeviceCaps(dc
, PLANES
) * GetDeviceCaps(dc
, BITSPIXEL
); 
1463 // Get size of display 
1464 void wxDisplaySize(int *width
, int *height
) 
1466 #ifdef __WXMICROWIN__ 
1468     HWND hWnd 
= GetDesktopWindow(); 
1469     ::GetWindowRect(hWnd
, & rect
); 
1472         *width 
= rect
.right 
- rect
.left
; 
1474         *height 
= rect
.bottom 
- rect
.top
; 
1475 #else // !__WXMICROWIN__ 
1479         *width 
= ::GetDeviceCaps(dc
, HORZRES
); 
1481         *height 
= ::GetDeviceCaps(dc
, VERTRES
); 
1482 #endif // __WXMICROWIN__/!__WXMICROWIN__ 
1485 void wxDisplaySizeMM(int *width
, int *height
) 
1487 #ifdef __WXMICROWIN__ 
1497         *width 
= ::GetDeviceCaps(dc
, HORZSIZE
); 
1499         *height 
= ::GetDeviceCaps(dc
, VERTSIZE
); 
1503 void wxClientDisplayRect(int *x
, int *y
, int *width
, int *height
) 
1505 #if defined(__WIN16__) || defined(__WXMICROWIN__) 
1507     wxDisplaySize(width
, height
); 
1509     // Determine the desktop dimensions minus the taskbar and any other 
1510     // special decorations... 
1513     SystemParametersInfo(SPI_GETWORKAREA
, 0, &r
, 0); 
1516     if (width
)  *width 
= r
.right 
- r
.left
; 
1517     if (height
) *height 
= r
.bottom 
- r
.top
; 
1521 // --------------------------------------------------------------------------- 
1522 // window information functions 
1523 // --------------------------------------------------------------------------- 
1525 wxString WXDLLEXPORT 
wxGetWindowText(WXHWND hWnd
) 
1531         int len 
= GetWindowTextLength((HWND
)hWnd
) + 1; 
1532         ::GetWindowText((HWND
)hWnd
, str
.GetWriteBuf(len
), len
); 
1533         str
.UngetWriteBuf(); 
1539 wxString WXDLLEXPORT 
wxGetWindowClass(WXHWND hWnd
) 
1544 #ifndef __WXMICROWIN__ 
1547         int len 
= 256; // some starting value 
1551             int count 
= ::GetClassName((HWND
)hWnd
, str
.GetWriteBuf(len
), len
); 
1553             str
.UngetWriteBuf(); 
1556                 // the class name might have been truncated, retry with larger 
1566 #endif // !__WXMICROWIN__ 
1571 WXWORD WXDLLEXPORT 
wxGetWindowId(WXHWND hWnd
) 
1574     return (WXWORD
)GetWindowWord((HWND
)hWnd
, GWW_ID
); 
1576     return (WXWORD
)GetWindowLong((HWND
)hWnd
, GWL_ID
); 
1580 // ---------------------------------------------------------------------------- 
1582 // ---------------------------------------------------------------------------- 
1584 extern void PixelToHIMETRIC(LONG 
*x
, LONG 
*y
) 
1588     int iWidthMM 
= GetDeviceCaps(hdcRef
, HORZSIZE
), 
1589         iHeightMM 
= GetDeviceCaps(hdcRef
, VERTSIZE
), 
1590         iWidthPels 
= GetDeviceCaps(hdcRef
, HORZRES
), 
1591         iHeightPels 
= GetDeviceCaps(hdcRef
, VERTRES
); 
1593     *x 
*= (iWidthMM 
* 100); 
1595     *y 
*= (iHeightMM 
* 100); 
1599 extern void HIMETRICToPixel(LONG 
*x
, LONG 
*y
) 
1603     int iWidthMM 
= GetDeviceCaps(hdcRef
, HORZSIZE
), 
1604         iHeightMM 
= GetDeviceCaps(hdcRef
, VERTSIZE
), 
1605         iWidthPels 
= GetDeviceCaps(hdcRef
, HORZRES
), 
1606         iHeightPels 
= GetDeviceCaps(hdcRef
, VERTRES
); 
1609     *x 
/= (iWidthMM 
* 100); 
1611     *y 
/= (iHeightMM 
* 100); 
1616 #ifdef __WXMICROWIN__ 
1617 int wxGetOsVersion(int *majorVsn
, int *minorVsn
) 
1620     if (majorVsn
) *majorVsn 
= 0; 
1621     if (minorVsn
) *minorVsn 
= 0; 
1624 #endif // __WXMICROWIN__ 
1626 // ---------------------------------------------------------------------------- 
1627 // Win32 codepage conversion functions 
1628 // ---------------------------------------------------------------------------- 
1630 #if defined(__WIN32__) && !defined(__WXMICROWIN__) 
1632 // wxGetNativeFontEncoding() doesn't exist neither in wxBase nor in wxUniv 
1633 #if wxUSE_GUI && !defined(__WXUNIVERSAL__) 
1635 #include "wx/fontmap.h" 
1637 // VZ: the new version of wxCharsetToCodepage() is more politically correct 
1638 //     and should work on other Windows versions as well but the old version is 
1639 //     still needed for !wxUSE_FONTMAP || !wxUSE_GUI case 
1641 extern long wxEncodingToCodepage(wxFontEncoding encoding
) 
1643     // translate encoding into the Windows CHARSET 
1644     wxNativeEncodingInfo natveEncInfo
; 
1645     if ( !wxGetNativeFontEncoding(encoding
, &natveEncInfo
) ) 
1648     // translate CHARSET to code page 
1649     CHARSETINFO csetInfo
; 
1650     if ( !::TranslateCharsetInfo((DWORD 
*)(DWORD
)natveEncInfo
.charset
, 
1654         wxLogLastError(_T("TranslateCharsetInfo(TCI_SRCCHARSET)")); 
1659     return csetInfo
.ciACP
; 
1664 extern long wxCharsetToCodepage(const wxChar 
*name
) 
1666     // first get the font encoding for this charset 
1670     wxFontEncoding enc 
= wxFontMapper::Get()->CharsetToEncoding(name
, FALSE
); 
1671     if ( enc 
== wxFONTENCODING_SYSTEM 
) 
1674     // the use the helper function 
1675     return wxEncodingToCodepage(enc
); 
1678 #endif // wxUSE_FONTMAP 
1682 // include old wxCharsetToCodepage() by OK if needed 
1683 #if !wxUSE_GUI || !wxUSE_FONTMAP 
1685 #include "wx/msw/registry.h" 
1687 // this should work if Internet Exploiter is installed 
1688 extern long wxCharsetToCodepage(const wxChar 
*name
) 
1697         wxString 
path(wxT("MIME\\Database\\Charset\\")); 
1699         wxRegKey 
key(wxRegKey::HKCR
, path
); 
1701         if (!key
.Exists()) break; 
1703         // two cases: either there's an AliasForCharset string, 
1704         // or there are Codepage and InternetEncoding dwords. 
1705         // The InternetEncoding gives us the actual encoding, 
1706         // the Codepage just says which Windows character set to 
1707         // use when displaying the data. 
1708         if (key
.HasValue(wxT("InternetEncoding")) && 
1709             key
.QueryValue(wxT("InternetEncoding"), &CP
)) break; 
1711         // no encoding, see if it's an alias 
1712         if (!key
.HasValue(wxT("AliasForCharset")) || 
1713             !key
.QueryValue(wxT("AliasForCharset"), cn
)) break; 
1719 #endif // !wxUSE_GUI || !wxUSE_FONTMAP