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("Cannot 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__) || defined(__MINGW32__)
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
= _("Windows 2000");
1281 // we can't distinguish between XP 64 and 2003
1282 // as they both are 5.2, so examine the product
1283 // type to resolve this ambiguity
1284 if ( wxIsWindowsServer() == 1 )
1286 str
= _("Windows Server 2003");
1289 //else: must be XP, fall through
1292 str
= _("Windows XP");
1298 switch ( info
.dwMinorVersion
)
1301 str
= wxIsWindowsServer() == 1
1302 ? _("Windows Server 2008")
1303 : _("Windows Vista");
1307 str
= wxIsWindowsServer() == 1
1308 ? _("Windows Server 2008 R2")
1317 str
.Printf(_("Windows NT %lu.%lu"),
1318 info
.dwMajorVersion
,
1319 info
.dwMinorVersion
);
1323 << wxString::Format(_("build %lu"), info
.dwBuildNumber
);
1324 if ( !wxIsEmpty(info
.szCSDVersion
) )
1326 str
<< wxT(", ") << info
.szCSDVersion
;
1330 if ( wxIsPlatform64Bit() )
1331 str
<< _(", 64-bit edition");
1337 wxFAIL_MSG( wxT("GetVersionEx() failed") ); // should never happen
1343 bool wxIsPlatform64Bit()
1346 return true; // 64-bit programs run only on Win64
1347 #elif wxUSE_DYNLIB_CLASS // Win32
1348 // 32-bit programs run on both 32-bit and 64-bit Windows so check
1349 typedef BOOL (WINAPI
*IsWow64Process_t
)(HANDLE
, BOOL
*);
1351 wxDynamicLibrary
dllKernel32(wxT("kernel32.dll"));
1352 IsWow64Process_t pfnIsWow64Process
=
1353 (IsWow64Process_t
)dllKernel32
.RawGetSymbol(wxT("IsWow64Process"));
1356 if ( pfnIsWow64Process
)
1358 pfnIsWow64Process(::GetCurrentProcess(), &wow64
);
1360 //else: running under a system without Win64 support
1362 return wow64
!= FALSE
;
1365 #endif // Win64/Win32
1368 wxOperatingSystemId
wxGetOsVersion(int *verMaj
, int *verMin
)
1372 // this may be false, true or -1 if we tried to initialize but failed
1375 wxOperatingSystemId os
;
1381 // query the OS info only once as it's not supposed to change
1382 if ( !s_version
.initialized
)
1386 info
.dwOSVersionInfoSize
= sizeof(info
);
1387 if ( ::GetVersionEx(&info
) )
1389 s_version
.initialized
= true;
1391 #if defined(__WXWINCE__)
1392 s_version
.os
= wxOS_WINDOWS_CE
;
1393 #elif defined(__WXMICROWIN__)
1394 s_version
.os
= wxOS_WINDOWS_MICRO
;
1395 #else // "normal" desktop Windows system, use run-time detection
1396 switch ( info
.dwPlatformId
)
1398 case VER_PLATFORM_WIN32_NT
:
1399 s_version
.os
= wxOS_WINDOWS_NT
;
1402 case VER_PLATFORM_WIN32_WINDOWS
:
1403 s_version
.os
= wxOS_WINDOWS_9X
;
1406 #endif // Windows versions
1408 s_version
.verMaj
= info
.dwMajorVersion
;
1409 s_version
.verMin
= info
.dwMinorVersion
;
1411 else // GetVersionEx() failed
1413 s_version
.initialized
= -1;
1417 if ( s_version
.initialized
== 1 )
1420 *verMaj
= s_version
.verMaj
;
1422 *verMin
= s_version
.verMin
;
1425 // this works even if we were not initialized successfully as the initial
1426 // values of this field is 0 which is wxOS_UNKNOWN and exactly what we need
1427 return s_version
.os
;
1430 wxWinVersion
wxGetWinVersion()
1434 switch ( wxGetOsVersion(&verMaj
, &verMin
) )
1436 case wxOS_WINDOWS_9X
:
1442 return wxWinVersion_95
;
1445 return wxWinVersion_98
;
1448 return wxWinVersion_ME
;
1453 case wxOS_WINDOWS_NT
:
1457 return wxWinVersion_NT3
;
1460 return wxWinVersion_NT4
;
1466 return wxWinVersion_2000
;
1469 return wxWinVersion_XP
;
1472 return wxWinVersion_2003
;
1477 return wxWinVersion_NT6
;
1482 // Do nothing just to silence GCC warning
1486 return wxWinVersion_Unknown
;
1489 // ----------------------------------------------------------------------------
1491 // ----------------------------------------------------------------------------
1493 void wxMilliSleep(unsigned long milliseconds
)
1495 ::Sleep(milliseconds
);
1498 void wxMicroSleep(unsigned long microseconds
)
1500 wxMilliSleep(microseconds
/1000);
1503 void wxSleep(int nSecs
)
1505 wxMilliSleep(1000*nSecs
);
1508 // ----------------------------------------------------------------------------
1509 // font encoding <-> Win32 codepage conversion functions
1510 // ----------------------------------------------------------------------------
1512 extern WXDLLIMPEXP_BASE
long wxEncodingToCharset(wxFontEncoding encoding
)
1516 // although this function is supposed to return an exact match, do do
1517 // some mappings here for the most common case of "standard" encoding
1518 case wxFONTENCODING_SYSTEM
:
1519 return DEFAULT_CHARSET
;
1521 case wxFONTENCODING_ISO8859_1
:
1522 case wxFONTENCODING_ISO8859_15
:
1523 case wxFONTENCODING_CP1252
:
1524 return ANSI_CHARSET
;
1526 #if !defined(__WXMICROWIN__)
1527 // The following four fonts are multi-byte charsets
1528 case wxFONTENCODING_CP932
:
1529 return SHIFTJIS_CHARSET
;
1531 case wxFONTENCODING_CP936
:
1532 return GB2312_CHARSET
;
1535 case wxFONTENCODING_CP949
:
1536 return HANGUL_CHARSET
;
1539 case wxFONTENCODING_CP950
:
1540 return CHINESEBIG5_CHARSET
;
1542 // The rest are single byte encodings
1543 case wxFONTENCODING_CP1250
:
1544 return EASTEUROPE_CHARSET
;
1546 case wxFONTENCODING_CP1251
:
1547 return RUSSIAN_CHARSET
;
1549 case wxFONTENCODING_CP1253
:
1550 return GREEK_CHARSET
;
1552 case wxFONTENCODING_CP1254
:
1553 return TURKISH_CHARSET
;
1555 case wxFONTENCODING_CP1255
:
1556 return HEBREW_CHARSET
;
1558 case wxFONTENCODING_CP1256
:
1559 return ARABIC_CHARSET
;
1561 case wxFONTENCODING_CP1257
:
1562 return BALTIC_CHARSET
;
1564 case wxFONTENCODING_CP874
:
1565 return THAI_CHARSET
;
1566 #endif // !__WXMICROWIN__
1568 case wxFONTENCODING_CP437
:
1572 // no way to translate this encoding into a Windows charset
1577 // we have 2 versions of wxCharsetToCodepage(): the old one which directly
1578 // looks up the vlaues in the registry and the new one which is more
1579 // politically correct and has more chances to work on other Windows versions
1580 // as well but the old version is still needed for !wxUSE_FONTMAP case
1583 #include "wx/fontmap.h"
1585 extern WXDLLIMPEXP_BASE
long wxEncodingToCodepage(wxFontEncoding encoding
)
1587 // There don't seem to be symbolic names for
1588 // these under Windows so I just copied the
1589 // values from MSDN.
1595 case wxFONTENCODING_ISO8859_1
: ret
= 28591; break;
1596 case wxFONTENCODING_ISO8859_2
: ret
= 28592; break;
1597 case wxFONTENCODING_ISO8859_3
: ret
= 28593; break;
1598 case wxFONTENCODING_ISO8859_4
: ret
= 28594; break;
1599 case wxFONTENCODING_ISO8859_5
: ret
= 28595; break;
1600 case wxFONTENCODING_ISO8859_6
: ret
= 28596; break;
1601 case wxFONTENCODING_ISO8859_7
: ret
= 28597; break;
1602 case wxFONTENCODING_ISO8859_8
: ret
= 28598; break;
1603 case wxFONTENCODING_ISO8859_9
: ret
= 28599; break;
1604 case wxFONTENCODING_ISO8859_10
: ret
= 28600; break;
1605 case wxFONTENCODING_ISO8859_11
: ret
= 874; break;
1606 // case wxFONTENCODING_ISO8859_12, // doesn't exist currently, but put it
1607 case wxFONTENCODING_ISO8859_13
: ret
= 28603; break;
1608 // case wxFONTENCODING_ISO8859_14: ret = 28604; break; // no correspondence on Windows
1609 case wxFONTENCODING_ISO8859_15
: ret
= 28605; break;
1611 case wxFONTENCODING_KOI8
: ret
= 20866; break;
1612 case wxFONTENCODING_KOI8_U
: ret
= 21866; break;
1614 case wxFONTENCODING_CP437
: ret
= 437; break;
1615 case wxFONTENCODING_CP850
: ret
= 850; break;
1616 case wxFONTENCODING_CP852
: ret
= 852; break;
1617 case wxFONTENCODING_CP855
: ret
= 855; break;
1618 case wxFONTENCODING_CP866
: ret
= 866; break;
1619 case wxFONTENCODING_CP874
: ret
= 874; break;
1620 case wxFONTENCODING_CP932
: ret
= 932; break;
1621 case wxFONTENCODING_CP936
: ret
= 936; break;
1622 case wxFONTENCODING_CP949
: ret
= 949; break;
1623 case wxFONTENCODING_CP950
: ret
= 950; break;
1624 case wxFONTENCODING_CP1250
: ret
= 1250; break;
1625 case wxFONTENCODING_CP1251
: ret
= 1251; break;
1626 case wxFONTENCODING_CP1252
: ret
= 1252; break;
1627 case wxFONTENCODING_CP1253
: ret
= 1253; break;
1628 case wxFONTENCODING_CP1254
: ret
= 1254; break;
1629 case wxFONTENCODING_CP1255
: ret
= 1255; break;
1630 case wxFONTENCODING_CP1256
: ret
= 1256; break;
1631 case wxFONTENCODING_CP1257
: ret
= 1257; break;
1633 case wxFONTENCODING_EUC_JP
: ret
= 20932; break;
1635 case wxFONTENCODING_MACROMAN
: ret
= 10000; break;
1636 case wxFONTENCODING_MACJAPANESE
: ret
= 10001; break;
1637 case wxFONTENCODING_MACCHINESETRAD
: ret
= 10002; break;
1638 case wxFONTENCODING_MACKOREAN
: ret
= 10003; break;
1639 case wxFONTENCODING_MACARABIC
: ret
= 10004; break;
1640 case wxFONTENCODING_MACHEBREW
: ret
= 10005; break;
1641 case wxFONTENCODING_MACGREEK
: ret
= 10006; break;
1642 case wxFONTENCODING_MACCYRILLIC
: ret
= 10007; break;
1643 case wxFONTENCODING_MACTHAI
: ret
= 10021; break;
1644 case wxFONTENCODING_MACCHINESESIMP
: ret
= 10008; break;
1645 case wxFONTENCODING_MACCENTRALEUR
: ret
= 10029; break;
1646 case wxFONTENCODING_MACCROATIAN
: ret
= 10082; break;
1647 case wxFONTENCODING_MACICELANDIC
: ret
= 10079; break;
1648 case wxFONTENCODING_MACROMANIAN
: ret
= 10009; break;
1650 case wxFONTENCODING_ISO2022_JP
: ret
= 50222; break;
1652 case wxFONTENCODING_UTF7
: ret
= 65000; break;
1653 case wxFONTENCODING_UTF8
: ret
= 65001; break;
1658 if (::IsValidCodePage(ret
) == 0)
1662 if (::GetCPInfo(ret
, &info
) == 0)
1668 extern long wxCharsetToCodepage(const char *name
)
1670 // first get the font encoding for this charset
1674 wxFontEncoding enc
= wxFontMapperBase::Get()->CharsetToEncoding(name
, false);
1675 if ( enc
== wxFONTENCODING_SYSTEM
)
1678 // the use the helper function
1679 return wxEncodingToCodepage(enc
);
1682 #else // !wxUSE_FONTMAP
1684 #include "wx/msw/registry.h"
1686 // this should work if Internet Exploiter is installed
1687 extern long wxCharsetToCodepage(const char *name
)
1695 wxString
path(wxT("MIME\\Database\\Charset\\"));
1698 // follow the alias loop
1701 wxRegKey
key(wxRegKey::HKCR
, path
+ cn
);
1706 // two cases: either there's an AliasForCharset string,
1707 // or there are Codepage and InternetEncoding dwords.
1708 // The InternetEncoding gives us the actual encoding,
1709 // the Codepage just says which Windows character set to
1710 // use when displaying the data.
1711 if (key
.HasValue(wxT("InternetEncoding")) &&
1712 key
.QueryValue(wxT("InternetEncoding"), &CP
))
1715 // no encoding, see if it's an alias
1716 if (!key
.HasValue(wxT("AliasForCharset")) ||
1717 !key
.QueryValue(wxT("AliasForCharset"), cn
))
1720 #endif // wxUSE_REGKEY
1725 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
1728 Creates a hidden window with supplied window proc registering the class for
1729 it if necesssary (i.e. the first time only). Caller is responsible for
1730 destroying the window and unregistering the class (note that this must be
1731 done because wxWidgets may be used as a DLL and so may be loaded/unloaded
1732 multiple times into/from the same process so we cna't rely on automatic
1733 Windows class unregistration).
1735 pclassname is a pointer to a caller stored classname, which must initially be
1736 NULL. classname is the desired wndclass classname. If function successfully
1737 registers the class, pclassname will be set to classname.
1739 extern "C" WXDLLIMPEXP_BASE HWND
1740 wxCreateHiddenWindow(LPCTSTR
*pclassname
, LPCTSTR classname
, WNDPROC wndproc
)
1742 wxCHECK_MSG( classname
&& pclassname
&& wndproc
, NULL
,
1743 wxT("NULL parameter in wxCreateHiddenWindow") );
1745 // register the class fi we need to first
1746 if ( *pclassname
== NULL
)
1749 wxZeroMemory(wndclass
);
1751 wndclass
.lpfnWndProc
= wndproc
;
1752 wndclass
.hInstance
= wxGetInstance();
1753 wndclass
.lpszClassName
= classname
;
1755 if ( !::RegisterClass(&wndclass
) )
1757 wxLogLastError(wxT("RegisterClass() in wxCreateHiddenWindow"));
1762 *pclassname
= classname
;
1765 // next create the window
1766 HWND hwnd
= ::CreateWindow
1780 wxLogLastError(wxT("CreateWindow() in wxCreateHiddenWindow"));