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"
39 #include "wx/filename.h"
41 #include "wx/confbase.h" // for wxExpandEnvVars()
43 #include "wx/msw/private.h" // includes <windows.h>
44 #include "wx/msw/missing.h" // for CHARSET_HANGUL
46 #if defined(__CYGWIN__)
47 //CYGWIN gives annoying warning about runtime stuff if we don't do this
48 # define USE_SYS_TYPES_FD_SET
49 # include <sys/types.h>
52 // Doesn't work with Cygwin at present
53 #if wxUSE_SOCKETS && (defined(__GNUWIN32_OLD__) || defined(__WXWINCE__) || defined(__CYGWIN32__))
54 // apparently we need to include winsock.h to get WSADATA and other stuff
55 // used in wxGetFullHostName() with the old mingw32 versions
59 #if !defined(__GNUWIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
67 #if defined(__CYGWIN__)
68 #include <sys/unistd.h>
70 #include <sys/cygwin.h> // for cygwin_conv_path()
71 // and cygwin_conv_to_full_win32_path()
72 #include <cygwin/version.h>
75 #ifdef __BORLANDC__ // Please someone tell me which version of Borland needs
76 // this (3.1 I believe) and how to test for it.
77 // If this works for Borland 4.0 as well, then no worries.
81 // VZ: there is some code using NetXXX() functions to get the full user name:
82 // I don't think it's a good idea because they don't work under Win95 and
83 // seem to return the same as wxGetUserId() under NT. If you really want
84 // to use them, just #define USE_NET_API
91 #if defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
102 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
107 // For wxKillAllChildren
108 #include <tlhelp32.h>
110 // ----------------------------------------------------------------------------
112 // ----------------------------------------------------------------------------
114 // In the WIN.INI file
115 #if (!defined(USE_NET_API) && !defined(__WXWINCE__)) || defined(__WXMICROWIN__)
116 static const wxChar WX_SECTION
[] = wxT("wxWindows");
119 #if (!defined(USE_NET_API) && !defined(__WXWINCE__))
120 static const wxChar eUSERNAME
[] = wxT("UserName");
123 WXDLLIMPEXP_DATA_BASE(const wxChar
*) wxUserResourceStr
= wxT("TEXT");
125 // ============================================================================
127 // ============================================================================
129 // ----------------------------------------------------------------------------
130 // get host name and related
131 // ----------------------------------------------------------------------------
133 // Get hostname only (without domain name)
134 bool wxGetHostName(wxChar
*buf
, int maxSize
)
136 #if defined(__WXWINCE__)
137 // GetComputerName() is not supported but the name seems to be stored in
138 // this location in the registry, at least for PPC2003 and WM5
140 wxRegKey
regKey(wxRegKey::HKLM
, wxT("Ident"));
141 if ( !regKey
.HasValue(wxT("Name")) ||
142 !regKey
.QueryValue(wxT("Name"), hostName
) )
145 wxStrlcpy(buf
, hostName
.wx_str(), maxSize
);
146 #else // !__WXWINCE__
147 DWORD nSize
= maxSize
;
148 if ( !::GetComputerName(buf
, &nSize
) )
150 wxLogLastError(wxT("GetComputerName"));
154 #endif // __WXWINCE__/!__WXWINCE__
159 // get full hostname (with domain name if possible)
160 bool wxGetFullHostName(wxChar
*buf
, int maxSize
)
162 #if !defined( __WXMICROWIN__) && wxUSE_DYNLIB_CLASS && 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(wxT("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(wxT(#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 wxStrlcpy(buf
, host
.c_str(), 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__)
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
);
267 // Get user name e.g. Julian Smart
268 bool wxGetUserName(wxChar
*buf
, int maxSize
)
270 wxCHECK_MSG( buf
&& ( maxSize
> 0 ), false,
271 wxT("empty buffer in wxGetUserName") );
272 #if defined(__WXWINCE__) && wxUSE_REGKEY
274 wxRegKey
key(wxRegKey::HKCU
, wxT("ControlPanel\\Owner"));
275 if(!key
.Open(wxRegKey::Read
))
278 if(!key
.QueryValue(wxT("Owner"),name
))
280 wxStrlcpy(buf
, name
.c_str(), maxSize
);
282 #elif defined(USE_NET_API)
283 CHAR szUserName
[256];
284 if ( !wxGetUserId(szUserName
, WXSIZEOF(szUserName
)) )
287 // TODO how to get the domain name?
290 // the code is based on the MSDN example (also see KB article Q119670)
291 WCHAR wszUserName
[256]; // Unicode user name
292 WCHAR wszDomain
[256];
295 USER_INFO_2
*ui2
; // User structure
297 // Convert ANSI user name and domain to Unicode
298 MultiByteToWideChar( CP_ACP
, 0, szUserName
, strlen(szUserName
)+1,
299 wszUserName
, WXSIZEOF(wszUserName
) );
300 MultiByteToWideChar( CP_ACP
, 0, szDomain
, strlen(szDomain
)+1,
301 wszDomain
, WXSIZEOF(wszDomain
) );
303 // Get the computer name of a DC for the domain.
304 if ( NetGetDCName( NULL
, wszDomain
, &ComputerName
) != NERR_Success
)
306 wxLogError(wxT("Can not find domain controller"));
311 // Look up the user on the DC
312 NET_API_STATUS status
= NetUserGetInfo( (LPWSTR
)ComputerName
,
313 (LPWSTR
)&wszUserName
,
314 2, // level - we want USER_INFO_2
322 case NERR_InvalidComputer
:
323 wxLogError(wxT("Invalid domain controller name."));
327 case NERR_UserNotFound
:
328 wxLogError(wxT("Invalid user name '%s'."), szUserName
);
333 wxLogSysError(wxT("Can't get information about user"));
338 // Convert the Unicode full name to ANSI
339 WideCharToMultiByte( CP_ACP
, 0, ui2
->usri2_full_name
, -1,
340 buf
, maxSize
, NULL
, NULL
);
345 wxLogError(wxT("Couldn't look up full user name."));
348 #else // !USE_NET_API
349 // Could use NIS, MS-Mail or other site specific programs
350 // Use wxWidgets configuration data
351 bool ok
= GetProfileString(WX_SECTION
, eUSERNAME
, wxEmptyString
, buf
, maxSize
- 1) != 0;
354 ok
= wxGetUserId(buf
, maxSize
);
359 wxStrlcpy(buf
, wxT("Unknown User"), maxSize
);
366 const wxChar
* wxGetHomeDir(wxString
*pstr
)
368 wxString
& strDir
= *pstr
;
370 // first branch is for Cygwin
371 #if defined(__UNIX__) && !defined(__WINE__)
372 const wxChar
*szHome
= wxGetenv(wxT("HOME"));
373 if ( szHome
== NULL
) {
375 wxLogWarning(_("can't find user's HOME, using current directory."));
381 // add a trailing slash if needed
382 if ( strDir
.Last() != wxT('/') )
386 // Cygwin returns unix type path but that does not work well
387 static wxChar windowsPath
[MAX_PATH
];
388 #if CYGWIN_VERSION_DLL_MAJOR >= 1007
389 cygwin_conv_path(CCP_POSIX_TO_WIN_W
, strDir
, windowsPath
, MAX_PATH
);
391 cygwin_conv_to_full_win32_path(strDir
, windowsPath
);
393 strDir
= windowsPath
;
395 #elif defined(__WXWINCE__)
400 // If we have a valid HOME directory, as is used on many machines that
401 // have unix utilities on them, we should use that.
402 const wxChar
*szHome
= wxGetenv(wxT("HOME"));
404 if ( szHome
!= NULL
)
408 else // no HOME, try HOMEDRIVE/PATH
410 szHome
= wxGetenv(wxT("HOMEDRIVE"));
411 if ( szHome
!= NULL
)
413 szHome
= wxGetenv(wxT("HOMEPATH"));
415 if ( szHome
!= NULL
)
419 // the idea is that under NT these variables have default values
420 // of "%systemdrive%:" and "\\". As we don't want to create our
421 // config files in the root directory of the system drive, we will
422 // create it in our program's dir. However, if the user took care
423 // to set HOMEPATH to something other than "\\", we suppose that he
424 // knows what he is doing and use the supplied value.
425 if ( wxStrcmp(szHome
, wxT("\\")) == 0 )
430 if ( strDir
.empty() )
432 // If we have a valid USERPROFILE directory, as is the case in
433 // Windows NT, 2000 and XP, we should use that as our home directory.
434 szHome
= wxGetenv(wxT("USERPROFILE"));
436 if ( szHome
!= NULL
)
440 if ( !strDir
.empty() )
442 // sometimes the value of HOME may be "%USERPROFILE%", so reexpand the
443 // value once again, it shouldn't hurt anyhow
444 strDir
= wxExpandEnvVars(strDir
);
446 else // fall back to the program directory
448 // extract the directory component of the program file name
449 wxFileName::SplitPath(wxGetFullModuleName(), &strDir
, NULL
, NULL
);
453 return strDir
.c_str();
456 wxString
wxGetUserHome(const wxString
& user
)
460 if ( user
.empty() || user
== wxGetUserId() )
466 bool wxGetDiskSpace(const wxString
& WXUNUSED_IN_WINCE(path
),
467 wxDiskspaceSize_t
*WXUNUSED_IN_WINCE(pTotal
),
468 wxDiskspaceSize_t
*WXUNUSED_IN_WINCE(pFree
))
477 // old w32api don't have ULARGE_INTEGER
478 #if defined(__WIN32__) && \
479 (!defined(__GNUWIN32__) || wxCHECK_W32API_VERSION( 0, 3 ))
480 // GetDiskFreeSpaceEx() is not available under original Win95, check for
482 typedef BOOL (WINAPI
*GetDiskFreeSpaceEx_t
)(LPCTSTR
,
488 pGetDiskFreeSpaceEx
= (GetDiskFreeSpaceEx_t
)::GetProcAddress
490 ::GetModuleHandle(wxT("kernel32.dll")),
492 "GetDiskFreeSpaceExW"
494 "GetDiskFreeSpaceExA"
498 if ( pGetDiskFreeSpaceEx
)
500 ULARGE_INTEGER bytesFree
, bytesTotal
;
502 // may pass the path as is, GetDiskFreeSpaceEx() is smart enough
503 if ( !pGetDiskFreeSpaceEx(path
.t_str(),
508 wxLogLastError(wxT("GetDiskFreeSpaceEx"));
513 // ULARGE_INTEGER is a union of a 64 bit value and a struct containing
514 // two 32 bit fields which may be or may be not named - try to make it
515 // compile in all cases
516 #if defined(__BORLANDC__) && !defined(_ANONYMOUS_STRUCT)
524 *pTotal
= wxDiskspaceSize_t(UL(bytesTotal
).HighPart
, UL(bytesTotal
).LowPart
);
526 *pTotal
= wxDiskspaceSize_t(UL(bytesTotal
).LowPart
);
533 *pFree
= wxLongLong(UL(bytesFree
).HighPart
, UL(bytesFree
).LowPart
);
535 *pFree
= wxDiskspaceSize_t(UL(bytesFree
).LowPart
);
542 // there's a problem with drives larger than 2GB, GetDiskFreeSpaceEx()
543 // should be used instead - but if it's not available, fall back on
544 // GetDiskFreeSpace() nevertheless...
546 DWORD lSectorsPerCluster
,
548 lNumberOfFreeClusters
,
549 lTotalNumberOfClusters
;
551 // FIXME: this is wrong, we should extract the root drive from path
552 // instead, but this is the job for wxFileName...
553 if ( !::GetDiskFreeSpace(path
.t_str(),
556 &lNumberOfFreeClusters
,
557 &lTotalNumberOfClusters
) )
559 wxLogLastError(wxT("GetDiskFreeSpace"));
564 wxDiskspaceSize_t lBytesPerCluster
= (wxDiskspaceSize_t
) lSectorsPerCluster
;
565 lBytesPerCluster
*= lBytesPerSector
;
569 *pTotal
= lBytesPerCluster
;
570 *pTotal
*= lTotalNumberOfClusters
;
575 *pFree
= lBytesPerCluster
;
576 *pFree
*= lNumberOfFreeClusters
;
585 // ----------------------------------------------------------------------------
587 // ----------------------------------------------------------------------------
589 bool wxGetEnv(const wxString
& WXUNUSED_IN_WINCE(var
),
590 wxString
*WXUNUSED_IN_WINCE(value
))
593 // no environment variables under CE
596 // first get the size of the buffer
597 DWORD dwRet
= ::GetEnvironmentVariable(var
.t_str(), NULL
, 0);
600 // this means that there is no such variable
606 (void)::GetEnvironmentVariable(var
.t_str(),
607 wxStringBuffer(*value
, dwRet
),
615 bool wxDoSetEnv(const wxString
& var
, const wxChar
*value
)
618 // no environment variables under CE
622 #else // !__WXWINCE__
623 // update the CRT environment if possible as people expect getenv() to also
624 // work and it is not affected by Win32 SetEnvironmentVariable() call (OTOH
625 // the CRT does use Win32 call to update the process environment block so
626 // there is no need to call it)
628 // TODO: add checks for the other compilers (and update wxSetEnv()
629 // documentation in interface/wx/utils.h accordingly)
630 #if defined(__VISUALC__)
631 // notice that Microsoft _putenv() has different semantics from POSIX
632 // function with almost the same name: in particular it makes a copy of the
633 // string instead of using it as part of environment so we can safely call
634 // it here without going through all the troubles with wxSetEnvModule as in
635 // src/unix/utilsunx.cpp
636 wxString envstr
= var
;
640 _tputenv(envstr
.t_str());
641 #else // other compiler
642 if ( !::SetEnvironmentVariable(var
.t_str(), value
) )
644 wxLogLastError(wxT("SetEnvironmentVariable"));
651 #endif // __WXWINCE__/!__WXWINCE__
654 bool wxSetEnv(const wxString
& variable
, const wxString
& value
)
656 return wxDoSetEnv(variable
, value
.t_str());
659 bool wxUnsetEnv(const wxString
& variable
)
661 return wxDoSetEnv(variable
, NULL
);
664 // ----------------------------------------------------------------------------
665 // process management
666 // ----------------------------------------------------------------------------
668 // structure used to pass parameters from wxKill() to wxEnumFindByPidProc()
669 struct wxFindByPidParams
671 wxFindByPidParams() { hwnd
= 0; pid
= 0; }
673 // the HWND used to return the result
676 // the PID we're looking from
679 wxDECLARE_NO_COPY_CLASS(wxFindByPidParams
);
682 // wxKill helper: EnumWindows() callback which is used to find the first (top
683 // level) window belonging to the given process
684 BOOL CALLBACK
wxEnumFindByPidProc(HWND hwnd
, LPARAM lParam
)
687 (void)::GetWindowThreadProcessId(hwnd
, &pid
);
689 wxFindByPidParams
*params
= (wxFindByPidParams
*)lParam
;
690 if ( pid
== params
->pid
)
692 // remember the window we found
695 // return FALSE to stop the enumeration
699 // continue enumeration
703 int wxKillAllChildren(long pid
, wxSignal sig
, wxKillError
*krc
);
705 int wxKill(long pid
, wxSignal sig
, wxKillError
*krc
, int flags
)
707 if (flags
& wxKILL_CHILDREN
)
708 wxKillAllChildren(pid
, sig
, krc
);
710 // get the process handle to operate on
711 DWORD dwAccess
= PROCESS_QUERY_INFORMATION
| SYNCHRONIZE
;
712 if ( sig
== wxSIGKILL
)
713 dwAccess
|= PROCESS_TERMINATE
;
715 HANDLE hProcess
= ::OpenProcess(dwAccess
, FALSE
, (DWORD
)pid
);
716 if ( hProcess
== NULL
)
720 // recognize wxKILL_ACCESS_DENIED as special because this doesn't
721 // mean that the process doesn't exist and this is important for
722 // wxProcess::Exists()
723 *krc
= ::GetLastError() == ERROR_ACCESS_DENIED
724 ? wxKILL_ACCESS_DENIED
731 wxON_BLOCK_EXIT1(::CloseHandle
, hProcess
);
733 // Default timeout for waiting for the process termination after killing
734 // it. It should be long enough to allow the process to terminate even on a
735 // busy system but short enough to avoid blocking the main thread for too
737 DWORD waitTimeout
= 500; // ms
743 // kill the process forcefully returning -1 as error code
744 if ( !::TerminateProcess(hProcess
, (UINT
)-1) )
746 wxLogSysError(_("Failed to kill process %d"), pid
);
750 // this is not supposed to happen if we could open the
760 // Opening the process handle may succeed for a process even if it
761 // doesn't run any more (typically because open handles to it still
762 // exist elsewhere, possibly in this process itself if we're
763 // killing a child process) so we still need check if it hasn't
764 // terminated yet but, unlike when killing it, we don't need to
765 // wait for any time at all.
770 // any other signal means "terminate"
772 wxFindByPidParams params
;
773 params
.pid
= (DWORD
)pid
;
775 // EnumWindows() has nice semantics: it returns 0 if it found
776 // something or if an error occurred and non zero if it
777 // enumerated all the window
778 if ( !::EnumWindows(wxEnumFindByPidProc
, (LPARAM
)¶ms
) )
780 // did we find any window?
783 // tell the app to close
785 // NB: this is the harshest way, the app won't have an
786 // opportunity to save any files, for example, but
787 // this is probably what we want here. If not we
788 // can also use SendMesageTimeout(WM_CLOSE)
789 if ( !::PostMessage(params
.hwnd
, WM_QUIT
, 0, 0) )
791 wxLogLastError(wxT("PostMessage(WM_QUIT)"));
794 else // it was an error then
796 wxLogLastError(wxT("EnumWindows"));
801 else // no windows for this PID
814 // as we wait for a short time, we can use just WaitForSingleObject()
815 // and not MsgWaitForMultipleObjects()
816 switch ( ::WaitForSingleObject(hProcess
, waitTimeout
) )
819 // Process terminated: normally this indicates that we
820 // successfully killed it but when testing for the process
821 // existence, this means failure.
822 if ( sig
== wxSIGNONE
)
825 *krc
= wxKILL_NO_PROCESS
;
832 wxFAIL_MSG( wxT("unexpected WaitForSingleObject() return") );
836 wxLogLastError(wxT("WaitForSingleObject"));
840 // Process didn't terminate: normally this is a failure but not
841 // when we're just testing for its existence.
842 if ( sig
!= wxSIGNONE
)
854 // the return code is the same as from Unix kill(): 0 if killed
855 // successfully or -1 on error
865 typedef HANDLE (WINAPI
*CreateToolhelp32Snapshot_t
)(DWORD
,DWORD
);
866 typedef BOOL (WINAPI
*Process32_t
)(HANDLE
,LPPROCESSENTRY32
);
868 CreateToolhelp32Snapshot_t lpfCreateToolhelp32Snapshot
;
869 Process32_t lpfProcess32First
, lpfProcess32Next
;
871 static void InitToolHelp32()
873 static bool s_initToolHelpDone
= false;
875 if (s_initToolHelpDone
)
878 s_initToolHelpDone
= true;
880 lpfCreateToolhelp32Snapshot
= NULL
;
881 lpfProcess32First
= NULL
;
882 lpfProcess32Next
= NULL
;
884 #if wxUSE_DYNLIB_CLASS
886 wxDynamicLibrary
dllKernel(wxT("kernel32.dll"), wxDL_VERBATIM
);
888 // Get procedure addresses.
889 // We are linking to these functions of Kernel32
890 // explicitly, because otherwise a module using
891 // this code would fail to load under Windows NT,
892 // which does not have the Toolhelp32
893 // functions in the Kernel 32.
894 lpfCreateToolhelp32Snapshot
=
895 (CreateToolhelp32Snapshot_t
)dllKernel
.RawGetSymbol(wxT("CreateToolhelp32Snapshot"));
898 (Process32_t
)dllKernel
.RawGetSymbol(wxT("Process32First"));
901 (Process32_t
)dllKernel
.RawGetSymbol(wxT("Process32Next"));
903 #endif // wxUSE_DYNLIB_CLASS
907 int wxKillAllChildren(long pid
, wxSignal sig
, wxKillError
*krc
)
914 // If not implemented for this platform (e.g. NT 4.0), silently ignore
915 if (!lpfCreateToolhelp32Snapshot
|| !lpfProcess32First
|| !lpfProcess32Next
)
918 // Take a snapshot of all processes in the system.
919 HANDLE hProcessSnap
= lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0);
920 if (hProcessSnap
== INVALID_HANDLE_VALUE
) {
926 //Fill in the size of the structure before using it.
929 pe
.dwSize
= sizeof(PROCESSENTRY32
);
931 // Walk the snapshot of the processes, and for each process,
932 // kill it if its parent is pid.
933 if (!lpfProcess32First(hProcessSnap
, &pe
)) {
934 // Can't get first process.
937 CloseHandle (hProcessSnap
);
942 if (pe
.th32ParentProcessID
== (DWORD
) pid
) {
943 if (wxKill(pe
.th32ProcessID
, sig
, krc
))
946 } while (lpfProcess32Next (hProcessSnap
, &pe
));
952 // Execute a program in an Interactive Shell
953 bool wxShell(const wxString
& command
)
960 wxChar
*shell
= wxGetenv(wxT("COMSPEC"));
962 shell
= (wxChar
*) wxT("\\COMMAND.COM");
971 // pass the command to execute to the command processor
972 cmd
.Printf(wxT("%s /c %s"), shell
, command
.c_str());
976 return wxExecute(cmd
, wxEXEC_SYNC
) == 0;
979 // Shutdown or reboot the PC
980 bool wxShutdown(int WXUNUSED_IN_WINCE(flags
))
985 #elif defined(__WIN32__)
988 if ( wxGetOsVersion(NULL
, NULL
) == wxOS_WINDOWS_NT
) // if is NT or 2K
990 // Get a token for this process.
992 bOK
= ::OpenProcessToken(GetCurrentProcess(),
993 TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
,
997 TOKEN_PRIVILEGES tkp
;
999 // Get the LUID for the shutdown privilege.
1000 bOK
= ::LookupPrivilegeValue(NULL
, SE_SHUTDOWN_NAME
,
1001 &tkp
.Privileges
[0].Luid
) != 0;
1005 tkp
.PrivilegeCount
= 1; // one privilege to set
1006 tkp
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
1008 // Get the shutdown privilege for this process.
1009 ::AdjustTokenPrivileges(hToken
, FALSE
, &tkp
, 0,
1010 (PTOKEN_PRIVILEGES
)NULL
, 0);
1012 // Cannot test the return value of AdjustTokenPrivileges.
1013 bOK
= ::GetLastError() == ERROR_SUCCESS
;
1016 ::CloseHandle(hToken
);
1023 if ( flags
& wxSHUTDOWN_FORCE
)
1026 flags
&= ~wxSHUTDOWN_FORCE
;
1031 case wxSHUTDOWN_POWEROFF
:
1032 wFlags
|= EWX_POWEROFF
;
1035 case wxSHUTDOWN_REBOOT
:
1036 wFlags
|= EWX_REBOOT
;
1039 case wxSHUTDOWN_LOGOFF
:
1040 wFlags
|= EWX_LOGOFF
;
1044 wxFAIL_MSG( wxT("unknown wxShutdown() flag") );
1048 bOK
= ::ExitWindowsEx(wFlags
, 0) != 0;
1052 #endif // WinCE/!WinCE
1055 // ----------------------------------------------------------------------------
1057 // ----------------------------------------------------------------------------
1059 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
1060 wxMemorySize
wxGetFreeMemory()
1062 #if defined(__WIN64__)
1063 MEMORYSTATUSEX memStatex
;
1064 memStatex
.dwLength
= sizeof (memStatex
);
1065 ::GlobalMemoryStatusEx (&memStatex
);
1066 return (wxMemorySize
)memStatex
.ullAvailPhys
;
1067 #else /* if defined(__WIN32__) */
1068 MEMORYSTATUS memStatus
;
1069 memStatus
.dwLength
= sizeof(MEMORYSTATUS
);
1070 ::GlobalMemoryStatus(&memStatus
);
1071 return (wxMemorySize
)memStatus
.dwAvailPhys
;
1075 unsigned long wxGetProcessId()
1077 return ::GetCurrentProcessId();
1083 ::MessageBeep((UINT
)-1); // default sound
1086 bool wxIsDebuggerRunning()
1088 #if wxUSE_DYNLIB_CLASS
1089 // IsDebuggerPresent() is not available under Win95, so load it dynamically
1090 wxDynamicLibrary
dll(wxT("kernel32.dll"), wxDL_VERBATIM
);
1092 typedef BOOL (WINAPI
*IsDebuggerPresent_t
)();
1093 if ( !dll
.HasSymbol(wxT("IsDebuggerPresent")) )
1095 // no way to know, assume no
1099 return (*(IsDebuggerPresent_t
)dll
.GetSymbol(wxT("IsDebuggerPresent")))() != 0;
1105 // ----------------------------------------------------------------------------
1106 // working with MSW resources
1107 // ----------------------------------------------------------------------------
1110 wxLoadUserResource(const void **outData
,
1112 const wxString
& resourceName
,
1113 const wxString
& resourceType
,
1114 WXHINSTANCE instance
)
1116 wxCHECK_MSG( outData
&& outLen
, false, "output pointers can't be NULL" );
1118 HRSRC hResource
= ::FindResource(instance
,
1119 resourceName
.wx_str(),
1120 resourceType
.wx_str());
1124 HGLOBAL hData
= ::LoadResource(instance
, hResource
);
1127 wxLogSysError(_("Failed to load resource \"%s\"."), resourceName
);
1131 *outData
= ::LockResource(hData
);
1134 wxLogSysError(_("Failed to lock resource \"%s\"."), resourceName
);
1138 *outLen
= ::SizeofResource(instance
, hResource
);
1140 // Notice that we do not need to call neither UnlockResource() (which is
1141 // obsolete in Win32) nor GlobalFree() (resources are freed on process
1142 // termination only)
1148 wxLoadUserResource(const wxString
& resourceName
,
1149 const wxString
& resourceType
,
1151 WXHINSTANCE instance
)
1155 if ( !wxLoadUserResource(&data
, &len
, resourceName
, resourceType
, instance
) )
1158 char *s
= new char[len
+ 1];
1159 memcpy(s
, data
, len
);
1160 s
[len
] = '\0'; // NUL-terminate in case the resource itself wasn't
1168 // ----------------------------------------------------------------------------
1170 // ----------------------------------------------------------------------------
1172 // check if we're running under a server or workstation Windows system: it
1173 // returns true or false with obvious meaning as well as -1 if the system type
1174 // couldn't be determined
1176 // this function is currently private but we may want to expose it later if
1177 // it's really useful
1181 int wxIsWindowsServer()
1183 #ifdef VER_NT_WORKSTATION
1184 OSVERSIONINFOEX info
;
1187 info
.dwOSVersionInfoSize
= sizeof(info
);
1188 if ( ::GetVersionEx(reinterpret_cast<OSVERSIONINFO
*>(&info
)) )
1190 switch ( info
.wProductType
)
1192 case VER_NT_WORKSTATION
:
1196 case VER_NT_DOMAIN_CONTROLLER
:
1200 #endif // VER_NT_WORKSTATION
1205 } // anonymous namespace
1207 wxString
wxGetOsDescription()
1214 info
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
1215 if ( ::GetVersionEx(&info
) )
1217 switch ( info
.dwPlatformId
)
1219 #ifdef VER_PLATFORM_WIN32_CE
1220 case VER_PLATFORM_WIN32_CE
:
1221 str
.Printf(_("Windows CE (%d.%d)"),
1222 info
.dwMajorVersion
,
1223 info
.dwMinorVersion
);
1226 case VER_PLATFORM_WIN32s
:
1227 str
= _("Win32s on Windows 3.1");
1230 case VER_PLATFORM_WIN32_WINDOWS
:
1231 switch (info
.dwMinorVersion
)
1234 if ( info
.szCSDVersion
[1] == 'B' ||
1235 info
.szCSDVersion
[1] == 'C' )
1237 str
= _("Windows 95 OSR2");
1241 str
= _("Windows 95");
1245 if ( info
.szCSDVersion
[1] == 'B' ||
1246 info
.szCSDVersion
[1] == 'C' )
1248 str
= _("Windows 98 SE");
1252 str
= _("Windows 98");
1256 str
= _("Windows ME");
1259 str
.Printf(_("Windows 9x (%d.%d)"),
1260 info
.dwMajorVersion
,
1261 info
.dwMinorVersion
);
1264 if ( !wxIsEmpty(info
.szCSDVersion
) )
1266 str
<< wxT(" (") << info
.szCSDVersion
<< wxT(')');
1270 case VER_PLATFORM_WIN32_NT
:
1271 switch ( info
.dwMajorVersion
)
1274 switch ( info
.dwMinorVersion
)
1277 str
.Printf(_("Windows 2000 (build %lu"),
1278 info
.dwBuildNumber
);
1282 // we can't distinguish between XP 64 and 2003
1283 // as they both are 5.2, so examine the product
1284 // type to resolve this ambiguity
1285 if ( wxIsWindowsServer() == 1 )
1287 str
.Printf(_("Windows Server 2003 (build %lu"),
1288 info
.dwBuildNumber
);
1291 //else: must be XP, fall through
1294 str
.Printf(_("Windows XP (build %lu"),
1295 info
.dwBuildNumber
);
1301 if ( info
.dwMinorVersion
== 0 )
1303 str
.Printf(_("Windows Vista (build %lu"),
1304 info
.dwBuildNumber
);
1311 str
.Printf(_("Windows NT %lu.%lu (build %lu"),
1312 info
.dwMajorVersion
,
1313 info
.dwMinorVersion
,
1314 info
.dwBuildNumber
);
1317 if ( !wxIsEmpty(info
.szCSDVersion
) )
1319 str
<< wxT(", ") << info
.szCSDVersion
;
1323 if ( wxIsPlatform64Bit() )
1324 str
<< _(", 64-bit edition");
1330 wxFAIL_MSG( wxT("GetVersionEx() failed") ); // should never happen
1336 bool wxIsPlatform64Bit()
1339 return true; // 64-bit programs run only on Win64
1340 #elif wxUSE_DYNLIB_CLASS // Win32
1341 // 32-bit programs run on both 32-bit and 64-bit Windows so check
1342 typedef BOOL (WINAPI
*IsWow64Process_t
)(HANDLE
, BOOL
*);
1344 wxDynamicLibrary
dllKernel32(wxT("kernel32.dll"));
1345 IsWow64Process_t pfnIsWow64Process
=
1346 (IsWow64Process_t
)dllKernel32
.RawGetSymbol(wxT("IsWow64Process"));
1349 if ( pfnIsWow64Process
)
1351 pfnIsWow64Process(::GetCurrentProcess(), &wow64
);
1353 //else: running under a system without Win64 support
1355 return wow64
!= FALSE
;
1358 #endif // Win64/Win32
1361 wxOperatingSystemId
wxGetOsVersion(int *verMaj
, int *verMin
)
1365 // this may be false, true or -1 if we tried to initialize but failed
1368 wxOperatingSystemId os
;
1374 // query the OS info only once as it's not supposed to change
1375 if ( !s_version
.initialized
)
1379 info
.dwOSVersionInfoSize
= sizeof(info
);
1380 if ( ::GetVersionEx(&info
) )
1382 s_version
.initialized
= true;
1384 #if defined(__WXWINCE__)
1385 s_version
.os
= wxOS_WINDOWS_CE
;
1386 #elif defined(__WXMICROWIN__)
1387 s_version
.os
= wxOS_WINDOWS_MICRO
;
1388 #else // "normal" desktop Windows system, use run-time detection
1389 switch ( info
.dwPlatformId
)
1391 case VER_PLATFORM_WIN32_NT
:
1392 s_version
.os
= wxOS_WINDOWS_NT
;
1395 case VER_PLATFORM_WIN32_WINDOWS
:
1396 s_version
.os
= wxOS_WINDOWS_9X
;
1399 #endif // Windows versions
1401 s_version
.verMaj
= info
.dwMajorVersion
;
1402 s_version
.verMin
= info
.dwMinorVersion
;
1404 else // GetVersionEx() failed
1406 s_version
.initialized
= -1;
1410 if ( s_version
.initialized
== 1 )
1413 *verMaj
= s_version
.verMaj
;
1415 *verMin
= s_version
.verMin
;
1418 // this works even if we were not initialized successfully as the initial
1419 // values of this field is 0 which is wxOS_UNKNOWN and exactly what we need
1420 return s_version
.os
;
1423 wxWinVersion
wxGetWinVersion()
1427 switch ( wxGetOsVersion(&verMaj
, &verMin
) )
1429 case wxOS_WINDOWS_9X
:
1435 return wxWinVersion_95
;
1438 return wxWinVersion_98
;
1441 return wxWinVersion_ME
;
1446 case wxOS_WINDOWS_NT
:
1450 return wxWinVersion_NT3
;
1453 return wxWinVersion_NT4
;
1459 return wxWinVersion_2000
;
1462 return wxWinVersion_XP
;
1465 return wxWinVersion_2003
;
1470 return wxWinVersion_NT6
;
1475 // Do nothing just to silence GCC warning
1479 return wxWinVersion_Unknown
;
1482 // ----------------------------------------------------------------------------
1484 // ----------------------------------------------------------------------------
1486 void wxMilliSleep(unsigned long milliseconds
)
1488 ::Sleep(milliseconds
);
1491 void wxMicroSleep(unsigned long microseconds
)
1493 wxMilliSleep(microseconds
/1000);
1496 void wxSleep(int nSecs
)
1498 wxMilliSleep(1000*nSecs
);
1501 // ----------------------------------------------------------------------------
1502 // font encoding <-> Win32 codepage conversion functions
1503 // ----------------------------------------------------------------------------
1505 extern WXDLLIMPEXP_BASE
long wxEncodingToCharset(wxFontEncoding encoding
)
1509 // although this function is supposed to return an exact match, do do
1510 // some mappings here for the most common case of "standard" encoding
1511 case wxFONTENCODING_SYSTEM
:
1512 return DEFAULT_CHARSET
;
1514 case wxFONTENCODING_ISO8859_1
:
1515 case wxFONTENCODING_ISO8859_15
:
1516 case wxFONTENCODING_CP1252
:
1517 return ANSI_CHARSET
;
1519 #if !defined(__WXMICROWIN__)
1520 // The following four fonts are multi-byte charsets
1521 case wxFONTENCODING_CP932
:
1522 return SHIFTJIS_CHARSET
;
1524 case wxFONTENCODING_CP936
:
1525 return GB2312_CHARSET
;
1528 case wxFONTENCODING_CP949
:
1529 return HANGUL_CHARSET
;
1532 case wxFONTENCODING_CP950
:
1533 return CHINESEBIG5_CHARSET
;
1535 // The rest are single byte encodings
1536 case wxFONTENCODING_CP1250
:
1537 return EASTEUROPE_CHARSET
;
1539 case wxFONTENCODING_CP1251
:
1540 return RUSSIAN_CHARSET
;
1542 case wxFONTENCODING_CP1253
:
1543 return GREEK_CHARSET
;
1545 case wxFONTENCODING_CP1254
:
1546 return TURKISH_CHARSET
;
1548 case wxFONTENCODING_CP1255
:
1549 return HEBREW_CHARSET
;
1551 case wxFONTENCODING_CP1256
:
1552 return ARABIC_CHARSET
;
1554 case wxFONTENCODING_CP1257
:
1555 return BALTIC_CHARSET
;
1557 case wxFONTENCODING_CP874
:
1558 return THAI_CHARSET
;
1559 #endif // !__WXMICROWIN__
1561 case wxFONTENCODING_CP437
:
1565 // no way to translate this encoding into a Windows charset
1570 // we have 2 versions of wxCharsetToCodepage(): the old one which directly
1571 // looks up the vlaues in the registry and the new one which is more
1572 // politically correct and has more chances to work on other Windows versions
1573 // as well but the old version is still needed for !wxUSE_FONTMAP case
1576 #include "wx/fontmap.h"
1578 extern WXDLLIMPEXP_BASE
long wxEncodingToCodepage(wxFontEncoding encoding
)
1580 // There don't seem to be symbolic names for
1581 // these under Windows so I just copied the
1582 // values from MSDN.
1588 case wxFONTENCODING_ISO8859_1
: ret
= 28591; break;
1589 case wxFONTENCODING_ISO8859_2
: ret
= 28592; break;
1590 case wxFONTENCODING_ISO8859_3
: ret
= 28593; break;
1591 case wxFONTENCODING_ISO8859_4
: ret
= 28594; break;
1592 case wxFONTENCODING_ISO8859_5
: ret
= 28595; break;
1593 case wxFONTENCODING_ISO8859_6
: ret
= 28596; break;
1594 case wxFONTENCODING_ISO8859_7
: ret
= 28597; break;
1595 case wxFONTENCODING_ISO8859_8
: ret
= 28598; break;
1596 case wxFONTENCODING_ISO8859_9
: ret
= 28599; break;
1597 case wxFONTENCODING_ISO8859_10
: ret
= 28600; break;
1598 case wxFONTENCODING_ISO8859_11
: ret
= 874; break;
1599 // case wxFONTENCODING_ISO8859_12, // doesn't exist currently, but put it
1600 case wxFONTENCODING_ISO8859_13
: ret
= 28603; break;
1601 // case wxFONTENCODING_ISO8859_14: ret = 28604; break; // no correspondence on Windows
1602 case wxFONTENCODING_ISO8859_15
: ret
= 28605; break;
1604 case wxFONTENCODING_KOI8
: ret
= 20866; break;
1605 case wxFONTENCODING_KOI8_U
: ret
= 21866; break;
1607 case wxFONTENCODING_CP437
: ret
= 437; break;
1608 case wxFONTENCODING_CP850
: ret
= 850; break;
1609 case wxFONTENCODING_CP852
: ret
= 852; break;
1610 case wxFONTENCODING_CP855
: ret
= 855; break;
1611 case wxFONTENCODING_CP866
: ret
= 866; break;
1612 case wxFONTENCODING_CP874
: ret
= 874; break;
1613 case wxFONTENCODING_CP932
: ret
= 932; break;
1614 case wxFONTENCODING_CP936
: ret
= 936; break;
1615 case wxFONTENCODING_CP949
: ret
= 949; break;
1616 case wxFONTENCODING_CP950
: ret
= 950; break;
1617 case wxFONTENCODING_CP1250
: ret
= 1250; break;
1618 case wxFONTENCODING_CP1251
: ret
= 1251; break;
1619 case wxFONTENCODING_CP1252
: ret
= 1252; break;
1620 case wxFONTENCODING_CP1253
: ret
= 1253; break;
1621 case wxFONTENCODING_CP1254
: ret
= 1254; break;
1622 case wxFONTENCODING_CP1255
: ret
= 1255; break;
1623 case wxFONTENCODING_CP1256
: ret
= 1256; break;
1624 case wxFONTENCODING_CP1257
: ret
= 1257; break;
1626 case wxFONTENCODING_EUC_JP
: ret
= 20932; break;
1628 case wxFONTENCODING_MACROMAN
: ret
= 10000; break;
1629 case wxFONTENCODING_MACJAPANESE
: ret
= 10001; break;
1630 case wxFONTENCODING_MACCHINESETRAD
: ret
= 10002; break;
1631 case wxFONTENCODING_MACKOREAN
: ret
= 10003; break;
1632 case wxFONTENCODING_MACARABIC
: ret
= 10004; break;
1633 case wxFONTENCODING_MACHEBREW
: ret
= 10005; break;
1634 case wxFONTENCODING_MACGREEK
: ret
= 10006; break;
1635 case wxFONTENCODING_MACCYRILLIC
: ret
= 10007; break;
1636 case wxFONTENCODING_MACTHAI
: ret
= 10021; break;
1637 case wxFONTENCODING_MACCHINESESIMP
: ret
= 10008; break;
1638 case wxFONTENCODING_MACCENTRALEUR
: ret
= 10029; break;
1639 case wxFONTENCODING_MACCROATIAN
: ret
= 10082; break;
1640 case wxFONTENCODING_MACICELANDIC
: ret
= 10079; break;
1641 case wxFONTENCODING_MACROMANIAN
: ret
= 10009; break;
1643 case wxFONTENCODING_ISO2022_JP
: ret
= 50222; break;
1645 case wxFONTENCODING_UTF7
: ret
= 65000; break;
1646 case wxFONTENCODING_UTF8
: ret
= 65001; break;
1651 if (::IsValidCodePage(ret
) == 0)
1655 if (::GetCPInfo(ret
, &info
) == 0)
1661 extern long wxCharsetToCodepage(const char *name
)
1663 // first get the font encoding for this charset
1667 wxFontEncoding enc
= wxFontMapperBase::Get()->CharsetToEncoding(name
, false);
1668 if ( enc
== wxFONTENCODING_SYSTEM
)
1671 // the use the helper function
1672 return wxEncodingToCodepage(enc
);
1675 #else // !wxUSE_FONTMAP
1677 #include "wx/msw/registry.h"
1679 // this should work if Internet Exploiter is installed
1680 extern long wxCharsetToCodepage(const char *name
)
1688 wxString
path(wxT("MIME\\Database\\Charset\\"));
1691 // follow the alias loop
1694 wxRegKey
key(wxRegKey::HKCR
, path
+ cn
);
1699 // two cases: either there's an AliasForCharset string,
1700 // or there are Codepage and InternetEncoding dwords.
1701 // The InternetEncoding gives us the actual encoding,
1702 // the Codepage just says which Windows character set to
1703 // use when displaying the data.
1704 if (key
.HasValue(wxT("InternetEncoding")) &&
1705 key
.QueryValue(wxT("InternetEncoding"), &CP
))
1708 // no encoding, see if it's an alias
1709 if (!key
.HasValue(wxT("AliasForCharset")) ||
1710 !key
.QueryValue(wxT("AliasForCharset"), cn
))
1713 #endif // wxUSE_REGKEY
1718 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
1721 Creates a hidden window with supplied window proc registering the class for
1722 it if necesssary (i.e. the first time only). Caller is responsible for
1723 destroying the window and unregistering the class (note that this must be
1724 done because wxWidgets may be used as a DLL and so may be loaded/unloaded
1725 multiple times into/from the same process so we cna't rely on automatic
1726 Windows class unregistration).
1728 pclassname is a pointer to a caller stored classname, which must initially be
1729 NULL. classname is the desired wndclass classname. If function successfully
1730 registers the class, pclassname will be set to classname.
1732 extern "C" WXDLLIMPEXP_BASE HWND
1733 wxCreateHiddenWindow(LPCTSTR
*pclassname
, LPCTSTR classname
, WNDPROC wndproc
)
1735 wxCHECK_MSG( classname
&& pclassname
&& wndproc
, NULL
,
1736 wxT("NULL parameter in wxCreateHiddenWindow") );
1738 // register the class fi we need to first
1739 if ( *pclassname
== NULL
)
1742 wxZeroMemory(wndclass
);
1744 wndclass
.lpfnWndProc
= wndproc
;
1745 wndclass
.hInstance
= wxGetInstance();
1746 wndclass
.lpszClassName
= classname
;
1748 if ( !::RegisterClass(&wndclass
) )
1750 wxLogLastError(wxT("RegisterClass() in wxCreateHiddenWindow"));
1755 *pclassname
= classname
;
1758 // next create the window
1759 HWND hwnd
= ::CreateWindow
1773 wxLogLastError(wxT("CreateWindow() in wxCreateHiddenWindow"));