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"
34 #include "wx/msw/registry.h"
35 #include "wx/apptrait.h"
36 #include "wx/dynlib.h"
37 #include "wx/dynload.h"
38 #include "wx/scopeguard.h"
40 #include "wx/confbase.h" // for wxExpandEnvVars()
42 #include "wx/msw/private.h" // includes <windows.h>
43 #include "wx/msw/missing.h" // for CHARSET_HANGUL
45 #if defined(__CYGWIN__)
46 //CYGWIN gives annoying warning about runtime stuff if we don't do this
47 # define USE_SYS_TYPES_FD_SET
48 # include <sys/types.h>
51 // Doesn't work with Cygwin at present
52 #if wxUSE_SOCKETS && (defined(__GNUWIN32_OLD__) || defined(__WXWINCE__) || defined(__CYGWIN32__))
53 // apparently we need to include winsock.h to get WSADATA and other stuff
54 // used in wxGetFullHostName() with the old mingw32 versions
58 #if !defined(__GNUWIN32__) && !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 #if (!defined(USE_NET_API) && !defined(__WXWINCE__)) || defined(__WXMICROWIN__)
113 static const wxChar WX_SECTION
[] = wxT("wxWindows");
116 #if (!defined(USE_NET_API) && !defined(__WXWINCE__))
117 static const wxChar eUSERNAME
[] = wxT("UserName");
120 // ============================================================================
122 // ============================================================================
124 // ----------------------------------------------------------------------------
125 // get host name and related
126 // ----------------------------------------------------------------------------
128 // Get hostname only (without domain name)
129 bool wxGetHostName(wxChar
*WXUNUSED_IN_WINCE(buf
),
130 int WXUNUSED_IN_WINCE(maxSize
))
132 #if defined(__WXWINCE__)
136 DWORD nSize
= maxSize
;
137 if ( !::GetComputerName(buf
, &nSize
) )
139 wxLogLastError(wxT("GetComputerName"));
148 // get full hostname (with domain name if possible)
149 bool wxGetFullHostName(wxChar
*buf
, int maxSize
)
151 #if !defined( __WXMICROWIN__) && wxUSE_DYNLIB_CLASS && wxUSE_SOCKETS
152 // TODO should use GetComputerNameEx() when available
154 // we don't want to always link with Winsock DLL as we might not use it at
155 // all, so load it dynamically here if needed (and don't complain if it is
156 // missing, we handle this)
159 wxDynamicLibrary
dllWinsock(_T("ws2_32.dll"), wxDL_VERBATIM
);
160 if ( dllWinsock
.IsLoaded() )
162 typedef int (PASCAL
*WSAStartup_t
)(WORD
, WSADATA
*);
163 typedef int (PASCAL
*gethostname_t
)(char *, int);
164 typedef hostent
* (PASCAL
*gethostbyname_t
)(const char *);
165 typedef hostent
* (PASCAL
*gethostbyaddr_t
)(const char *, int , int);
166 typedef int (PASCAL
*WSACleanup_t
)(void);
168 #define LOAD_WINSOCK_FUNC(func) \
170 pfn ## func = (func ## _t)dllWinsock.GetSymbol(_T(#func))
172 LOAD_WINSOCK_FUNC(WSAStartup
);
175 if ( pfnWSAStartup
&& pfnWSAStartup(MAKEWORD(1, 1), &wsa
) == 0 )
177 LOAD_WINSOCK_FUNC(gethostname
);
180 if ( pfngethostname
)
183 if ( pfngethostname(bufA
, WXSIZEOF(bufA
)) == 0 )
185 // gethostname() won't usually include the DNS domain name,
186 // for this we need to work a bit more
187 if ( !strchr(bufA
, '.') )
189 LOAD_WINSOCK_FUNC(gethostbyname
);
191 struct hostent
*pHostEnt
= pfngethostbyname
192 ? pfngethostbyname(bufA
)
197 // Windows will use DNS internally now
198 LOAD_WINSOCK_FUNC(gethostbyaddr
);
200 pHostEnt
= pfngethostbyaddr
201 ? pfngethostbyaddr(pHostEnt
->h_addr
,
208 host
= wxString::FromAscii(pHostEnt
->h_name
);
214 LOAD_WINSOCK_FUNC(WSACleanup
);
221 wxStrlcpy(buf
, host
, maxSize
);
227 #endif // !__WXMICROWIN__
229 return wxGetHostName(buf
, maxSize
);
232 // Get user ID e.g. jacs
233 bool wxGetUserId(wxChar
*WXUNUSED_IN_WINCE(buf
),
234 int WXUNUSED_IN_WINCE(maxSize
))
236 #if defined(__WXWINCE__)
240 DWORD nSize
= maxSize
;
241 if ( ::GetUserName(buf
, &nSize
) == 0 )
243 // actually, it does happen on Win9x if the user didn't log on
244 DWORD res
= ::GetEnvironmentVariable(wxT("username"), buf
, maxSize
);
256 // Get user name e.g. Julian Smart
257 bool wxGetUserName(wxChar
*buf
, int maxSize
)
259 wxCHECK_MSG( buf
&& ( maxSize
> 0 ), false,
260 _T("empty buffer in wxGetUserName") );
261 #if defined(__WXWINCE__) && wxUSE_REGKEY
263 wxRegKey
key(wxRegKey::HKCU
, wxT("ControlPanel\\Owner"));
264 if(!key
.Open(wxRegKey::Read
))
267 if(!key
.QueryValue(wxT("Owner"),name
))
269 wxStrlcpy(buf
, name
.c_str(), maxSize
);
271 #elif defined(USE_NET_API)
272 CHAR szUserName
[256];
273 if ( !wxGetUserId(szUserName
, WXSIZEOF(szUserName
)) )
276 // TODO how to get the domain name?
279 // the code is based on the MSDN example (also see KB article Q119670)
280 WCHAR wszUserName
[256]; // Unicode user name
281 WCHAR wszDomain
[256];
284 USER_INFO_2
*ui2
; // User structure
286 // Convert ANSI user name and domain to Unicode
287 MultiByteToWideChar( CP_ACP
, 0, szUserName
, strlen(szUserName
)+1,
288 wszUserName
, WXSIZEOF(wszUserName
) );
289 MultiByteToWideChar( CP_ACP
, 0, szDomain
, strlen(szDomain
)+1,
290 wszDomain
, WXSIZEOF(wszDomain
) );
292 // Get the computer name of a DC for the domain.
293 if ( NetGetDCName( NULL
, wszDomain
, &ComputerName
) != NERR_Success
)
295 wxLogError(wxT("Can not find domain controller"));
300 // Look up the user on the DC
301 NET_API_STATUS status
= NetUserGetInfo( (LPWSTR
)ComputerName
,
302 (LPWSTR
)&wszUserName
,
303 2, // level - we want USER_INFO_2
311 case NERR_InvalidComputer
:
312 wxLogError(wxT("Invalid domain controller name."));
316 case NERR_UserNotFound
:
317 wxLogError(wxT("Invalid user name '%s'."), szUserName
);
322 wxLogSysError(wxT("Can't get information about user"));
327 // Convert the Unicode full name to ANSI
328 WideCharToMultiByte( CP_ACP
, 0, ui2
->usri2_full_name
, -1,
329 buf
, maxSize
, NULL
, NULL
);
334 wxLogError(wxT("Couldn't look up full user name."));
337 #else // !USE_NET_API
338 // Could use NIS, MS-Mail or other site specific programs
339 // Use wxWidgets configuration data
340 bool ok
= GetProfileString(WX_SECTION
, eUSERNAME
, wxEmptyString
, buf
, maxSize
- 1) != 0;
343 ok
= wxGetUserId(buf
, maxSize
);
348 wxStrlcpy(buf
, wxT("Unknown User"), maxSize
);
355 const wxChar
* wxGetHomeDir(wxString
*pstr
)
357 wxString
& strDir
= *pstr
;
359 // first branch is for Cygwin
360 #if defined(__UNIX__) && !defined(__WINE__)
361 const wxChar
*szHome
= wxGetenv("HOME");
362 if ( szHome
== NULL
) {
364 wxLogWarning(_("can't find user's HOME, using current directory."));
370 // add a trailing slash if needed
371 if ( strDir
.Last() != wxT('/') )
375 // Cygwin returns unix type path but that does not work well
376 static wxChar windowsPath
[MAX_PATH
];
377 cygwin_conv_to_full_win32_path(strDir
, windowsPath
);
378 strDir
= windowsPath
;
380 #elif defined(__WXWINCE__)
385 // If we have a valid HOME directory, as is used on many machines that
386 // have unix utilities on them, we should use that.
387 const wxChar
*szHome
= wxGetenv(wxT("HOME"));
389 if ( szHome
!= NULL
)
393 else // no HOME, try HOMEDRIVE/PATH
395 szHome
= wxGetenv(wxT("HOMEDRIVE"));
396 if ( szHome
!= NULL
)
398 szHome
= wxGetenv(wxT("HOMEPATH"));
400 if ( szHome
!= NULL
)
404 // the idea is that under NT these variables have default values
405 // of "%systemdrive%:" and "\\". As we don't want to create our
406 // config files in the root directory of the system drive, we will
407 // create it in our program's dir. However, if the user took care
408 // to set HOMEPATH to something other than "\\", we suppose that he
409 // knows what he is doing and use the supplied value.
410 if ( wxStrcmp(szHome
, wxT("\\")) == 0 )
415 if ( strDir
.empty() )
417 // If we have a valid USERPROFILE directory, as is the case in
418 // Windows NT, 2000 and XP, we should use that as our home directory.
419 szHome
= wxGetenv(wxT("USERPROFILE"));
421 if ( szHome
!= NULL
)
425 if ( !strDir
.empty() )
427 // sometimes the value of HOME may be "%USERPROFILE%", so reexpand the
428 // value once again, it shouldn't hurt anyhow
429 strDir
= wxExpandEnvVars(strDir
);
431 else // fall back to the program directory
433 // extract the directory component of the program file name
434 wxSplitPath(wxGetFullModuleName(), &strDir
, NULL
, NULL
);
438 return strDir
.c_str();
441 wxString
wxGetUserHome(const wxString
& user
)
445 if ( user
.empty() || user
== wxGetUserId() )
451 bool wxGetDiskSpace(const wxString
& WXUNUSED_IN_WINCE(path
),
452 wxDiskspaceSize_t
*WXUNUSED_IN_WINCE(pTotal
),
453 wxDiskspaceSize_t
*WXUNUSED_IN_WINCE(pFree
))
462 // old w32api don't have ULARGE_INTEGER
463 #if defined(__WIN32__) && \
464 (!defined(__GNUWIN32__) || wxCHECK_W32API_VERSION( 0, 3 ))
465 // GetDiskFreeSpaceEx() is not available under original Win95, check for
467 typedef BOOL (WINAPI
*GetDiskFreeSpaceEx_t
)(LPCTSTR
,
473 pGetDiskFreeSpaceEx
= (GetDiskFreeSpaceEx_t
)::GetProcAddress
475 ::GetModuleHandle(_T("kernel32.dll")),
477 "GetDiskFreeSpaceExW"
479 "GetDiskFreeSpaceExA"
483 if ( pGetDiskFreeSpaceEx
)
485 ULARGE_INTEGER bytesFree
, bytesTotal
;
487 // may pass the path as is, GetDiskFreeSpaceEx() is smart enough
488 if ( !pGetDiskFreeSpaceEx(path
.fn_str(),
493 wxLogLastError(_T("GetDiskFreeSpaceEx"));
498 // ULARGE_INTEGER is a union of a 64 bit value and a struct containing
499 // two 32 bit fields which may be or may be not named - try to make it
500 // compile in all cases
501 #if defined(__BORLANDC__) && !defined(_ANONYMOUS_STRUCT)
509 *pTotal
= wxDiskspaceSize_t(UL(bytesTotal
).HighPart
, UL(bytesTotal
).LowPart
);
511 *pTotal
= wxDiskspaceSize_t(UL(bytesTotal
).LowPart
);
518 *pFree
= wxLongLong(UL(bytesFree
).HighPart
, UL(bytesFree
).LowPart
);
520 *pFree
= wxDiskspaceSize_t(UL(bytesFree
).LowPart
);
527 // there's a problem with drives larger than 2GB, GetDiskFreeSpaceEx()
528 // should be used instead - but if it's not available, fall back on
529 // GetDiskFreeSpace() nevertheless...
531 DWORD lSectorsPerCluster
,
533 lNumberOfFreeClusters
,
534 lTotalNumberOfClusters
;
536 // FIXME: this is wrong, we should extract the root drive from path
537 // instead, but this is the job for wxFileName...
538 if ( !::GetDiskFreeSpace(path
.fn_str(),
541 &lNumberOfFreeClusters
,
542 &lTotalNumberOfClusters
) )
544 wxLogLastError(_T("GetDiskFreeSpace"));
549 wxDiskspaceSize_t lBytesPerCluster
= (wxDiskspaceSize_t
) lSectorsPerCluster
;
550 lBytesPerCluster
*= lBytesPerSector
;
554 *pTotal
= lBytesPerCluster
;
555 *pTotal
*= lTotalNumberOfClusters
;
560 *pFree
= lBytesPerCluster
;
561 *pFree
*= lNumberOfFreeClusters
;
570 // ----------------------------------------------------------------------------
572 // ----------------------------------------------------------------------------
574 bool wxGetEnv(const wxString
& WXUNUSED_IN_WINCE(var
),
575 wxString
*WXUNUSED_IN_WINCE(value
))
578 // no environment variables under CE
581 // first get the size of the buffer
582 DWORD dwRet
= ::GetEnvironmentVariable(var
.t_str(), NULL
, 0);
585 // this means that there is no such variable
591 (void)::GetEnvironmentVariable(var
.t_str(),
592 wxStringBuffer(*value
, dwRet
),
600 bool wxDoSetEnv(const wxString
& WXUNUSED_IN_WINCE(var
),
601 const wxChar
*WXUNUSED_IN_WINCE(value
))
603 // some compilers have putenv() or _putenv() or _wputenv() but it's better
604 // to always use Win32 function directly instead of dealing with them
606 // no environment variables under CE
609 if ( !::SetEnvironmentVariable(var
.t_str(), value
) )
611 wxLogLastError(_T("SetEnvironmentVariable"));
620 bool wxSetEnv(const wxString
& variable
, const wxString
& value
)
622 return wxDoSetEnv(variable
, value
.t_str());
625 bool wxUnsetEnv(const wxString
& variable
)
627 return wxDoSetEnv(variable
, NULL
);
630 // ----------------------------------------------------------------------------
631 // process management
632 // ----------------------------------------------------------------------------
634 // structure used to pass parameters from wxKill() to wxEnumFindByPidProc()
635 struct wxFindByPidParams
637 wxFindByPidParams() { hwnd
= 0; pid
= 0; }
639 // the HWND used to return the result
642 // the PID we're looking from
645 DECLARE_NO_COPY_CLASS(wxFindByPidParams
)
648 // wxKill helper: EnumWindows() callback which is used to find the first (top
649 // level) window belonging to the given process
650 BOOL CALLBACK
wxEnumFindByPidProc(HWND hwnd
, LPARAM lParam
)
653 (void)::GetWindowThreadProcessId(hwnd
, &pid
);
655 wxFindByPidParams
*params
= (wxFindByPidParams
*)lParam
;
656 if ( pid
== params
->pid
)
658 // remember the window we found
661 // return FALSE to stop the enumeration
665 // continue enumeration
669 int wxKillAllChildren(long pid
, wxSignal sig
, wxKillError
*krc
);
671 int wxKill(long pid
, wxSignal sig
, wxKillError
*krc
, int flags
)
673 if (flags
& wxKILL_CHILDREN
)
674 wxKillAllChildren(pid
, sig
, krc
);
676 // get the process handle to operate on
677 HANDLE hProcess
= ::OpenProcess(SYNCHRONIZE
|
679 PROCESS_QUERY_INFORMATION
,
680 FALSE
, // not inheritable
682 if ( hProcess
== NULL
)
686 // recognize wxKILL_ACCESS_DENIED as special because this doesn't
687 // mean that the process doesn't exist and this is important for
688 // wxProcess::Exists()
689 *krc
= ::GetLastError() == ERROR_ACCESS_DENIED
690 ? wxKILL_ACCESS_DENIED
697 wxON_BLOCK_EXIT1(::CloseHandle
, hProcess
);
703 // kill the process forcefully returning -1 as error code
704 if ( !::TerminateProcess(hProcess
, (UINT
)-1) )
706 wxLogSysError(_("Failed to kill process %d"), pid
);
710 // this is not supposed to happen if we could open the
720 // 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
768 DWORD rc
wxDUMMY_INITIALIZE(0);
771 // as we wait for a short time, we can use just WaitForSingleObject()
772 // and not MsgWaitForMultipleObjects()
773 switch ( ::WaitForSingleObject(hProcess
, 500 /* msec */) )
776 // process terminated
777 if ( !::GetExitCodeProcess(hProcess
, &rc
) )
779 wxLogLastError(_T("GetExitCodeProcess"));
784 wxFAIL_MSG( _T("unexpected WaitForSingleObject() return") );
788 wxLogLastError(_T("WaitForSingleObject"));
801 // the return code is the same as from Unix kill(): 0 if killed
802 // successfully or -1 on error
803 if ( !ok
|| rc
== STILL_ACTIVE
)
812 typedef HANDLE (WINAPI
*CreateToolhelp32Snapshot_t
)(DWORD
,DWORD
);
813 typedef BOOL (WINAPI
*Process32_t
)(HANDLE
,LPPROCESSENTRY32
);
815 CreateToolhelp32Snapshot_t lpfCreateToolhelp32Snapshot
;
816 Process32_t lpfProcess32First
, lpfProcess32Next
;
818 static void InitToolHelp32()
820 static bool s_initToolHelpDone
= false;
822 if (s_initToolHelpDone
)
825 s_initToolHelpDone
= true;
827 lpfCreateToolhelp32Snapshot
= NULL
;
828 lpfProcess32First
= NULL
;
829 lpfProcess32Next
= NULL
;
831 #if wxUSE_DYNLIB_CLASS
833 wxDynamicLibrary
dllKernel(_T("kernel32.dll"), wxDL_VERBATIM
);
835 // Get procedure addresses.
836 // We are linking to these functions of Kernel32
837 // explicitly, because otherwise a module using
838 // this code would fail to load under Windows NT,
839 // which does not have the Toolhelp32
840 // functions in the Kernel 32.
841 lpfCreateToolhelp32Snapshot
=
842 (CreateToolhelp32Snapshot_t
)dllKernel
.RawGetSymbol(_T("CreateToolhelp32Snapshot"));
845 (Process32_t
)dllKernel
.RawGetSymbol(_T("Process32First"));
848 (Process32_t
)dllKernel
.RawGetSymbol(_T("Process32Next"));
850 #endif // wxUSE_DYNLIB_CLASS
854 int wxKillAllChildren(long pid
, wxSignal sig
, wxKillError
*krc
)
861 // If not implemented for this platform (e.g. NT 4.0), silently ignore
862 if (!lpfCreateToolhelp32Snapshot
|| !lpfProcess32First
|| !lpfProcess32Next
)
865 // Take a snapshot of all processes in the system.
866 HANDLE hProcessSnap
= lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0);
867 if (hProcessSnap
== INVALID_HANDLE_VALUE
) {
873 //Fill in the size of the structure before using it.
876 pe
.dwSize
= sizeof(PROCESSENTRY32
);
878 // Walk the snapshot of the processes, and for each process,
879 // kill it if its parent is pid.
880 if (!lpfProcess32First(hProcessSnap
, &pe
)) {
881 // Can't get first process.
884 CloseHandle (hProcessSnap
);
889 if (pe
.th32ParentProcessID
== (DWORD
) pid
) {
890 if (wxKill(pe
.th32ProcessID
, sig
, krc
))
893 } while (lpfProcess32Next (hProcessSnap
, &pe
));
899 // Execute a program in an Interactive Shell
900 bool wxShell(const wxString
& command
)
907 wxChar
*shell
= wxGetenv(wxT("COMSPEC"));
909 shell
= (wxChar
*) wxT("\\COMMAND.COM");
918 // pass the command to execute to the command processor
919 cmd
.Printf(wxT("%s /c %s"), shell
, command
.c_str());
923 return wxExecute(cmd
, wxEXEC_SYNC
) == 0;
926 // Shutdown or reboot the PC
927 bool wxShutdown(int WXUNUSED_IN_WINCE(flags
))
932 #elif defined(__WIN32__)
935 if ( wxGetOsVersion(NULL
, NULL
) == wxOS_WINDOWS_NT
) // if is NT or 2K
937 // Get a token for this process.
939 bOK
= ::OpenProcessToken(GetCurrentProcess(),
940 TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
,
944 TOKEN_PRIVILEGES tkp
;
946 // Get the LUID for the shutdown privilege.
947 ::LookupPrivilegeValue(NULL
, SE_SHUTDOWN_NAME
,
948 &tkp
.Privileges
[0].Luid
);
950 tkp
.PrivilegeCount
= 1; // one privilege to set
951 tkp
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
953 // Get the shutdown privilege for this process.
954 ::AdjustTokenPrivileges(hToken
, FALSE
, &tkp
, 0,
955 (PTOKEN_PRIVILEGES
)NULL
, 0);
957 // Cannot test the return value of AdjustTokenPrivileges.
958 bOK
= ::GetLastError() == ERROR_SUCCESS
;
965 if ( flags
& wxSHUTDOWN_FORCE
)
968 flags
&= ~wxSHUTDOWN_FORCE
;
973 case wxSHUTDOWN_POWEROFF
:
974 wFlags
|= EWX_POWEROFF
;
977 case wxSHUTDOWN_REBOOT
:
978 wFlags
|= EWX_REBOOT
;
981 case wxSHUTDOWN_LOGOFF
:
982 wFlags
|= EWX_LOGOFF
;
986 wxFAIL_MSG( _T("unknown wxShutdown() flag") );
990 bOK
= ::ExitWindowsEx(wFlags
, 0) != 0;
994 #endif // WinCE/!WinCE
997 // ----------------------------------------------------------------------------
999 // ----------------------------------------------------------------------------
1001 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
1002 wxMemorySize
wxGetFreeMemory()
1004 #if defined(__WIN64__)
1005 MEMORYSTATUSEX memStatex
;
1006 memStatex
.dwLength
= sizeof (memStatex
);
1007 ::GlobalMemoryStatusEx (&memStatex
);
1008 return (wxMemorySize
)memStatex
.ullAvailPhys
;
1009 #else /* if defined(__WIN32__) */
1010 MEMORYSTATUS memStatus
;
1011 memStatus
.dwLength
= sizeof(MEMORYSTATUS
);
1012 ::GlobalMemoryStatus(&memStatus
);
1013 return (wxMemorySize
)memStatus
.dwAvailPhys
;
1017 unsigned long wxGetProcessId()
1019 return ::GetCurrentProcessId();
1025 ::MessageBeep((UINT
)-1); // default sound
1028 bool wxIsDebuggerRunning()
1030 #if wxUSE_DYNLIB_CLASS
1031 // IsDebuggerPresent() is not available under Win95, so load it dynamically
1032 wxDynamicLibrary
dll(_T("kernel32.dll"), wxDL_VERBATIM
);
1034 typedef BOOL (WINAPI
*IsDebuggerPresent_t
)();
1035 if ( !dll
.HasSymbol(_T("IsDebuggerPresent")) )
1037 // no way to know, assume no
1041 return (*(IsDebuggerPresent_t
)dll
.GetSymbol(_T("IsDebuggerPresent")))() != 0;
1047 // ----------------------------------------------------------------------------
1049 // ----------------------------------------------------------------------------
1051 // check if we're running under a server or workstation Windows system: it
1052 // returns true or false with obvious meaning as well as -1 if the system type
1053 // couldn't be determined
1055 // this function is currently private but we may want to expose it later if
1056 // it's really useful
1060 int wxIsWindowsServer()
1062 #ifdef VER_NT_WORKSTATION
1063 OSVERSIONINFOEX info
;
1066 info
.dwOSVersionInfoSize
= sizeof(info
);
1067 if ( ::GetVersionEx(reinterpret_cast<OSVERSIONINFO
*>(&info
)) )
1069 switch ( info
.wProductType
)
1071 case VER_NT_WORKSTATION
:
1075 case VER_NT_DOMAIN_CONTROLLER
:
1079 #endif // VER_NT_WORKSTATION
1084 } // anonymous namespace
1086 wxString
wxGetOsDescription()
1093 info
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
1094 if ( ::GetVersionEx(&info
) )
1096 switch ( info
.dwPlatformId
)
1098 #ifdef VER_PLATFORM_WIN32_CE
1099 case VER_PLATFORM_WIN32_CE
:
1100 str
.Printf(_("Windows CE (%d.%d)"),
1101 info
.dwMajorVersion
,
1102 info
.dwMinorVersion
);
1105 case VER_PLATFORM_WIN32s
:
1106 str
= _("Win32s on Windows 3.1");
1109 case VER_PLATFORM_WIN32_WINDOWS
:
1110 switch (info
.dwMinorVersion
)
1113 if ( info
.szCSDVersion
[1] == 'B' ||
1114 info
.szCSDVersion
[1] == 'C' )
1116 str
= _("Windows 95 OSR2");
1120 str
= _("Windows 95");
1124 if ( info
.szCSDVersion
[1] == 'B' ||
1125 info
.szCSDVersion
[1] == 'C' )
1127 str
= _("Windows 98 SE");
1131 str
= _("Windows 98");
1135 str
= _("Windows ME");
1138 str
.Printf(_("Windows 9x (%d.%d)"),
1139 info
.dwMajorVersion
,
1140 info
.dwMinorVersion
);
1143 if ( !wxIsEmpty(info
.szCSDVersion
) )
1145 str
<< _T(" (") << info
.szCSDVersion
<< _T(')');
1149 case VER_PLATFORM_WIN32_NT
:
1150 switch ( info
.dwMajorVersion
)
1153 switch ( info
.dwMinorVersion
)
1156 str
.Printf(_("Windows 2000 (build %lu"),
1157 info
.dwBuildNumber
);
1161 // we can't distinguish between XP 64 and 2003
1162 // as they both are 5.2, so examine the product
1163 // type to resolve this ambiguity
1164 if ( wxIsWindowsServer() == 1 )
1166 str
.Printf(_("Windows Server 2003 (build %lu"),
1167 info
.dwBuildNumber
);
1170 //else: must be XP, fall through
1173 str
.Printf(_("Windows XP (build %lu"),
1174 info
.dwBuildNumber
);
1180 if ( info
.dwMinorVersion
== 0 )
1182 str
.Printf(_("Windows Vista (build %lu"),
1183 info
.dwBuildNumber
);
1190 str
.Printf(_("Windows NT %lu.%lu (build %lu"),
1191 info
.dwMajorVersion
,
1192 info
.dwMinorVersion
,
1193 info
.dwBuildNumber
);
1196 if ( !wxIsEmpty(info
.szCSDVersion
) )
1198 str
<< _T(", ") << info
.szCSDVersion
;
1202 if ( wxIsPlatform64Bit() )
1203 str
<< _(", 64-bit edition");
1209 wxFAIL_MSG( _T("GetVersionEx() failed") ); // should never happen
1215 bool wxIsPlatform64Bit()
1218 return true; // 64-bit programs run only on Win64
1219 #elif wxUSE_DYNLIB_CLASS // Win32
1220 // 32-bit programs run on both 32-bit and 64-bit Windows so check
1221 typedef BOOL (WINAPI
*IsWow64Process_t
)(HANDLE
, BOOL
*);
1223 wxDynamicLibrary
dllKernel32(_T("kernel32.dll"));
1224 IsWow64Process_t pfnIsWow64Process
=
1225 (IsWow64Process_t
)dllKernel32
.RawGetSymbol(_T("IsWow64Process"));
1228 if ( pfnIsWow64Process
)
1230 pfnIsWow64Process(::GetCurrentProcess(), &wow64
);
1232 //else: running under a system without Win64 support
1234 return wow64
!= FALSE
;
1237 #endif // Win64/Win32
1240 wxOperatingSystemId
wxGetOsVersion(int *verMaj
, int *verMin
)
1244 // this may be false, true or -1 if we tried to initialize but failed
1247 wxOperatingSystemId os
;
1253 // query the OS info only once as it's not supposed to change
1254 if ( !s_version
.initialized
)
1258 info
.dwOSVersionInfoSize
= sizeof(info
);
1259 if ( ::GetVersionEx(&info
) )
1261 s_version
.initialized
= true;
1263 #if defined(__WXWINCE__)
1264 s_version
.os
= wxOS_WINDOWS_CE
;
1265 #elif defined(__WXMICROWIN__)
1266 s_version
.os
= wxOS_WINDOWS_MICRO
;
1267 #else // "normal" desktop Windows system, use run-time detection
1268 switch ( info
.dwPlatformId
)
1270 case VER_PLATFORM_WIN32_NT
:
1271 s_version
.os
= wxOS_WINDOWS_NT
;
1274 case VER_PLATFORM_WIN32_WINDOWS
:
1275 s_version
.os
= wxOS_WINDOWS_9X
;
1278 #endif // Windows versions
1280 s_version
.verMaj
= info
.dwMajorVersion
;
1281 s_version
.verMin
= info
.dwMinorVersion
;
1283 else // GetVersionEx() failed
1285 s_version
.initialized
= -1;
1289 if ( s_version
.initialized
== 1 )
1292 *verMaj
= s_version
.verMaj
;
1294 *verMin
= s_version
.verMin
;
1297 // this works even if we were not initialized successfully as the initial
1298 // values of this field is 0 which is wxOS_UNKNOWN and exactly what we need
1299 return s_version
.os
;
1302 wxWinVersion
wxGetWinVersion()
1306 switch ( wxGetOsVersion(&verMaj
, &verMin
) )
1308 case wxOS_WINDOWS_9X
:
1314 return wxWinVersion_95
;
1317 return wxWinVersion_98
;
1320 return wxWinVersion_ME
;
1325 case wxOS_WINDOWS_NT
:
1329 return wxWinVersion_NT3
;
1332 return wxWinVersion_NT4
;
1338 return wxWinVersion_2000
;
1341 return wxWinVersion_XP
;
1344 return wxWinVersion_2003
;
1349 return wxWinVersion_NT6
;
1354 // Do nothing just to silence GCC warning
1358 return wxWinVersion_Unknown
;
1361 // ----------------------------------------------------------------------------
1363 // ----------------------------------------------------------------------------
1365 void wxMilliSleep(unsigned long milliseconds
)
1367 ::Sleep(milliseconds
);
1370 void wxMicroSleep(unsigned long microseconds
)
1372 wxMilliSleep(microseconds
/1000);
1375 void wxSleep(int nSecs
)
1377 wxMilliSleep(1000*nSecs
);
1380 // ----------------------------------------------------------------------------
1381 // font encoding <-> Win32 codepage conversion functions
1382 // ----------------------------------------------------------------------------
1384 extern WXDLLIMPEXP_BASE
long wxEncodingToCharset(wxFontEncoding encoding
)
1388 // although this function is supposed to return an exact match, do do
1389 // some mappings here for the most common case of "standard" encoding
1390 case wxFONTENCODING_SYSTEM
:
1391 return DEFAULT_CHARSET
;
1393 case wxFONTENCODING_ISO8859_1
:
1394 case wxFONTENCODING_ISO8859_15
:
1395 case wxFONTENCODING_CP1252
:
1396 return ANSI_CHARSET
;
1398 #if !defined(__WXMICROWIN__)
1399 // The following four fonts are multi-byte charsets
1400 case wxFONTENCODING_CP932
:
1401 return SHIFTJIS_CHARSET
;
1403 case wxFONTENCODING_CP936
:
1404 return GB2312_CHARSET
;
1407 case wxFONTENCODING_CP949
:
1408 return HANGUL_CHARSET
;
1411 case wxFONTENCODING_CP950
:
1412 return CHINESEBIG5_CHARSET
;
1414 // The rest are single byte encodings
1415 case wxFONTENCODING_CP1250
:
1416 return EASTEUROPE_CHARSET
;
1418 case wxFONTENCODING_CP1251
:
1419 return RUSSIAN_CHARSET
;
1421 case wxFONTENCODING_CP1253
:
1422 return GREEK_CHARSET
;
1424 case wxFONTENCODING_CP1254
:
1425 return TURKISH_CHARSET
;
1427 case wxFONTENCODING_CP1255
:
1428 return HEBREW_CHARSET
;
1430 case wxFONTENCODING_CP1256
:
1431 return ARABIC_CHARSET
;
1433 case wxFONTENCODING_CP1257
:
1434 return BALTIC_CHARSET
;
1436 case wxFONTENCODING_CP874
:
1437 return THAI_CHARSET
;
1438 #endif // !__WXMICROWIN__
1440 case wxFONTENCODING_CP437
:
1444 // no way to translate this encoding into a Windows charset
1449 // we have 2 versions of wxCharsetToCodepage(): the old one which directly
1450 // looks up the vlaues in the registry and the new one which is more
1451 // politically correct and has more chances to work on other Windows versions
1452 // as well but the old version is still needed for !wxUSE_FONTMAP case
1455 #include "wx/fontmap.h"
1457 extern WXDLLIMPEXP_BASE
long wxEncodingToCodepage(wxFontEncoding encoding
)
1459 // There don't seem to be symbolic names for
1460 // these under Windows so I just copied the
1461 // values from MSDN.
1467 case wxFONTENCODING_ISO8859_1
: ret
= 28591; break;
1468 case wxFONTENCODING_ISO8859_2
: ret
= 28592; break;
1469 case wxFONTENCODING_ISO8859_3
: ret
= 28593; break;
1470 case wxFONTENCODING_ISO8859_4
: ret
= 28594; break;
1471 case wxFONTENCODING_ISO8859_5
: ret
= 28595; break;
1472 case wxFONTENCODING_ISO8859_6
: ret
= 28596; break;
1473 case wxFONTENCODING_ISO8859_7
: ret
= 28597; break;
1474 case wxFONTENCODING_ISO8859_8
: ret
= 28598; break;
1475 case wxFONTENCODING_ISO8859_9
: ret
= 28599; break;
1476 case wxFONTENCODING_ISO8859_10
: ret
= 28600; break;
1477 case wxFONTENCODING_ISO8859_11
: ret
= 874; break;
1478 // case wxFONTENCODING_ISO8859_12, // doesn't exist currently, but put it
1479 case wxFONTENCODING_ISO8859_13
: ret
= 28603; break;
1480 // case wxFONTENCODING_ISO8859_14: ret = 28604; break; // no correspondence on Windows
1481 case wxFONTENCODING_ISO8859_15
: ret
= 28605; break;
1483 case wxFONTENCODING_KOI8
: ret
= 20866; break;
1484 case wxFONTENCODING_KOI8_U
: ret
= 21866; break;
1486 case wxFONTENCODING_CP437
: ret
= 437; break;
1487 case wxFONTENCODING_CP850
: ret
= 850; break;
1488 case wxFONTENCODING_CP852
: ret
= 852; break;
1489 case wxFONTENCODING_CP855
: ret
= 855; break;
1490 case wxFONTENCODING_CP866
: ret
= 866; break;
1491 case wxFONTENCODING_CP874
: ret
= 874; break;
1492 case wxFONTENCODING_CP932
: ret
= 932; break;
1493 case wxFONTENCODING_CP936
: ret
= 936; break;
1494 case wxFONTENCODING_CP949
: ret
= 949; break;
1495 case wxFONTENCODING_CP950
: ret
= 950; break;
1496 case wxFONTENCODING_CP1250
: ret
= 1250; break;
1497 case wxFONTENCODING_CP1251
: ret
= 1251; break;
1498 case wxFONTENCODING_CP1252
: ret
= 1252; break;
1499 case wxFONTENCODING_CP1253
: ret
= 1253; break;
1500 case wxFONTENCODING_CP1254
: ret
= 1254; break;
1501 case wxFONTENCODING_CP1255
: ret
= 1255; break;
1502 case wxFONTENCODING_CP1256
: ret
= 1256; break;
1503 case wxFONTENCODING_CP1257
: ret
= 1257; break;
1505 case wxFONTENCODING_EUC_JP
: ret
= 20932; break;
1507 case wxFONTENCODING_MACROMAN
: ret
= 10000; break;
1508 case wxFONTENCODING_MACJAPANESE
: ret
= 10001; break;
1509 case wxFONTENCODING_MACCHINESETRAD
: ret
= 10002; break;
1510 case wxFONTENCODING_MACKOREAN
: ret
= 10003; break;
1511 case wxFONTENCODING_MACARABIC
: ret
= 10004; break;
1512 case wxFONTENCODING_MACHEBREW
: ret
= 10005; break;
1513 case wxFONTENCODING_MACGREEK
: ret
= 10006; break;
1514 case wxFONTENCODING_MACCYRILLIC
: ret
= 10007; break;
1515 case wxFONTENCODING_MACTHAI
: ret
= 10021; break;
1516 case wxFONTENCODING_MACCHINESESIMP
: ret
= 10008; break;
1517 case wxFONTENCODING_MACCENTRALEUR
: ret
= 10029; break;
1518 case wxFONTENCODING_MACCROATIAN
: ret
= 10082; break;
1519 case wxFONTENCODING_MACICELANDIC
: ret
= 10079; break;
1520 case wxFONTENCODING_MACROMANIAN
: ret
= 10009; break;
1522 case wxFONTENCODING_ISO2022_JP
: ret
= 50222; break;
1524 case wxFONTENCODING_UTF7
: ret
= 65000; break;
1525 case wxFONTENCODING_UTF8
: ret
= 65001; break;
1530 if (::IsValidCodePage(ret
) == 0)
1534 if (::GetCPInfo(ret
, &info
) == 0)
1540 extern long wxCharsetToCodepage(const char *name
)
1542 // first get the font encoding for this charset
1546 wxFontEncoding enc
= wxFontMapperBase::Get()->CharsetToEncoding(name
, false);
1547 if ( enc
== wxFONTENCODING_SYSTEM
)
1550 // the use the helper function
1551 return wxEncodingToCodepage(enc
);
1554 #else // !wxUSE_FONTMAP
1556 #include "wx/msw/registry.h"
1558 // this should work if Internet Exploiter is installed
1559 extern long wxCharsetToCodepage(const char *name
)
1567 wxString
path(wxT("MIME\\Database\\Charset\\"));
1570 // follow the alias loop
1573 wxRegKey
key(wxRegKey::HKCR
, path
+ cn
);
1578 // two cases: either there's an AliasForCharset string,
1579 // or there are Codepage and InternetEncoding dwords.
1580 // The InternetEncoding gives us the actual encoding,
1581 // the Codepage just says which Windows character set to
1582 // use when displaying the data.
1583 if (key
.HasValue(wxT("InternetEncoding")) &&
1584 key
.QueryValue(wxT("InternetEncoding"), &CP
))
1587 // no encoding, see if it's an alias
1588 if (!key
.HasValue(wxT("AliasForCharset")) ||
1589 !key
.QueryValue(wxT("AliasForCharset"), cn
))
1592 #endif // wxUSE_REGKEY
1597 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
1600 Creates a hidden window with supplied window proc registering the class for
1601 it if necesssary (i.e. the first time only). Caller is responsible for
1602 destroying the window and unregistering the class (note that this must be
1603 done because wxWidgets may be used as a DLL and so may be loaded/unloaded
1604 multiple times into/from the same process so we cna't rely on automatic
1605 Windows class unregistration).
1607 pclassname is a pointer to a caller stored classname, which must initially be
1608 NULL. classname is the desired wndclass classname. If function successfully
1609 registers the class, pclassname will be set to classname.
1611 extern "C" WXDLLIMPEXP_BASE HWND
1612 wxCreateHiddenWindow(LPCTSTR
*pclassname
, LPCTSTR classname
, WNDPROC wndproc
)
1614 wxCHECK_MSG( classname
&& pclassname
&& wndproc
, NULL
,
1615 _T("NULL parameter in wxCreateHiddenWindow") );
1617 // register the class fi we need to first
1618 if ( *pclassname
== NULL
)
1621 wxZeroMemory(wndclass
);
1623 wndclass
.lpfnWndProc
= wndproc
;
1624 wndclass
.hInstance
= wxGetInstance();
1625 wndclass
.lpszClassName
= classname
;
1627 if ( !::RegisterClass(&wndclass
) )
1629 wxLogLastError(wxT("RegisterClass() in wxCreateHiddenWindow"));
1634 *pclassname
= classname
;
1637 // next create the window
1638 HWND hwnd
= ::CreateWindow
1652 wxLogLastError(wxT("CreateWindow() in wxCreateHiddenWindow"));