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
.c_str(), 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 bOK
= ::LookupPrivilegeValue(NULL
, SE_SHUTDOWN_NAME
,
948 &tkp
.Privileges
[0].Luid
) != 0;
952 tkp
.PrivilegeCount
= 1; // one privilege to set
953 tkp
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
955 // Get the shutdown privilege for this process.
956 ::AdjustTokenPrivileges(hToken
, FALSE
, &tkp
, 0,
957 (PTOKEN_PRIVILEGES
)NULL
, 0);
959 // Cannot test the return value of AdjustTokenPrivileges.
960 bOK
= ::GetLastError() == ERROR_SUCCESS
;
963 ::CloseHandle(hToken
);
970 if ( flags
& wxSHUTDOWN_FORCE
)
973 flags
&= ~wxSHUTDOWN_FORCE
;
978 case wxSHUTDOWN_POWEROFF
:
979 wFlags
|= EWX_POWEROFF
;
982 case wxSHUTDOWN_REBOOT
:
983 wFlags
|= EWX_REBOOT
;
986 case wxSHUTDOWN_LOGOFF
:
987 wFlags
|= EWX_LOGOFF
;
991 wxFAIL_MSG( _T("unknown wxShutdown() flag") );
995 bOK
= ::ExitWindowsEx(wFlags
, 0) != 0;
999 #endif // WinCE/!WinCE
1002 // ----------------------------------------------------------------------------
1004 // ----------------------------------------------------------------------------
1006 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
1007 wxMemorySize
wxGetFreeMemory()
1009 #if defined(__WIN64__)
1010 MEMORYSTATUSEX memStatex
;
1011 memStatex
.dwLength
= sizeof (memStatex
);
1012 ::GlobalMemoryStatusEx (&memStatex
);
1013 return (wxMemorySize
)memStatex
.ullAvailPhys
;
1014 #else /* if defined(__WIN32__) */
1015 MEMORYSTATUS memStatus
;
1016 memStatus
.dwLength
= sizeof(MEMORYSTATUS
);
1017 ::GlobalMemoryStatus(&memStatus
);
1018 return (wxMemorySize
)memStatus
.dwAvailPhys
;
1022 unsigned long wxGetProcessId()
1024 return ::GetCurrentProcessId();
1030 ::MessageBeep((UINT
)-1); // default sound
1033 bool wxIsDebuggerRunning()
1035 #if wxUSE_DYNLIB_CLASS
1036 // IsDebuggerPresent() is not available under Win95, so load it dynamically
1037 wxDynamicLibrary
dll(_T("kernel32.dll"), wxDL_VERBATIM
);
1039 typedef BOOL (WINAPI
*IsDebuggerPresent_t
)();
1040 if ( !dll
.HasSymbol(_T("IsDebuggerPresent")) )
1042 // no way to know, assume no
1046 return (*(IsDebuggerPresent_t
)dll
.GetSymbol(_T("IsDebuggerPresent")))() != 0;
1052 // ----------------------------------------------------------------------------
1054 // ----------------------------------------------------------------------------
1056 // check if we're running under a server or workstation Windows system: it
1057 // returns true or false with obvious meaning as well as -1 if the system type
1058 // couldn't be determined
1060 // this function is currently private but we may want to expose it later if
1061 // it's really useful
1065 int wxIsWindowsServer()
1067 #ifdef VER_NT_WORKSTATION
1068 OSVERSIONINFOEX info
;
1071 info
.dwOSVersionInfoSize
= sizeof(info
);
1072 if ( ::GetVersionEx(reinterpret_cast<OSVERSIONINFO
*>(&info
)) )
1074 switch ( info
.wProductType
)
1076 case VER_NT_WORKSTATION
:
1080 case VER_NT_DOMAIN_CONTROLLER
:
1084 #endif // VER_NT_WORKSTATION
1089 } // anonymous namespace
1091 wxString
wxGetOsDescription()
1098 info
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
1099 if ( ::GetVersionEx(&info
) )
1101 switch ( info
.dwPlatformId
)
1103 #ifdef VER_PLATFORM_WIN32_CE
1104 case VER_PLATFORM_WIN32_CE
:
1105 str
.Printf(_("Windows CE (%d.%d)"),
1106 info
.dwMajorVersion
,
1107 info
.dwMinorVersion
);
1110 case VER_PLATFORM_WIN32s
:
1111 str
= _("Win32s on Windows 3.1");
1114 case VER_PLATFORM_WIN32_WINDOWS
:
1115 switch (info
.dwMinorVersion
)
1118 if ( info
.szCSDVersion
[1] == 'B' ||
1119 info
.szCSDVersion
[1] == 'C' )
1121 str
= _("Windows 95 OSR2");
1125 str
= _("Windows 95");
1129 if ( info
.szCSDVersion
[1] == 'B' ||
1130 info
.szCSDVersion
[1] == 'C' )
1132 str
= _("Windows 98 SE");
1136 str
= _("Windows 98");
1140 str
= _("Windows ME");
1143 str
.Printf(_("Windows 9x (%d.%d)"),
1144 info
.dwMajorVersion
,
1145 info
.dwMinorVersion
);
1148 if ( !wxIsEmpty(info
.szCSDVersion
) )
1150 str
<< _T(" (") << info
.szCSDVersion
<< _T(')');
1154 case VER_PLATFORM_WIN32_NT
:
1155 switch ( info
.dwMajorVersion
)
1158 switch ( info
.dwMinorVersion
)
1161 str
.Printf(_("Windows 2000 (build %lu"),
1162 info
.dwBuildNumber
);
1166 // we can't distinguish between XP 64 and 2003
1167 // as they both are 5.2, so examine the product
1168 // type to resolve this ambiguity
1169 if ( wxIsWindowsServer() == 1 )
1171 str
.Printf(_("Windows Server 2003 (build %lu"),
1172 info
.dwBuildNumber
);
1175 //else: must be XP, fall through
1178 str
.Printf(_("Windows XP (build %lu"),
1179 info
.dwBuildNumber
);
1185 if ( info
.dwMinorVersion
== 0 )
1187 str
.Printf(_("Windows Vista (build %lu"),
1188 info
.dwBuildNumber
);
1195 str
.Printf(_("Windows NT %lu.%lu (build %lu"),
1196 info
.dwMajorVersion
,
1197 info
.dwMinorVersion
,
1198 info
.dwBuildNumber
);
1201 if ( !wxIsEmpty(info
.szCSDVersion
) )
1203 str
<< _T(", ") << info
.szCSDVersion
;
1207 if ( wxIsPlatform64Bit() )
1208 str
<< _(", 64-bit edition");
1214 wxFAIL_MSG( _T("GetVersionEx() failed") ); // should never happen
1220 bool wxIsPlatform64Bit()
1223 return true; // 64-bit programs run only on Win64
1224 #elif wxUSE_DYNLIB_CLASS // Win32
1225 // 32-bit programs run on both 32-bit and 64-bit Windows so check
1226 typedef BOOL (WINAPI
*IsWow64Process_t
)(HANDLE
, BOOL
*);
1228 wxDynamicLibrary
dllKernel32(_T("kernel32.dll"));
1229 IsWow64Process_t pfnIsWow64Process
=
1230 (IsWow64Process_t
)dllKernel32
.RawGetSymbol(_T("IsWow64Process"));
1233 if ( pfnIsWow64Process
)
1235 pfnIsWow64Process(::GetCurrentProcess(), &wow64
);
1237 //else: running under a system without Win64 support
1239 return wow64
!= FALSE
;
1242 #endif // Win64/Win32
1245 wxOperatingSystemId
wxGetOsVersion(int *verMaj
, int *verMin
)
1249 // this may be false, true or -1 if we tried to initialize but failed
1252 wxOperatingSystemId os
;
1258 // query the OS info only once as it's not supposed to change
1259 if ( !s_version
.initialized
)
1263 info
.dwOSVersionInfoSize
= sizeof(info
);
1264 if ( ::GetVersionEx(&info
) )
1266 s_version
.initialized
= true;
1268 #if defined(__WXWINCE__)
1269 s_version
.os
= wxOS_WINDOWS_CE
;
1270 #elif defined(__WXMICROWIN__)
1271 s_version
.os
= wxOS_WINDOWS_MICRO
;
1272 #else // "normal" desktop Windows system, use run-time detection
1273 switch ( info
.dwPlatformId
)
1275 case VER_PLATFORM_WIN32_NT
:
1276 s_version
.os
= wxOS_WINDOWS_NT
;
1279 case VER_PLATFORM_WIN32_WINDOWS
:
1280 s_version
.os
= wxOS_WINDOWS_9X
;
1283 #endif // Windows versions
1285 s_version
.verMaj
= info
.dwMajorVersion
;
1286 s_version
.verMin
= info
.dwMinorVersion
;
1288 else // GetVersionEx() failed
1290 s_version
.initialized
= -1;
1294 if ( s_version
.initialized
== 1 )
1297 *verMaj
= s_version
.verMaj
;
1299 *verMin
= s_version
.verMin
;
1302 // this works even if we were not initialized successfully as the initial
1303 // values of this field is 0 which is wxOS_UNKNOWN and exactly what we need
1304 return s_version
.os
;
1307 wxWinVersion
wxGetWinVersion()
1311 switch ( wxGetOsVersion(&verMaj
, &verMin
) )
1313 case wxOS_WINDOWS_9X
:
1319 return wxWinVersion_95
;
1322 return wxWinVersion_98
;
1325 return wxWinVersion_ME
;
1330 case wxOS_WINDOWS_NT
:
1334 return wxWinVersion_NT3
;
1337 return wxWinVersion_NT4
;
1343 return wxWinVersion_2000
;
1346 return wxWinVersion_XP
;
1349 return wxWinVersion_2003
;
1354 return wxWinVersion_NT6
;
1359 // Do nothing just to silence GCC warning
1363 return wxWinVersion_Unknown
;
1366 // ----------------------------------------------------------------------------
1368 // ----------------------------------------------------------------------------
1370 void wxMilliSleep(unsigned long milliseconds
)
1372 ::Sleep(milliseconds
);
1375 void wxMicroSleep(unsigned long microseconds
)
1377 wxMilliSleep(microseconds
/1000);
1380 void wxSleep(int nSecs
)
1382 wxMilliSleep(1000*nSecs
);
1385 // ----------------------------------------------------------------------------
1386 // font encoding <-> Win32 codepage conversion functions
1387 // ----------------------------------------------------------------------------
1389 extern WXDLLIMPEXP_BASE
long wxEncodingToCharset(wxFontEncoding encoding
)
1393 // although this function is supposed to return an exact match, do do
1394 // some mappings here for the most common case of "standard" encoding
1395 case wxFONTENCODING_SYSTEM
:
1396 return DEFAULT_CHARSET
;
1398 case wxFONTENCODING_ISO8859_1
:
1399 case wxFONTENCODING_ISO8859_15
:
1400 case wxFONTENCODING_CP1252
:
1401 return ANSI_CHARSET
;
1403 #if !defined(__WXMICROWIN__)
1404 // The following four fonts are multi-byte charsets
1405 case wxFONTENCODING_CP932
:
1406 return SHIFTJIS_CHARSET
;
1408 case wxFONTENCODING_CP936
:
1409 return GB2312_CHARSET
;
1412 case wxFONTENCODING_CP949
:
1413 return HANGUL_CHARSET
;
1416 case wxFONTENCODING_CP950
:
1417 return CHINESEBIG5_CHARSET
;
1419 // The rest are single byte encodings
1420 case wxFONTENCODING_CP1250
:
1421 return EASTEUROPE_CHARSET
;
1423 case wxFONTENCODING_CP1251
:
1424 return RUSSIAN_CHARSET
;
1426 case wxFONTENCODING_CP1253
:
1427 return GREEK_CHARSET
;
1429 case wxFONTENCODING_CP1254
:
1430 return TURKISH_CHARSET
;
1432 case wxFONTENCODING_CP1255
:
1433 return HEBREW_CHARSET
;
1435 case wxFONTENCODING_CP1256
:
1436 return ARABIC_CHARSET
;
1438 case wxFONTENCODING_CP1257
:
1439 return BALTIC_CHARSET
;
1441 case wxFONTENCODING_CP874
:
1442 return THAI_CHARSET
;
1443 #endif // !__WXMICROWIN__
1445 case wxFONTENCODING_CP437
:
1449 // no way to translate this encoding into a Windows charset
1454 // we have 2 versions of wxCharsetToCodepage(): the old one which directly
1455 // looks up the vlaues in the registry and the new one which is more
1456 // politically correct and has more chances to work on other Windows versions
1457 // as well but the old version is still needed for !wxUSE_FONTMAP case
1460 #include "wx/fontmap.h"
1462 extern WXDLLIMPEXP_BASE
long wxEncodingToCodepage(wxFontEncoding encoding
)
1464 // There don't seem to be symbolic names for
1465 // these under Windows so I just copied the
1466 // values from MSDN.
1472 case wxFONTENCODING_ISO8859_1
: ret
= 28591; break;
1473 case wxFONTENCODING_ISO8859_2
: ret
= 28592; break;
1474 case wxFONTENCODING_ISO8859_3
: ret
= 28593; break;
1475 case wxFONTENCODING_ISO8859_4
: ret
= 28594; break;
1476 case wxFONTENCODING_ISO8859_5
: ret
= 28595; break;
1477 case wxFONTENCODING_ISO8859_6
: ret
= 28596; break;
1478 case wxFONTENCODING_ISO8859_7
: ret
= 28597; break;
1479 case wxFONTENCODING_ISO8859_8
: ret
= 28598; break;
1480 case wxFONTENCODING_ISO8859_9
: ret
= 28599; break;
1481 case wxFONTENCODING_ISO8859_10
: ret
= 28600; break;
1482 case wxFONTENCODING_ISO8859_11
: ret
= 874; break;
1483 // case wxFONTENCODING_ISO8859_12, // doesn't exist currently, but put it
1484 case wxFONTENCODING_ISO8859_13
: ret
= 28603; break;
1485 // case wxFONTENCODING_ISO8859_14: ret = 28604; break; // no correspondence on Windows
1486 case wxFONTENCODING_ISO8859_15
: ret
= 28605; break;
1488 case wxFONTENCODING_KOI8
: ret
= 20866; break;
1489 case wxFONTENCODING_KOI8_U
: ret
= 21866; break;
1491 case wxFONTENCODING_CP437
: ret
= 437; break;
1492 case wxFONTENCODING_CP850
: ret
= 850; break;
1493 case wxFONTENCODING_CP852
: ret
= 852; break;
1494 case wxFONTENCODING_CP855
: ret
= 855; break;
1495 case wxFONTENCODING_CP866
: ret
= 866; break;
1496 case wxFONTENCODING_CP874
: ret
= 874; break;
1497 case wxFONTENCODING_CP932
: ret
= 932; break;
1498 case wxFONTENCODING_CP936
: ret
= 936; break;
1499 case wxFONTENCODING_CP949
: ret
= 949; break;
1500 case wxFONTENCODING_CP950
: ret
= 950; break;
1501 case wxFONTENCODING_CP1250
: ret
= 1250; break;
1502 case wxFONTENCODING_CP1251
: ret
= 1251; break;
1503 case wxFONTENCODING_CP1252
: ret
= 1252; break;
1504 case wxFONTENCODING_CP1253
: ret
= 1253; break;
1505 case wxFONTENCODING_CP1254
: ret
= 1254; break;
1506 case wxFONTENCODING_CP1255
: ret
= 1255; break;
1507 case wxFONTENCODING_CP1256
: ret
= 1256; break;
1508 case wxFONTENCODING_CP1257
: ret
= 1257; break;
1510 case wxFONTENCODING_EUC_JP
: ret
= 20932; break;
1512 case wxFONTENCODING_MACROMAN
: ret
= 10000; break;
1513 case wxFONTENCODING_MACJAPANESE
: ret
= 10001; break;
1514 case wxFONTENCODING_MACCHINESETRAD
: ret
= 10002; break;
1515 case wxFONTENCODING_MACKOREAN
: ret
= 10003; break;
1516 case wxFONTENCODING_MACARABIC
: ret
= 10004; break;
1517 case wxFONTENCODING_MACHEBREW
: ret
= 10005; break;
1518 case wxFONTENCODING_MACGREEK
: ret
= 10006; break;
1519 case wxFONTENCODING_MACCYRILLIC
: ret
= 10007; break;
1520 case wxFONTENCODING_MACTHAI
: ret
= 10021; break;
1521 case wxFONTENCODING_MACCHINESESIMP
: ret
= 10008; break;
1522 case wxFONTENCODING_MACCENTRALEUR
: ret
= 10029; break;
1523 case wxFONTENCODING_MACCROATIAN
: ret
= 10082; break;
1524 case wxFONTENCODING_MACICELANDIC
: ret
= 10079; break;
1525 case wxFONTENCODING_MACROMANIAN
: ret
= 10009; break;
1527 case wxFONTENCODING_ISO2022_JP
: ret
= 50222; break;
1529 case wxFONTENCODING_UTF7
: ret
= 65000; break;
1530 case wxFONTENCODING_UTF8
: ret
= 65001; break;
1535 if (::IsValidCodePage(ret
) == 0)
1539 if (::GetCPInfo(ret
, &info
) == 0)
1545 extern long wxCharsetToCodepage(const char *name
)
1547 // first get the font encoding for this charset
1551 wxFontEncoding enc
= wxFontMapperBase::Get()->CharsetToEncoding(name
, false);
1552 if ( enc
== wxFONTENCODING_SYSTEM
)
1555 // the use the helper function
1556 return wxEncodingToCodepage(enc
);
1559 #else // !wxUSE_FONTMAP
1561 #include "wx/msw/registry.h"
1563 // this should work if Internet Exploiter is installed
1564 extern long wxCharsetToCodepage(const char *name
)
1572 wxString
path(wxT("MIME\\Database\\Charset\\"));
1575 // follow the alias loop
1578 wxRegKey
key(wxRegKey::HKCR
, path
+ cn
);
1583 // two cases: either there's an AliasForCharset string,
1584 // or there are Codepage and InternetEncoding dwords.
1585 // The InternetEncoding gives us the actual encoding,
1586 // the Codepage just says which Windows character set to
1587 // use when displaying the data.
1588 if (key
.HasValue(wxT("InternetEncoding")) &&
1589 key
.QueryValue(wxT("InternetEncoding"), &CP
))
1592 // no encoding, see if it's an alias
1593 if (!key
.HasValue(wxT("AliasForCharset")) ||
1594 !key
.QueryValue(wxT("AliasForCharset"), cn
))
1597 #endif // wxUSE_REGKEY
1602 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
1605 Creates a hidden window with supplied window proc registering the class for
1606 it if necesssary (i.e. the first time only). Caller is responsible for
1607 destroying the window and unregistering the class (note that this must be
1608 done because wxWidgets may be used as a DLL and so may be loaded/unloaded
1609 multiple times into/from the same process so we cna't rely on automatic
1610 Windows class unregistration).
1612 pclassname is a pointer to a caller stored classname, which must initially be
1613 NULL. classname is the desired wndclass classname. If function successfully
1614 registers the class, pclassname will be set to classname.
1616 extern "C" WXDLLIMPEXP_BASE HWND
1617 wxCreateHiddenWindow(LPCTSTR
*pclassname
, LPCTSTR classname
, WNDPROC wndproc
)
1619 wxCHECK_MSG( classname
&& pclassname
&& wndproc
, NULL
,
1620 _T("NULL parameter in wxCreateHiddenWindow") );
1622 // register the class fi we need to first
1623 if ( *pclassname
== NULL
)
1626 wxZeroMemory(wndclass
);
1628 wndclass
.lpfnWndProc
= wndproc
;
1629 wndclass
.hInstance
= wxGetInstance();
1630 wndclass
.lpszClassName
= classname
;
1632 if ( !::RegisterClass(&wndclass
) )
1634 wxLogLastError(wxT("RegisterClass() in wxCreateHiddenWindow"));
1639 *pclassname
= classname
;
1642 // next create the window
1643 HWND hwnd
= ::CreateWindow
1657 wxLogLastError(wxT("CreateWindow() in wxCreateHiddenWindow"));