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/apptrait.h"
35 #include "wx/dynlib.h"
36 #include "wx/dynload.h"
37 #include "wx/scopeguard.h"
39 #include "wx/confbase.h" // for wxExpandEnvVars()
41 #include "wx/msw/private.h" // includes <windows.h>
42 #include "wx/msw/missing.h" // CHARSET_HANGUL
44 #if defined(__CYGWIN__)
45 //CYGWIN gives annoying warning about runtime stuff if we don't do this
46 # define USE_SYS_TYPES_FD_SET
47 # include <sys/types.h>
50 // Doesn't work with Cygwin at present
51 #if wxUSE_SOCKETS && (defined(__GNUWIN32_OLD__) || defined(__WXWINCE__) || defined(__CYGWIN32__))
52 // apparently we need to include winsock.h to get WSADATA and other stuff
53 // used in wxGetFullHostName() with the old mingw32 versions
59 #if !defined(__GNUWIN32__) && !defined(__SALFORDC__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
67 #if defined(__CYGWIN__)
68 #include <sys/unistd.h>
70 #include <sys/cygwin.h> // for cygwin_conv_to_full_win32_path()
73 #ifdef __BORLANDC__ // Please someone tell me which version of Borland needs
74 // this (3.1 I believe) and how to test for it.
75 // If this works for Borland 4.0 as well, then no worries.
79 // VZ: there is some code using NetXXX() functions to get the full user name:
80 // I don't think it's a good idea because they don't work under Win95 and
81 // seem to return the same as wxGetUserId() under NT. If you really want
82 // to use them, just #define USE_NET_API
89 #if defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
100 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
105 // For wxKillAllChildren
106 #include <tlhelp32.h>
108 // ----------------------------------------------------------------------------
110 // ----------------------------------------------------------------------------
112 // In the WIN.INI file
113 #if (!defined(USE_NET_API) && !defined(__WXWINCE__)) || defined(__WXMICROWIN__)
114 static const wxChar WX_SECTION
[] = wxT("wxWindows");
117 #if (!defined(USE_NET_API) && !defined(__WXWINCE__))
118 static const wxChar eUSERNAME
[] = wxT("UserName");
121 // ============================================================================
123 // ============================================================================
125 // ----------------------------------------------------------------------------
126 // get host name and related
127 // ----------------------------------------------------------------------------
129 // Get hostname only (without domain name)
130 bool wxGetHostName(wxChar
*WXUNUSED_IN_WINCE(buf
),
131 int WXUNUSED_IN_WINCE(maxSize
))
133 #if defined(__WXWINCE__)
136 #elif defined(__WIN32__) && !defined(__WXMICROWIN__)
137 DWORD nSize
= maxSize
;
138 if ( !::GetComputerName(buf
, &nSize
) )
140 wxLogLastError(wxT("GetComputerName"));
148 const wxChar
*default_host
= wxT("noname");
150 if ((sysname
= wxGetenv(wxT("SYSTEM_NAME"))) == NULL
) {
151 GetProfileString(WX_SECTION
, eHOSTNAME
, default_host
, buf
, maxSize
- 1);
153 wxStrncpy(buf
, sysname
, maxSize
- 1);
154 buf
[maxSize
] = wxT('\0');
155 return *buf
? true : false;
159 // get full hostname (with domain name if possible)
160 bool wxGetFullHostName(wxChar
*buf
, int maxSize
)
162 #if !defined( __WXMICROWIN__) && wxUSE_DYNAMIC_LOADER && wxUSE_SOCKETS
163 // TODO should use GetComputerNameEx() when available
165 // we don't want to always link with Winsock DLL as we might not use it at
166 // all, so load it dynamically here if needed (and don't complain if it is
167 // missing, we handle this)
170 wxDynamicLibrary
dllWinsock(_T("ws2_32.dll"), wxDL_VERBATIM
);
171 if ( dllWinsock
.IsLoaded() )
173 typedef int (PASCAL
*WSAStartup_t
)(WORD
, WSADATA
*);
174 typedef int (PASCAL
*gethostname_t
)(char *, int);
175 typedef hostent
* (PASCAL
*gethostbyname_t
)(const char *);
176 typedef hostent
* (PASCAL
*gethostbyaddr_t
)(const char *, int , int);
177 typedef int (PASCAL
*WSACleanup_t
)(void);
179 #define LOAD_WINSOCK_FUNC(func) \
181 pfn ## func = (func ## _t)dllWinsock.GetSymbol(_T(#func))
183 LOAD_WINSOCK_FUNC(WSAStartup
);
186 if ( pfnWSAStartup
&& pfnWSAStartup(MAKEWORD(1, 1), &wsa
) == 0 )
188 LOAD_WINSOCK_FUNC(gethostname
);
191 if ( pfngethostname
)
194 if ( pfngethostname(bufA
, WXSIZEOF(bufA
)) == 0 )
196 // gethostname() won't usually include the DNS domain name,
197 // for this we need to work a bit more
198 if ( !strchr(bufA
, '.') )
200 LOAD_WINSOCK_FUNC(gethostbyname
);
202 struct hostent
*pHostEnt
= pfngethostbyname
203 ? pfngethostbyname(bufA
)
208 // Windows will use DNS internally now
209 LOAD_WINSOCK_FUNC(gethostbyaddr
);
211 pHostEnt
= pfngethostbyaddr
212 ? pfngethostbyaddr(pHostEnt
->h_addr
,
219 host
= wxString::FromAscii(pHostEnt
->h_name
);
225 LOAD_WINSOCK_FUNC(WSACleanup
);
232 wxStrncpy(buf
, host
, maxSize
);
238 #endif // !__WXMICROWIN__
240 return wxGetHostName(buf
, maxSize
);
243 // Get user ID e.g. jacs
244 bool wxGetUserId(wxChar
*WXUNUSED_IN_WINCE(buf
),
245 int WXUNUSED_IN_WINCE(maxSize
))
247 #if defined(__WXWINCE__)
250 #elif defined(__WIN32__) && !defined(__WXMICROWIN__)
251 DWORD nSize
= maxSize
;
252 if ( ::GetUserName(buf
, &nSize
) == 0 )
254 // actually, it does happen on Win9x if the user didn't log on
255 DWORD res
= ::GetEnvironmentVariable(wxT("username"), buf
, maxSize
);
264 #else // __WXMICROWIN__
266 const wxChar
*default_id
= wxT("anonymous");
268 // Can't assume we have NIS (PC-NFS) or some other ID daemon
270 if ( (user
= wxGetenv(wxT("USER"))) == NULL
&&
271 (user
= wxGetenv(wxT("LOGNAME"))) == NULL
)
273 // Use wxWidgets configuration data (comming soon)
274 GetProfileString(WX_SECTION
, eUSERID
, default_id
, buf
, maxSize
- 1);
278 wxStrncpy(buf
, user
, maxSize
- 1);
281 return *buf
? true : false;
285 // Get user name e.g. Julian Smart
286 bool wxGetUserName(wxChar
*buf
, int maxSize
)
288 wxCHECK_MSG( buf
&& ( maxSize
> 0 ), false,
289 _T("empty buffer in wxGetUserName") );
290 #if defined(__WXWINCE__)
291 wxRegKey
key(wxRegKey::HKCU
, wxT("Control Panel\\Owner\\Owner"));
292 if(!key
.Open(wxRegKey::Read
))
295 if(!key
.QueryValue(wxEmptyString
, name
))
297 wxStrncpy(buf
, name
.c_str(), maxSize
);
299 #elif defined(USE_NET_API)
300 CHAR szUserName
[256];
301 if ( !wxGetUserId(szUserName
, WXSIZEOF(szUserName
)) )
304 // TODO how to get the domain name?
307 // the code is based on the MSDN example (also see KB article Q119670)
308 WCHAR wszUserName
[256]; // Unicode user name
309 WCHAR wszDomain
[256];
312 USER_INFO_2
*ui2
; // User structure
314 // Convert ANSI user name and domain to Unicode
315 MultiByteToWideChar( CP_ACP
, 0, szUserName
, strlen(szUserName
)+1,
316 wszUserName
, WXSIZEOF(wszUserName
) );
317 MultiByteToWideChar( CP_ACP
, 0, szDomain
, strlen(szDomain
)+1,
318 wszDomain
, WXSIZEOF(wszDomain
) );
320 // Get the computer name of a DC for the domain.
321 if ( NetGetDCName( NULL
, wszDomain
, &ComputerName
) != NERR_Success
)
323 wxLogError(wxT("Can not find domain controller"));
328 // Look up the user on the DC
329 NET_API_STATUS status
= NetUserGetInfo( (LPWSTR
)ComputerName
,
330 (LPWSTR
)&wszUserName
,
331 2, // level - we want USER_INFO_2
339 case NERR_InvalidComputer
:
340 wxLogError(wxT("Invalid domain controller name."));
344 case NERR_UserNotFound
:
345 wxLogError(wxT("Invalid user name '%s'."), szUserName
);
350 wxLogSysError(wxT("Can't get information about user"));
355 // Convert the Unicode full name to ANSI
356 WideCharToMultiByte( CP_ACP
, 0, ui2
->usri2_full_name
, -1,
357 buf
, maxSize
, NULL
, NULL
);
362 wxLogError(wxT("Couldn't look up full user name."));
365 #else // !USE_NET_API
366 // Could use NIS, MS-Mail or other site specific programs
367 // Use wxWidgets configuration data
368 bool ok
= GetProfileString(WX_SECTION
, eUSERNAME
, wxEmptyString
, buf
, maxSize
- 1) != 0;
371 ok
= wxGetUserId(buf
, maxSize
);
376 wxStrncpy(buf
, wxT("Unknown User"), maxSize
);
383 const wxChar
* wxGetHomeDir(wxString
*pstr
)
385 wxString
& strDir
= *pstr
;
387 // first branch is for Cygwin
388 #if defined(__UNIX__)
389 const wxChar
*szHome
= wxGetenv("HOME");
390 if ( szHome
== NULL
) {
392 wxLogWarning(_("can't find user's HOME, using current directory."));
398 // add a trailing slash if needed
399 if ( strDir
.Last() != wxT('/') )
403 // Cygwin returns unix type path but that does not work well
404 static wxChar windowsPath
[MAX_PATH
];
405 cygwin_conv_to_full_win32_path(strDir
, windowsPath
);
406 strDir
= windowsPath
;
408 #elif defined(__WXWINCE__)
413 // If we have a valid HOME directory, as is used on many machines that
414 // have unix utilities on them, we should use that.
415 const wxChar
*szHome
= wxGetenv(wxT("HOME"));
417 if ( szHome
!= NULL
)
421 else // no HOME, try HOMEDRIVE/PATH
423 szHome
= wxGetenv(wxT("HOMEDRIVE"));
424 if ( szHome
!= NULL
)
426 szHome
= wxGetenv(wxT("HOMEPATH"));
428 if ( szHome
!= NULL
)
432 // the idea is that under NT these variables have default values
433 // of "%systemdrive%:" and "\\". As we don't want to create our
434 // config files in the root directory of the system drive, we will
435 // create it in our program's dir. However, if the user took care
436 // to set HOMEPATH to something other than "\\", we suppose that he
437 // knows what he is doing and use the supplied value.
438 if ( wxStrcmp(szHome
, wxT("\\")) == 0 )
443 if ( strDir
.empty() )
445 // If we have a valid USERPROFILE directory, as is the case in
446 // Windows NT, 2000 and XP, we should use that as our home directory.
447 szHome
= wxGetenv(wxT("USERPROFILE"));
449 if ( szHome
!= NULL
)
453 if ( !strDir
.empty() )
455 // sometimes the value of HOME may be "%USERPROFILE%", so reexpand the
456 // value once again, it shouldn't hurt anyhow
457 strDir
= wxExpandEnvVars(strDir
);
459 else // fall back to the program directory
461 // extract the directory component of the program file name
462 wxSplitPath(wxGetFullModuleName(), &strDir
, NULL
, NULL
);
466 return strDir
.c_str();
469 wxChar
*wxGetUserHome(const wxString
& WXUNUSED(user
))
471 // VZ: the old code here never worked for user != "" anyhow! Moreover, it
472 // returned sometimes a malloc()'d pointer, sometimes a pointer to a
473 // static buffer and sometimes I don't even know what.
474 static wxString s_home
;
476 return (wxChar
*)wxGetHomeDir(&s_home
);
479 bool wxGetDiskSpace(const wxString
& WXUNUSED_IN_WINCE(path
),
480 wxLongLong
*WXUNUSED_IN_WINCE(pTotal
),
481 wxLongLong
*WXUNUSED_IN_WINCE(pFree
))
490 // old w32api don't have ULARGE_INTEGER
491 #if defined(__WIN32__) && \
492 (!defined(__GNUWIN32__) || wxCHECK_W32API_VERSION( 0, 3 ))
493 // GetDiskFreeSpaceEx() is not available under original Win95, check for
495 typedef BOOL (WINAPI
*GetDiskFreeSpaceEx_t
)(LPCTSTR
,
501 pGetDiskFreeSpaceEx
= (GetDiskFreeSpaceEx_t
)::GetProcAddress
503 ::GetModuleHandle(_T("kernel32.dll")),
505 "GetDiskFreeSpaceExW"
507 "GetDiskFreeSpaceExA"
511 if ( pGetDiskFreeSpaceEx
)
513 ULARGE_INTEGER bytesFree
, bytesTotal
;
515 // may pass the path as is, GetDiskFreeSpaceEx() is smart enough
516 if ( !pGetDiskFreeSpaceEx(path
,
521 wxLogLastError(_T("GetDiskFreeSpaceEx"));
526 // ULARGE_INTEGER is a union of a 64 bit value and a struct containing
527 // two 32 bit fields which may be or may be not named - try to make it
528 // compile in all cases
529 #if defined(__BORLANDC__) && !defined(_ANONYMOUS_STRUCT)
536 *pTotal
= wxLongLong(UL(bytesTotal
).HighPart
, UL(bytesTotal
).LowPart
);
541 *pFree
= wxLongLong(UL(bytesFree
).HighPart
, UL(bytesFree
).LowPart
);
547 // there's a problem with drives larger than 2GB, GetDiskFreeSpaceEx()
548 // should be used instead - but if it's not available, fall back on
549 // GetDiskFreeSpace() nevertheless...
551 DWORD lSectorsPerCluster
,
553 lNumberOfFreeClusters
,
554 lTotalNumberOfClusters
;
556 // FIXME: this is wrong, we should extract the root drive from path
557 // instead, but this is the job for wxFileName...
558 if ( !::GetDiskFreeSpace(path
,
561 &lNumberOfFreeClusters
,
562 &lTotalNumberOfClusters
) )
564 wxLogLastError(_T("GetDiskFreeSpace"));
569 wxLongLong lBytesPerCluster
= lSectorsPerCluster
;
570 lBytesPerCluster
*= lBytesPerSector
;
574 *pTotal
= lBytesPerCluster
;
575 *pTotal
*= lTotalNumberOfClusters
;
580 *pFree
= lBytesPerCluster
;
581 *pFree
*= lNumberOfFreeClusters
;
590 // ----------------------------------------------------------------------------
592 // ----------------------------------------------------------------------------
594 bool wxGetEnv(const wxString
& WXUNUSED_IN_WINCE(var
),
595 wxString
*WXUNUSED_IN_WINCE(value
))
598 // no environment variables under CE
601 // first get the size of the buffer
602 DWORD dwRet
= ::GetEnvironmentVariable(var
, NULL
, 0);
605 // this means that there is no such variable
611 (void)::GetEnvironmentVariable(var
, wxStringBuffer(*value
, dwRet
),
619 bool wxSetEnv(const wxString
& WXUNUSED_IN_WINCE(var
),
620 const wxChar
*WXUNUSED_IN_WINCE(value
))
622 // some compilers have putenv() or _putenv() or _wputenv() but it's better
623 // to always use Win32 function directly instead of dealing with them
625 // no environment variables under CE
628 if ( !::SetEnvironmentVariable(var
, value
) )
630 wxLogLastError(_T("SetEnvironmentVariable"));
639 // ----------------------------------------------------------------------------
640 // process management
641 // ----------------------------------------------------------------------------
643 // structure used to pass parameters from wxKill() to wxEnumFindByPidProc()
644 struct wxFindByPidParams
646 wxFindByPidParams() { hwnd
= 0; pid
= 0; }
648 // the HWND used to return the result
651 // the PID we're looking from
654 DECLARE_NO_COPY_CLASS(wxFindByPidParams
)
657 // wxKill helper: EnumWindows() callback which is used to find the first (top
658 // level) window belonging to the given process
659 BOOL CALLBACK
wxEnumFindByPidProc(HWND hwnd
, LPARAM lParam
)
662 (void)::GetWindowThreadProcessId(hwnd
, &pid
);
664 wxFindByPidParams
*params
= (wxFindByPidParams
*)lParam
;
665 if ( pid
== params
->pid
)
667 // remember the window we found
670 // return FALSE to stop the enumeration
674 // continue enumeration
678 int wxKillAllChildren(long pid
, wxSignal sig
, wxKillError
*krc
);
680 int wxKill(long pid
, wxSignal sig
, wxKillError
*krc
, int flags
)
682 if (flags
& wxKILL_CHILDREN
)
683 wxKillAllChildren(pid
, sig
, krc
);
685 // get the process handle to operate on
686 HANDLE hProcess
= ::OpenProcess(SYNCHRONIZE
|
688 PROCESS_QUERY_INFORMATION
,
689 FALSE
, // not inheritable
691 if ( hProcess
== NULL
)
695 // recognize wxKILL_ACCESS_DENIED as special because this doesn't
696 // mean that the process doesn't exist and this is important for
697 // wxProcess::Exists()
698 *krc
= ::GetLastError() == ERROR_ACCESS_DENIED
699 ? wxKILL_ACCESS_DENIED
706 wxON_BLOCK_EXIT1(::CloseHandle
, hProcess
);
712 // kill the process forcefully returning -1 as error code
713 if ( !::TerminateProcess(hProcess
, (UINT
)-1) )
715 wxLogSysError(_("Failed to kill process %d"), pid
);
719 // this is not supposed to happen if we could open the
729 // do nothing, we just want to test for process existence
735 // any other signal means "terminate"
737 wxFindByPidParams params
;
738 params
.pid
= (DWORD
)pid
;
740 // EnumWindows() has nice semantics: it returns 0 if it found
741 // something or if an error occurred and non zero if it
742 // enumerated all the window
743 if ( !::EnumWindows(wxEnumFindByPidProc
, (LPARAM
)¶ms
) )
745 // did we find any window?
748 // tell the app to close
750 // NB: this is the harshest way, the app won't have an
751 // opportunity to save any files, for example, but
752 // this is probably what we want here. If not we
753 // can also use SendMesageTimeout(WM_CLOSE)
754 if ( !::PostMessage(params
.hwnd
, WM_QUIT
, 0, 0) )
756 wxLogLastError(_T("PostMessage(WM_QUIT)"));
759 else // it was an error then
761 wxLogLastError(_T("EnumWindows"));
766 else // no windows for this PID
777 DWORD rc
wxDUMMY_INITIALIZE(0);
780 // as we wait for a short time, we can use just WaitForSingleObject()
781 // and not MsgWaitForMultipleObjects()
782 switch ( ::WaitForSingleObject(hProcess
, 500 /* msec */) )
785 // process terminated
786 if ( !::GetExitCodeProcess(hProcess
, &rc
) )
788 wxLogLastError(_T("GetExitCodeProcess"));
793 wxFAIL_MSG( _T("unexpected WaitForSingleObject() return") );
797 wxLogLastError(_T("WaitForSingleObject"));
810 // the return code is the same as from Unix kill(): 0 if killed
811 // successfully or -1 on error
812 if ( !ok
|| rc
== STILL_ACTIVE
)
821 typedef HANDLE (WINAPI
*CreateToolhelp32Snapshot_t
)(DWORD
,DWORD
);
822 typedef BOOL (WINAPI
*Process32_t
)(HANDLE
,LPPROCESSENTRY32
);
824 CreateToolhelp32Snapshot_t lpfCreateToolhelp32Snapshot
;
825 Process32_t lpfProcess32First
, lpfProcess32Next
;
827 static void InitToolHelp32()
829 static bool s_initToolHelpDone
= false;
831 if (s_initToolHelpDone
)
834 s_initToolHelpDone
= true;
836 lpfCreateToolhelp32Snapshot
= NULL
;
837 lpfProcess32First
= NULL
;
838 lpfProcess32Next
= NULL
;
840 #if wxUSE_DYNLIB_CLASS
842 wxDynamicLibrary
dllKernel(_T("kernel32.dll"), wxDL_VERBATIM
);
844 // Get procedure addresses.
845 // We are linking to these functions of Kernel32
846 // explicitly, because otherwise a module using
847 // this code would fail to load under Windows NT,
848 // which does not have the Toolhelp32
849 // functions in the Kernel 32.
850 lpfCreateToolhelp32Snapshot
=
851 (CreateToolhelp32Snapshot_t
)dllKernel
.RawGetSymbol(_T("CreateToolhelp32Snapshot"));
854 (Process32_t
)dllKernel
.RawGetSymbol(_T("Process32First"));
857 (Process32_t
)dllKernel
.RawGetSymbol(_T("Process32Next"));
859 #endif // wxUSE_DYNLIB_CLASS
863 int wxKillAllChildren(long pid
, wxSignal sig
, wxKillError
*krc
)
870 // If not implemented for this platform (e.g. NT 4.0), silently ignore
871 if (!lpfCreateToolhelp32Snapshot
|| !lpfProcess32First
|| !lpfProcess32Next
)
874 // Take a snapshot of all processes in the system.
875 HANDLE hProcessSnap
= lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0);
876 if (hProcessSnap
== INVALID_HANDLE_VALUE
) {
882 //Fill in the size of the structure before using it.
885 pe
.dwSize
= sizeof(PROCESSENTRY32
);
887 // Walk the snapshot of the processes, and for each process,
888 // kill it if its parent is pid.
889 if (!lpfProcess32First(hProcessSnap
, &pe
)) {
890 // Can't get first process.
893 CloseHandle (hProcessSnap
);
898 if (pe
.th32ParentProcessID
== (DWORD
) pid
) {
899 if (wxKill(pe
.th32ProcessID
, sig
, krc
))
902 } while (lpfProcess32Next (hProcessSnap
, &pe
));
908 // Execute a program in an Interactive Shell
909 bool wxShell(const wxString
& command
)
916 wxChar
*shell
= wxGetenv(wxT("COMSPEC"));
918 shell
= (wxChar
*) wxT("\\COMMAND.COM");
927 // pass the command to execute to the command processor
928 cmd
.Printf(wxT("%s /c %s"), shell
, command
.c_str());
932 return wxExecute(cmd
, wxEXEC_SYNC
) == 0;
935 // Shutdown or reboot the PC
936 bool wxShutdown(wxShutdownFlags
WXUNUSED_IN_WINCE(wFlags
))
941 #elif defined(__WIN32__)
944 if ( wxGetOsVersion(NULL
, NULL
) == wxWINDOWS_NT
) // if is NT or 2K
946 // Get a token for this process.
948 bOK
= ::OpenProcessToken(GetCurrentProcess(),
949 TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
,
953 TOKEN_PRIVILEGES tkp
;
955 // Get the LUID for the shutdown privilege.
956 ::LookupPrivilegeValue(NULL
, SE_SHUTDOWN_NAME
,
957 &tkp
.Privileges
[0].Luid
);
959 tkp
.PrivilegeCount
= 1; // one privilege to set
960 tkp
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
962 // Get the shutdown privilege for this process.
963 ::AdjustTokenPrivileges(hToken
, FALSE
, &tkp
, 0,
964 (PTOKEN_PRIVILEGES
)NULL
, 0);
966 // Cannot test the return value of AdjustTokenPrivileges.
967 bOK
= ::GetLastError() == ERROR_SUCCESS
;
973 UINT flags
= EWX_SHUTDOWN
| EWX_FORCE
;
976 case wxSHUTDOWN_POWEROFF
:
977 flags
|= EWX_POWEROFF
;
980 case wxSHUTDOWN_REBOOT
:
985 wxFAIL_MSG( _T("unknown wxShutdown() flag") );
989 bOK
= ::ExitWindowsEx(flags
, 0) != 0;
996 wxPowerType
wxGetPowerType()
999 return wxPOWER_UNKNOWN
;
1002 wxBatteryState
wxGetBatteryState()
1005 return wxBATTERY_UNKNOWN_STATE
;
1008 // ----------------------------------------------------------------------------
1010 // ----------------------------------------------------------------------------
1012 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
1013 wxMemorySize
wxGetFreeMemory()
1015 #if defined(__WIN64__)
1016 MEMORYSTATUSEX memStatex
;
1017 memStatex
.dwLength
= sizeof (memStatex
);
1018 ::GlobalMemoryStatusEx (&memStatex
);
1019 return (wxMemorySize
)memStatex
.ullAvailPhys
;
1020 #else /* if defined(__WIN32__) */
1021 MEMORYSTATUS memStatus
;
1022 memStatus
.dwLength
= sizeof(MEMORYSTATUS
);
1023 ::GlobalMemoryStatus(&memStatus
);
1024 return (wxMemorySize
)memStatus
.dwAvailPhys
;
1028 unsigned long wxGetProcessId()
1030 return ::GetCurrentProcessId();
1036 ::MessageBeep((UINT
)-1); // default sound
1039 bool wxIsDebuggerRunning()
1041 #if wxUSE_DYNLIB_CLASS
1042 // IsDebuggerPresent() is not available under Win95, so load it dynamically
1043 wxDynamicLibrary
dll(_T("kernel32.dll"), wxDL_VERBATIM
);
1045 typedef BOOL (WINAPI
*IsDebuggerPresent_t
)();
1046 if ( !dll
.HasSymbol(_T("IsDebuggerPresent")) )
1048 // no way to know, assume no
1052 return (*(IsDebuggerPresent_t
)dll
.GetSymbol(_T("IsDebuggerPresent")))() != 0;
1058 // ----------------------------------------------------------------------------
1060 // ----------------------------------------------------------------------------
1062 wxString
wxGetOsDescription()
1069 info
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
1070 if ( ::GetVersionEx(&info
) )
1072 switch ( info
.dwPlatformId
)
1074 case VER_PLATFORM_WIN32s
:
1075 str
= _("Win32s on Windows 3.1");
1078 case VER_PLATFORM_WIN32_WINDOWS
:
1079 switch (info
.dwMinorVersion
)
1082 if ( info
.szCSDVersion
[1] == 'B' ||
1083 info
.szCSDVersion
[1] == 'C' )
1085 str
= _("Windows 95 OSR2");
1089 str
= _("Windows 95");
1093 if ( info
.szCSDVersion
[1] == 'B' ||
1094 info
.szCSDVersion
[1] == 'C' )
1096 str
= _("Windows 98 SE");
1100 str
= _("Windows 98");
1104 str
= _("Windows ME");
1107 str
.Printf(_("Windows 9x (%d.%d)"),
1108 info
.dwMajorVersion
,
1109 info
.dwMinorVersion
);
1112 if ( !wxIsEmpty(info
.szCSDVersion
) )
1114 str
<< _T(" (") << info
.szCSDVersion
<< _T(')');
1118 case VER_PLATFORM_WIN32_NT
:
1119 if ( info
.dwMajorVersion
== 5 )
1121 switch ( info
.dwMinorVersion
)
1124 str
.Printf(_("Windows 2000 (build %lu"),
1125 info
.dwBuildNumber
);
1128 str
.Printf(_("Windows XP (build %lu"),
1129 info
.dwBuildNumber
);
1132 str
.Printf(_("Windows Server 2003 (build %lu"),
1133 info
.dwBuildNumber
);
1137 if ( wxIsEmpty(str
) )
1139 str
.Printf(_("Windows NT %lu.%lu (build %lu"),
1140 info
.dwMajorVersion
,
1141 info
.dwMinorVersion
,
1142 info
.dwBuildNumber
);
1144 if ( !wxIsEmpty(info
.szCSDVersion
) )
1146 str
<< _T(", ") << info
.szCSDVersion
;
1154 wxFAIL_MSG( _T("GetVersionEx() failed") ); // should never happen
1160 wxToolkitInfo
& wxAppTraits::GetToolkitInfo()
1162 // cache the version info, it's not going to change
1164 // NB: this is MT-safe, we may use these static vars from different threads
1165 // but as they always have the same value it doesn't matter
1166 static int s_ver
= -1,
1176 info
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
1177 if ( ::GetVersionEx(&info
) )
1179 s_major
= info
.dwMajorVersion
;
1180 s_minor
= info
.dwMinorVersion
;
1182 #ifdef __SMARTPHONE__
1183 s_ver
= wxWINDOWS_SMARTPHONE
;
1184 #elif defined(__POCKETPC__)
1185 s_ver
= wxWINDOWS_POCKETPC
;
1187 switch ( info
.dwPlatformId
)
1189 case VER_PLATFORM_WIN32s
:
1193 case VER_PLATFORM_WIN32_WINDOWS
:
1197 case VER_PLATFORM_WIN32_NT
:
1198 s_ver
= wxWINDOWS_NT
;
1201 case VER_PLATFORM_WIN32_CE
:
1202 s_ver
= wxWINDOWS_CE
;
1209 static wxToolkitInfo info
;
1210 info
.versionMajor
= s_major
;
1211 info
.versionMinor
= s_minor
;
1213 info
.name
= _T("wxBase");
1217 wxWinVersion
wxGetWinVersion()
1221 switch ( wxGetOsVersion(&verMaj
, &verMin
) )
1229 return wxWinVersion_95
;
1232 return wxWinVersion_98
;
1235 return wxWinVersion_ME
;
1244 return wxWinVersion_NT3
;
1247 return wxWinVersion_NT4
;
1253 return wxWinVersion_2000
;
1256 return wxWinVersion_XP
;
1259 return wxWinVersion_2003
;
1264 return wxWinVersion_NT6
;
1270 return wxWinVersion_Unknown
;
1273 // ----------------------------------------------------------------------------
1275 // ----------------------------------------------------------------------------
1277 void wxMilliSleep(unsigned long milliseconds
)
1279 ::Sleep(milliseconds
);
1282 void wxMicroSleep(unsigned long microseconds
)
1284 wxMilliSleep(microseconds
/1000);
1287 void wxSleep(int nSecs
)
1289 wxMilliSleep(1000*nSecs
);
1292 // ----------------------------------------------------------------------------
1293 // font encoding <-> Win32 codepage conversion functions
1294 // ----------------------------------------------------------------------------
1296 extern WXDLLIMPEXP_BASE
long wxEncodingToCharset(wxFontEncoding encoding
)
1300 // although this function is supposed to return an exact match, do do
1301 // some mappings here for the most common case of "standard" encoding
1302 case wxFONTENCODING_SYSTEM
:
1303 return DEFAULT_CHARSET
;
1305 case wxFONTENCODING_ISO8859_1
:
1306 case wxFONTENCODING_ISO8859_15
:
1307 case wxFONTENCODING_CP1252
:
1308 return ANSI_CHARSET
;
1310 #if !defined(__WXMICROWIN__)
1311 // The following four fonts are multi-byte charsets
1312 case wxFONTENCODING_CP932
:
1313 return SHIFTJIS_CHARSET
;
1315 case wxFONTENCODING_CP936
:
1316 return GB2312_CHARSET
;
1319 case wxFONTENCODING_CP949
:
1320 return HANGUL_CHARSET
;
1323 case wxFONTENCODING_CP950
:
1324 return CHINESEBIG5_CHARSET
;
1326 // The rest are single byte encodings
1327 case wxFONTENCODING_CP1250
:
1328 return EASTEUROPE_CHARSET
;
1330 case wxFONTENCODING_CP1251
:
1331 return RUSSIAN_CHARSET
;
1333 case wxFONTENCODING_CP1253
:
1334 return GREEK_CHARSET
;
1336 case wxFONTENCODING_CP1254
:
1337 return TURKISH_CHARSET
;
1339 case wxFONTENCODING_CP1255
:
1340 return HEBREW_CHARSET
;
1342 case wxFONTENCODING_CP1256
:
1343 return ARABIC_CHARSET
;
1345 case wxFONTENCODING_CP1257
:
1346 return BALTIC_CHARSET
;
1348 case wxFONTENCODING_CP874
:
1349 return THAI_CHARSET
;
1350 #endif // !__WXMICROWIN__
1352 case wxFONTENCODING_CP437
:
1356 // no way to translate this encoding into a Windows charset
1361 // we have 2 versions of wxCharsetToCodepage(): the old one which directly
1362 // looks up the vlaues in the registry and the new one which is more
1363 // politically correct and has more chances to work on other Windows versions
1364 // as well but the old version is still needed for !wxUSE_FONTMAP case
1367 #include "wx/fontmap.h"
1369 extern WXDLLIMPEXP_BASE
long wxEncodingToCodepage(wxFontEncoding encoding
)
1371 // There don't seem to be symbolic names for
1372 // these under Windows so I just copied the
1373 // values from MSDN.
1379 case wxFONTENCODING_ISO8859_1
: ret
= 28591; break;
1380 case wxFONTENCODING_ISO8859_2
: ret
= 28592; break;
1381 case wxFONTENCODING_ISO8859_3
: ret
= 28593; break;
1382 case wxFONTENCODING_ISO8859_4
: ret
= 28594; break;
1383 case wxFONTENCODING_ISO8859_5
: ret
= 28595; break;
1384 case wxFONTENCODING_ISO8859_6
: ret
= 28596; break;
1385 case wxFONTENCODING_ISO8859_7
: ret
= 28597; break;
1386 case wxFONTENCODING_ISO8859_8
: ret
= 28598; break;
1387 case wxFONTENCODING_ISO8859_9
: ret
= 28599; break;
1388 case wxFONTENCODING_ISO8859_10
: ret
= 28600; break;
1389 case wxFONTENCODING_ISO8859_11
: ret
= 28601; break;
1390 // case wxFONTENCODING_ISO8859_12, // doesn't exist currently, but put it
1391 case wxFONTENCODING_ISO8859_13
: ret
= 28603; break;
1392 case wxFONTENCODING_ISO8859_14
: ret
= 28604; break;
1393 case wxFONTENCODING_ISO8859_15
: ret
= 28605; break;
1394 case wxFONTENCODING_KOI8
: ret
= 20866; break;
1395 case wxFONTENCODING_KOI8_U
: ret
= 21866; break;
1396 case wxFONTENCODING_CP437
: ret
= 437; break;
1397 case wxFONTENCODING_CP850
: ret
= 850; break;
1398 case wxFONTENCODING_CP852
: ret
= 852; break;
1399 case wxFONTENCODING_CP855
: ret
= 855; break;
1400 case wxFONTENCODING_CP866
: ret
= 866; break;
1401 case wxFONTENCODING_CP874
: ret
= 874; break;
1402 case wxFONTENCODING_CP932
: ret
= 932; break;
1403 case wxFONTENCODING_CP936
: ret
= 936; break;
1404 case wxFONTENCODING_CP949
: ret
= 949; break;
1405 case wxFONTENCODING_CP950
: ret
= 950; break;
1406 case wxFONTENCODING_CP1250
: ret
= 1250; break;
1407 case wxFONTENCODING_CP1251
: ret
= 1251; break;
1408 case wxFONTENCODING_CP1252
: ret
= 1252; break;
1409 case wxFONTENCODING_CP1253
: ret
= 1253; break;
1410 case wxFONTENCODING_CP1254
: ret
= 1254; break;
1411 case wxFONTENCODING_CP1255
: ret
= 1255; break;
1412 case wxFONTENCODING_CP1256
: ret
= 1256; break;
1413 case wxFONTENCODING_CP1257
: ret
= 1257; break;
1414 case wxFONTENCODING_EUC_JP
: ret
= 20932; break;
1415 case wxFONTENCODING_MACROMAN
: ret
= 10000; break;
1416 case wxFONTENCODING_MACJAPANESE
: ret
= 10001; break;
1417 case wxFONTENCODING_MACCHINESETRAD
: ret
= 10002; break;
1418 case wxFONTENCODING_MACKOREAN
: ret
= 10003; break;
1419 case wxFONTENCODING_MACARABIC
: ret
= 10004; break;
1420 case wxFONTENCODING_MACHEBREW
: ret
= 10005; break;
1421 case wxFONTENCODING_MACGREEK
: ret
= 10006; break;
1422 case wxFONTENCODING_MACCYRILLIC
: ret
= 10007; break;
1423 case wxFONTENCODING_MACTHAI
: ret
= 10021; break;
1424 case wxFONTENCODING_MACCHINESESIMP
: ret
= 10008; break;
1425 case wxFONTENCODING_MACCENTRALEUR
: ret
= 10029; break;
1426 case wxFONTENCODING_MACCROATIAN
: ret
= 10082; break;
1427 case wxFONTENCODING_MACICELANDIC
: ret
= 10079; break;
1428 case wxFONTENCODING_MACROMANIAN
: ret
= 10009; break;
1429 case wxFONTENCODING_UTF7
: ret
= 65000; break;
1430 case wxFONTENCODING_UTF8
: ret
= 65001; break;
1434 if (::IsValidCodePage(ret
) == 0)
1438 if (::GetCPInfo(ret
, &info
) == 0)
1444 extern long wxCharsetToCodepage(const wxChar
*name
)
1446 // first get the font encoding for this charset
1450 wxFontEncoding enc
= wxFontMapperBase::Get()->CharsetToEncoding(name
, false);
1451 if ( enc
== wxFONTENCODING_SYSTEM
)
1454 // the use the helper function
1455 return wxEncodingToCodepage(enc
);
1458 #else // !wxUSE_FONTMAP
1460 #include "wx/msw/registry.h"
1462 // this should work if Internet Exploiter is installed
1463 extern long wxCharsetToCodepage(const wxChar
*name
)
1470 wxString
path(wxT("MIME\\Database\\Charset\\"));
1473 // follow the alias loop
1476 wxRegKey
key(wxRegKey::HKCR
, path
+ cn
);
1481 // two cases: either there's an AliasForCharset string,
1482 // or there are Codepage and InternetEncoding dwords.
1483 // The InternetEncoding gives us the actual encoding,
1484 // the Codepage just says which Windows character set to
1485 // use when displaying the data.
1486 if (key
.HasValue(wxT("InternetEncoding")) &&
1487 key
.QueryValue(wxT("InternetEncoding"), &CP
))
1490 // no encoding, see if it's an alias
1491 if (!key
.HasValue(wxT("AliasForCharset")) ||
1492 !key
.QueryValue(wxT("AliasForCharset"), cn
))
1499 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
1502 Creates a hidden window with supplied window proc registering the class for
1503 it if necesssary (i.e. the first time only). Caller is responsible for
1504 destroying the window and unregistering the class (note that this must be
1505 done because wxWidgets may be used as a DLL and so may be loaded/unloaded
1506 multiple times into/from the same process so we cna't rely on automatic
1507 Windows class unregistration).
1509 pclassname is a pointer to a caller stored classname, which must initially be
1510 NULL. classname is the desired wndclass classname. If function successfully
1511 registers the class, pclassname will be set to classname.
1513 extern "C" WXDLLIMPEXP_BASE HWND
1514 wxCreateHiddenWindow(LPCTSTR
*pclassname
, LPCTSTR classname
, WNDPROC wndproc
)
1516 wxCHECK_MSG( classname
&& pclassname
&& wndproc
, NULL
,
1517 _T("NULL parameter in wxCreateHiddenWindow") );
1519 // register the class fi we need to first
1520 if ( *pclassname
== NULL
)
1523 wxZeroMemory(wndclass
);
1525 wndclass
.lpfnWndProc
= wndproc
;
1526 wndclass
.hInstance
= wxGetInstance();
1527 wndclass
.lpszClassName
= classname
;
1529 if ( !::RegisterClass(&wndclass
) )
1531 wxLogLastError(wxT("RegisterClass() in wxCreateHiddenWindow"));
1536 *pclassname
= classname
;
1539 // next create the window
1540 HWND hwnd
= ::CreateWindow
1554 wxLogLastError(wxT("CreateWindow() in wxCreateHiddenWindow"));