X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/999836aacade840a5d9a0cbb5fad7b1d4de62c93..09cbc94feafe9c5a424eb1d462589f9620a1977e:/src/msw/utils.cpp diff --git a/src/msw/utils.cpp b/src/msw/utils.cpp index 89c2b89a0b..901aa039ed 100644 --- a/src/msw/utils.cpp +++ b/src/msw/utils.cpp @@ -34,6 +34,8 @@ #include "wx/apptrait.h" #include "wx/dynload.h" +#include "wx/confbase.h" // for wxExpandEnvVars() + #include "wx/msw/private.h" // includes #include "wx/msw/missing.h" // CHARSET_HANGUL @@ -92,6 +94,9 @@ #endif #endif +// For wxKillAllChildren +#include + // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- @@ -100,12 +105,6 @@ static const wxChar WX_SECTION[] = wxT("wxWindows"); static const wxChar eUSERNAME[] = wxT("UserName"); -// these are only used under Win16 -#if !defined(__WIN32__) && !defined(__WXMICROWIN__) -static const wxChar eHOSTNAME[] = wxT("HostName"); -static const wxChar eUSERID[] = wxT("UserId"); -#endif // !Win32 - // ============================================================================ // implementation // ============================================================================ @@ -118,17 +117,17 @@ static const wxChar eUSERID[] = wxT("UserId"); bool wxGetHostName(wxChar *buf, int maxSize) { #if defined(__WXWINCE__) - return FALSE; + return false; #elif defined(__WIN32__) && !defined(__WXMICROWIN__) DWORD nSize = maxSize; if ( !::GetComputerName(buf, &nSize) ) { wxLogLastError(wxT("GetComputerName")); - return FALSE; + return false; } - return TRUE; + return true; #else wxChar *sysname; const wxChar *default_host = wxT("noname"); @@ -138,7 +137,7 @@ bool wxGetHostName(wxChar *buf, int maxSize) } else wxStrncpy(buf, sysname, maxSize - 1); buf[maxSize] = wxT('\0'); - return *buf ? TRUE : FALSE; + return *buf ? true : false; #endif } @@ -149,7 +148,10 @@ bool wxGetFullHostName(wxChar *buf, int maxSize) // TODO should use GetComputerNameEx() when available // we don't want to always link with Winsock DLL as we might not use it at - // all, so load it dynamically here if needed + // all, so load it dynamically here if needed (and don't complain if it is + // missing, we handle this) + wxLogNull noLog; + wxDynamicLibrary dllWinsock(_T("ws2_32.dll"), wxDL_VERBATIM); if ( dllWinsock.IsLoaded() ) { @@ -214,7 +216,7 @@ bool wxGetFullHostName(wxChar *buf, int maxSize) { wxStrncpy(buf, host, maxSize); - return TRUE; + return true; } } } @@ -227,8 +229,8 @@ bool wxGetFullHostName(wxChar *buf, int maxSize) bool wxGetUserId(wxChar *buf, int maxSize) { #if defined(__WXWINCE__) - return FALSE; -#elif defined(__WIN32__) && !defined(__win32s__) && !defined(__WXMICROWIN__) + return false; +#elif defined(__WIN32__) && !defined(__WXMICROWIN__) DWORD nSize = maxSize; if ( ::GetUserName(buf, &nSize) == 0 ) { @@ -237,12 +239,12 @@ bool wxGetUserId(wxChar *buf, int maxSize) if ( res == 0 ) { // not found - return FALSE; + return false; } } - return TRUE; -#else // Win16 or Win32s + return true; +#else // __WXMICROWIN__ wxChar *user; const wxChar *default_id = wxT("anonymous"); @@ -251,7 +253,7 @@ bool wxGetUserId(wxChar *buf, int maxSize) if ( (user = wxGetenv(wxT("USER"))) == NULL && (user = wxGetenv(wxT("LOGNAME"))) == NULL ) { - // Use wxWindows configuration data (comming soon) + // Use wxWidgets configuration data (comming soon) GetProfileString(WX_SECTION, eUSERID, default_id, buf, maxSize - 1); } else @@ -259,7 +261,7 @@ bool wxGetUserId(wxChar *buf, int maxSize) wxStrncpy(buf, user, maxSize - 1); } - return *buf ? TRUE : FALSE; + return *buf ? true : false; #endif } @@ -267,11 +269,11 @@ bool wxGetUserId(wxChar *buf, int maxSize) bool wxGetUserName(wxChar *buf, int maxSize) { #if defined(__WXWINCE__) - return FALSE; + return false; #elif defined(USE_NET_API) CHAR szUserName[256]; if ( !wxGetUserId(szUserName, WXSIZEOF(szUserName)) ) - return FALSE; + return false; // TODO how to get the domain name? CHAR *szDomain = ""; @@ -328,15 +330,15 @@ bool wxGetUserName(wxChar *buf, int maxSize) WideCharToMultiByte( CP_ACP, 0, ui2->usri2_full_name, -1, buf, maxSize, NULL, NULL ); - return TRUE; + return true; error: wxLogError(wxT("Couldn't look up full user name.")); - return FALSE; + return false; #else // !USE_NET_API // Could use NIS, MS-Mail or other site specific programs - // Use wxWindows configuration data + // Use wxWidgets configuration data bool ok = GetProfileString(WX_SECTION, eUSERNAME, wxEmptyString, buf, maxSize - 1) != 0; if ( !ok ) { @@ -349,13 +351,14 @@ error: } #endif // Win32/16 - return TRUE; + return true; } const wxChar* wxGetHomeDir(wxString *pstr) { - wxString& strDir = *pstr; + wxString& strDir = *pstr; + // first branch is for Cygwin #if defined(__UNIX__) const wxChar *szHome = wxGetenv("HOME"); if ( szHome == NULL ) { @@ -371,34 +374,33 @@ const wxChar* wxGetHomeDir(wxString *pstr) strDir << wxT('/'); #ifdef __CYGWIN__ - // Cygwin returns unix type path but that does not work well - static wxChar windowsPath[MAX_PATH]; - cygwin_conv_to_full_win32_path(strDir, windowsPath); - strDir = windowsPath; + // Cygwin returns unix type path but that does not work well + static wxChar windowsPath[MAX_PATH]; + cygwin_conv_to_full_win32_path(strDir, windowsPath); + strDir = windowsPath; #endif #elif defined(__WXWINCE__) // Nothing #else - #ifdef __WIN32__ - strDir.clear(); + strDir.clear(); - // If we have a valid HOME directory, as is used on many machines that - // have unix utilities on them, we should use that. - const wxChar *szHome = wxGetenv(wxT("HOME")); + // If we have a valid HOME directory, as is used on many machines that + // have unix utilities on them, we should use that. + const wxChar *szHome = wxGetenv(wxT("HOME")); - if ( szHome != NULL ) - { + if ( szHome != NULL ) + { strDir = szHome; - } - else // no HOME, try HOMEDRIVE/PATH - { - szHome = wxGetenv(wxT("HOMEDRIVE")); - if ( szHome != NULL ) + } + else // no HOME, try HOMEDRIVE/PATH + { + szHome = wxGetenv(wxT("HOMEDRIVE")); + if ( szHome != NULL ) strDir << szHome; - szHome = wxGetenv(wxT("HOMEPATH")); + szHome = wxGetenv(wxT("HOMEPATH")); - if ( szHome != NULL ) - { + if ( szHome != NULL ) + { strDir << szHome; // the idea is that under NT these variables have default values @@ -408,44 +410,34 @@ const wxChar* wxGetHomeDir(wxString *pstr) // to set HOMEPATH to something other than "\\", we suppose that he // knows what he is doing and use the supplied value. if ( wxStrcmp(szHome, wxT("\\")) == 0 ) - strDir.clear(); - } - } + strDir.clear(); + } + } - if ( strDir.empty() ) - { - // If we have a valid USERPROFILE directory, as is the case in - // Windows NT, 2000 and XP, we should use that as our home directory. - szHome = wxGetenv(wxT("USERPROFILE")); + if ( strDir.empty() ) + { + // If we have a valid USERPROFILE directory, as is the case in + // Windows NT, 2000 and XP, we should use that as our home directory. + szHome = wxGetenv(wxT("USERPROFILE")); - if ( szHome != NULL ) + if ( szHome != NULL ) strDir = szHome; - } - - if ( !strDir.empty() ) - { - return strDir.c_str(); - } - //else: fall back to the prograrm directory - #else // Win16 - // Win16 has no idea about home, so use the executable directory instead - #endif // WIN16/32 - - // 260 was taken from windef.h - #ifndef MAX_PATH - #define MAX_PATH 260 - #endif - - wxString strPath; - ::GetModuleFileName(::GetModuleHandle(NULL), - wxStringBuffer(strPath, MAX_PATH), MAX_PATH); - - // extract the dir name - wxSplitPath(strPath, &strDir, NULL, NULL); + } + if ( !strDir.empty() ) + { + // sometimes the value of HOME may be "%USERPROFILE%", so reexpand the + // value once again, it shouldn't hurt anyhow + strDir = wxExpandEnvVars(strDir); + } + else // fall back to the program directory + { + // extract the directory component of the program file name + wxSplitPath(wxGetFullModuleName(), &strDir, NULL, NULL); + } #endif // UNIX/Win - return strDir.c_str(); + return strDir.c_str(); } wxChar *wxGetUserHome(const wxString& WXUNUSED(user)) @@ -465,32 +457,16 @@ bool wxDirExists(const wxString& dir) #elif defined(__WIN32__) DWORD attribs = GetFileAttributes(dir); return ((attribs != (DWORD)-1) && (attribs & FILE_ATTRIBUTE_DIRECTORY)); -#else // Win16 - #ifdef __BORLANDC__ - struct ffblk fileInfo; - #else - struct find_t fileInfo; - #endif - // In Borland findfirst has a different argument - // ordering from _dos_findfirst. But _dos_findfirst - // _should_ be ok in both MS and Borland... why not? - #ifdef __BORLANDC__ - return (findfirst(dir, &fileInfo, _A_SUBDIR) == 0 && - (fileInfo.ff_attrib & _A_SUBDIR) != 0); - #else - return (_dos_findfirst(dir, _A_SUBDIR, &fileInfo) == 0) && - ((fileInfo.attrib & _A_SUBDIR) != 0); - #endif -#endif // Win32/16 +#endif // Win32/__WXMICROWIN__ } bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) { #ifdef __WXWINCE__ - return FALSE; + return false; #else if ( path.empty() ) - return FALSE; + return false; // old w32api don't have ULARGE_INTEGER #if defined(__WIN32__) && \ @@ -525,7 +501,7 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) { wxLogLastError(_T("GetDiskFreeSpaceEx")); - return FALSE; + return false; } // ULARGE_INTEGER is a union of a 64 bit value and a struct containing @@ -568,7 +544,7 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) { wxLogLastError(_T("GetDiskFreeSpace")); - return FALSE; + return false; } wxLongLong lBytesPerCluster = lSectorsPerCluster; @@ -587,7 +563,7 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) } } - return TRUE; + return true; #endif // __WXWINCE__ } @@ -599,25 +575,14 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) bool wxGetEnv(const wxString& var, wxString *value) { #ifdef __WXWINCE__ - return FALSE; -#elif defined(__WIN16__) - const wxChar* ret = wxGetenv(var); - if ( !ret ) - return FALSE; - - if ( value ) - { - *value = ret; - } - - return TRUE; + return false; #else // Win32 // first get the size of the buffer DWORD dwRet = ::GetEnvironmentVariable(var, NULL, 0); if ( !dwRet ) { // this means that there is no such variable - return FALSE; + return false; } if ( value ) @@ -626,8 +591,8 @@ bool wxGetEnv(const wxString& var, wxString *value) dwRet); } - return TRUE; -#endif // Win16/32 + return true; +#endif // WinCE/32 } bool wxSetEnv(const wxString& var, const wxChar *value) @@ -639,12 +604,12 @@ bool wxSetEnv(const wxString& var, const wxChar *value) { wxLogLastError(_T("SetEnvironmentVariable")); - return FALSE; + return false; } - return TRUE; + return true; #else // no way to set env vars - return FALSE; + return false; #endif } @@ -687,8 +652,13 @@ BOOL CALLBACK wxEnumFindByPidProc(HWND hwnd, LPARAM lParam) return TRUE; } -int wxKill(long pid, wxSignal sig, wxKillError *krc) +int wxKillAllChildren(long pid, wxSignal sig, wxKillError *krc); + +int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags) { + if (flags & wxKILL_CHILDREN) + wxKillAllChildren(pid, sig, krc); + // get the process handle to operate on HANDLE hProcess = ::OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE | @@ -712,7 +682,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc) return -1; } - bool ok = TRUE; + bool ok = true; switch ( sig ) { case wxSIGKILL: @@ -728,7 +698,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc) *krc = wxKILL_ERROR; } - ok = FALSE; + ok = false; } break; @@ -765,7 +735,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc) { wxLogLastError(_T("EnumWindows")); - ok = FALSE; + ok = false; } } else // no windows for this PID @@ -775,7 +745,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc) *krc = wxKILL_ERROR; } - ok = FALSE; + ok = false; } } } @@ -843,17 +813,123 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc) return -1; } +HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD) ; +BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32) ; +BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32) ; + +static void InitToolHelp32() +{ + static bool s_initToolHelpDone = false; + + if (s_initToolHelpDone) + return; + + s_initToolHelpDone = true; + + lpfCreateToolhelp32Snapshot = NULL; + lpfProcess32First = NULL; + lpfProcess32Next = NULL; + + HINSTANCE hInstLib = LoadLibrary( wxT("Kernel32.DLL") ) ; + if( hInstLib == NULL ) + return ; + + // Get procedure addresses. + // We are linking to these functions of Kernel32 + // explicitly, because otherwise a module using + // this code would fail to load under Windows NT, + // which does not have the Toolhelp32 + // functions in the Kernel 32. + lpfCreateToolhelp32Snapshot= + (HANDLE(WINAPI *)(DWORD,DWORD)) + GetProcAddress( hInstLib, +#ifdef __WXWINCE__ + wxT("CreateToolhelp32Snapshot") +#else + "CreateToolhelp32Snapshot" +#endif + ) ; + + lpfProcess32First= + (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32)) + GetProcAddress( hInstLib, +#ifdef __WXWINCE__ + wxT("Process32First") +#else + "Process32First" +#endif + ) ; + + lpfProcess32Next= + (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32)) + GetProcAddress( hInstLib, +#ifdef __WXWINCE__ + wxT("Process32Next") +#else + "Process32Next" +#endif + ) ; + + FreeLibrary( hInstLib ) ; +} + +// By John Skiff +int wxKillAllChildren(long pid, wxSignal sig, wxKillError *krc) +{ + InitToolHelp32(); + + if (krc) + *krc = wxKILL_OK; + + // If not implemented for this platform (e.g. NT 4.0), silently ignore + if (!lpfCreateToolhelp32Snapshot || !lpfProcess32First || !lpfProcess32Next) + return 0; + + // Take a snapshot of all processes in the system. + HANDLE hProcessSnap = lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hProcessSnap == INVALID_HANDLE_VALUE) { + if (krc) + *krc = wxKILL_ERROR; + return -1; + } + + //Fill in the size of the structure before using it. + PROCESSENTRY32 pe = {0}; + pe.dwSize = sizeof(PROCESSENTRY32); + + // Walk the snapshot of the processes, and for each process, + // kill it if its parent is pid. + if (!lpfProcess32First(hProcessSnap, &pe)) { + // Can't get first process. + if (krc) + *krc = wxKILL_ERROR; + CloseHandle (hProcessSnap); + return -1; + } + + do { + if (pe.th32ParentProcessID == (DWORD) pid) { + if (wxKill(pe.th32ProcessID, sig, krc)) + return -1; + } + } while (lpfProcess32Next (hProcessSnap, &pe)); + + + return 0; +} + // Execute a program in an Interactive Shell bool wxShell(const wxString& command) { + wxString cmd; + #ifdef __WXWINCE__ - return FALSE; + cmd = command; #else wxChar *shell = wxGetenv(wxT("COMSPEC")); if ( !shell ) shell = (wxChar*) wxT("\\COMMAND.COM"); - wxString cmd; if ( !command ) { // just the shell @@ -864,18 +940,18 @@ bool wxShell(const wxString& command) // pass the command to execute to the command processor cmd.Printf(wxT("%s /c %s"), shell, command.c_str()); } +#endif return wxExecute(cmd, wxEXEC_SYNC) == 0; -#endif } // Shutdown or reboot the PC bool wxShutdown(wxShutdownFlags wFlags) { #ifdef __WXWINCE__ - return FALSE; + return false; #elif defined(__WIN32__) - bool bOK = TRUE; + bool bOK = true; if ( wxGetOsVersion(NULL, NULL) == wxWINDOWS_NT ) // if is NT or 2K { @@ -919,15 +995,13 @@ bool wxShutdown(wxShutdownFlags wFlags) default: wxFAIL_MSG( _T("unknown wxShutdown() flag") ); - return FALSE; + return false; } bOK = ::ExitWindowsEx(flags, 0) != 0; } return bOK; -#else // Win16 - return FALSE; #endif // Win32/16 } @@ -950,11 +1024,7 @@ long wxGetFreeMemory() unsigned long wxGetProcessId() { -#ifdef __WIN32__ return ::GetCurrentProcessId(); -#else - return 0; -#endif } // Emit a beeeeeep @@ -965,7 +1035,6 @@ void wxBell() wxString wxGetOsDescription() { -#ifdef __WIN32__ wxString str; OSVERSIONINFO info; @@ -981,8 +1050,39 @@ wxString wxGetOsDescription() break; case VER_PLATFORM_WIN32_WINDOWS: - str.Printf(_("Windows 9%c"), - info.dwMinorVersion == 0 ? _T('5') : _T('8')); + switch (info.dwMinorVersion) + { + case 0: + if ( info.szCSDVersion[1] == 'B' || + info.szCSDVersion[1] == 'C' ) + { + str = _("Windows 95 OSR2"); + } + else + { + str = _("Windows 95"); + } + break; + case 10: + if ( info.szCSDVersion[1] == 'B' || + info.szCSDVersion[1] == 'C' ) + { + str = _("Windows 98 SE"); + } + else + { + str = _("Windows 98"); + } + break; + case 90: + str = _("Windows ME"); + break; + default: + str.Printf(_("Windows 9x (%d.%d)"), + info.dwMajorVersion, + info.dwMinorVersion); + break; + } if ( !wxIsEmpty(info.szCSDVersion) ) { str << _T(" (") << info.szCSDVersion << _T(')'); @@ -990,10 +1090,31 @@ wxString wxGetOsDescription() break; case VER_PLATFORM_WIN32_NT: - str.Printf(_T("Windows NT %lu.%lu (build %lu"), + if ( info.dwMajorVersion == 5 ) + { + switch ( info.dwMinorVersion ) + { + case 0: + str.Printf(_("Windows 2000 (build %lu"), + info.dwBuildNumber); + break; + case 1: + str.Printf(_("Windows XP (build %lu"), + info.dwBuildNumber); + break; + case 2: + str.Printf(_("Windows Server 2003 (build %lu"), + info.dwBuildNumber); + break; + } + } + if ( wxIsEmpty(str) ) + { + str.Printf(_("Windows NT %lu.%lu (build %lu"), info.dwMajorVersion, info.dwMinorVersion, info.dwBuildNumber); + } if ( !wxIsEmpty(info.szCSDVersion) ) { str << _T(", ") << info.szCSDVersion; @@ -1008,9 +1129,6 @@ wxString wxGetOsDescription() } return str; -#else // Win16 - return _("Windows 3.1"); -#endif // Win32/16 } wxToolkitInfo& wxAppTraits::GetToolkitInfo() @@ -1069,14 +1187,19 @@ wxToolkitInfo& wxAppTraits::GetToolkitInfo() // sleep functions // ---------------------------------------------------------------------------- -void wxUsleep(unsigned long milliseconds) +void wxMilliSleep(unsigned long milliseconds) { ::Sleep(milliseconds); } +void wxMicroSleep(unsigned long microseconds) +{ + wxMilliSleep(microseconds/1000); +} + void wxSleep(int nSecs) { - wxUsleep(1000*nSecs); + wxMilliSleep(1000*nSecs); } // ---------------------------------------------------------------------------- @@ -1181,7 +1304,7 @@ extern long wxCharsetToCodepage(const wxChar *name) if ( !name ) return -1; - wxFontEncoding enc = wxFontMapper::Get()->CharsetToEncoding(name, FALSE); + wxFontEncoding enc = wxFontMapper::Get()->CharsetToEncoding(name, false); if ( enc == wxFONTENCODING_SYSTEM ) return -1; @@ -1236,7 +1359,7 @@ extern long wxCharsetToCodepage(const wxChar *name) Creates a hidden window with supplied window proc registering the class for it if necesssary (i.e. the first time only). Caller is responsible for destroying the window and unregistering the class (note that this must be - done because wxWindows may be used as a DLL and so may be loaded/unloaded + done because wxWidgets may be used as a DLL and so may be loaded/unloaded multiple times into/from the same process so we cna't rely on automatic Windows class unregistration).