X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/32cdc45397d8c0a24735f84e1dcf83bba1980f2d..07aaf32633ecf18ec3edfbb41793a112914792d0:/src/msw/utils.cpp diff --git a/src/msw/utils.cpp b/src/msw/utils.cpp index 8ad2280a50..afd0bb2e6c 100644 --- a/src/msw/utils.cpp +++ b/src/msw/utils.cpp @@ -41,6 +41,7 @@ #include "wx/confbase.h" // for wxExpandEnvVars() #include "wx/msw/private.h" // includes +#include "wx/msw/private/hiddenwin.h" #include "wx/msw/missing.h" // for CHARSET_HANGUL #if defined(__CYGWIN__) @@ -59,15 +60,15 @@ #if !defined(__GNUWIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__) #include - #ifndef __MWERKS__ - #include - #endif + #include #endif //GNUWIN32 #if defined(__CYGWIN__) #include #include - #include // for cygwin_conv_to_full_win32_path() + #include // for cygwin_conv_path() + // and cygwin_conv_to_full_win32_path() + #include #endif //GNUWIN32 #ifdef __BORLANDC__ // Please someone tell me which version of Borland needs @@ -118,6 +119,8 @@ static const wxChar WX_SECTION[] = wxT("wxWindows"); static const wxChar eUSERNAME[] = wxT("UserName"); #endif +WXDLLIMPEXP_DATA_BASE(const wxChar *) wxUserResourceStr = wxT("TEXT"); + // ============================================================================ // implementation // ============================================================================ @@ -138,7 +141,7 @@ bool wxGetHostName(wxChar *buf, int maxSize) !regKey.QueryValue(wxT("Name"), hostName) ) return false; - wxStrlcpy(buf, hostName.wx_str(), maxSize); + wxStrlcpy(buf, hostName.t_str(), maxSize); #else // !__WXWINCE__ DWORD nSize = maxSize; if ( !::GetComputerName(buf, &nSize) ) @@ -163,7 +166,7 @@ bool wxGetFullHostName(wxChar *buf, int maxSize) // missing, we handle this) wxLogNull noLog; - wxDynamicLibrary dllWinsock(_T("ws2_32.dll"), wxDL_VERBATIM); + wxDynamicLibrary dllWinsock(wxT("ws2_32.dll"), wxDL_VERBATIM); if ( dllWinsock.IsLoaded() ) { typedef int (PASCAL *WSAStartup_t)(WORD, WSADATA *); @@ -174,7 +177,7 @@ bool wxGetFullHostName(wxChar *buf, int maxSize) #define LOAD_WINSOCK_FUNC(func) \ func ## _t \ - pfn ## func = (func ## _t)dllWinsock.GetSymbol(_T(#func)) + pfn ## func = (func ## _t)dllWinsock.GetSymbol(wxT(#func)) LOAD_WINSOCK_FUNC(WSAStartup); @@ -264,7 +267,7 @@ bool wxGetUserId(wxChar *WXUNUSED_IN_WINCE(buf), bool wxGetUserName(wxChar *buf, int maxSize) { wxCHECK_MSG( buf && ( maxSize > 0 ), false, - _T("empty buffer in wxGetUserName") ); + wxT("empty buffer in wxGetUserName") ); #if defined(__WXWINCE__) && wxUSE_REGKEY wxLogNull noLog; wxRegKey key(wxRegKey::HKCU, wxT("ControlPanel\\Owner")); @@ -299,7 +302,7 @@ bool wxGetUserName(wxChar *buf, int maxSize) // Get the computer name of a DC for the domain. if ( NetGetDCName( NULL, wszDomain, &ComputerName ) != NERR_Success ) { - wxLogError(wxT("Can not find domain controller")); + wxLogError(wxT("Cannot find domain controller")); goto error; } @@ -365,7 +368,7 @@ const wxChar* wxGetHomeDir(wxString *pstr) // first branch is for Cygwin #if defined(__UNIX__) && !defined(__WINE__) - const wxChar *szHome = wxGetenv("HOME"); + const wxChar *szHome = wxGetenv(wxT("HOME")); if ( szHome == NULL ) { // we're homeless... wxLogWarning(_("can't find user's HOME, using current directory.")); @@ -381,7 +384,11 @@ const wxChar* wxGetHomeDir(wxString *pstr) #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); + #if CYGWIN_VERSION_DLL_MAJOR >= 1007 + cygwin_conv_path(CCP_POSIX_TO_WIN_W, strDir, windowsPath, MAX_PATH); + #else + cygwin_conv_to_full_win32_path(strDir, windowsPath); + #endif strDir = windowsPath; #endif #elif defined(__WXWINCE__) @@ -479,7 +486,7 @@ bool wxGetDiskSpace(const wxString& WXUNUSED_IN_WINCE(path), GetDiskFreeSpaceEx_t pGetDiskFreeSpaceEx = (GetDiskFreeSpaceEx_t)::GetProcAddress ( - ::GetModuleHandle(_T("kernel32.dll")), + ::GetModuleHandle(wxT("kernel32.dll")), #if wxUSE_UNICODE "GetDiskFreeSpaceExW" #else @@ -492,12 +499,12 @@ bool wxGetDiskSpace(const wxString& WXUNUSED_IN_WINCE(path), ULARGE_INTEGER bytesFree, bytesTotal; // may pass the path as is, GetDiskFreeSpaceEx() is smart enough - if ( !pGetDiskFreeSpaceEx(path.fn_str(), + if ( !pGetDiskFreeSpaceEx(path.t_str(), &bytesFree, &bytesTotal, NULL) ) { - wxLogLastError(_T("GetDiskFreeSpaceEx")); + wxLogLastError(wxT("GetDiskFreeSpaceEx")); return false; } @@ -542,13 +549,13 @@ bool wxGetDiskSpace(const wxString& WXUNUSED_IN_WINCE(path), // FIXME: this is wrong, we should extract the root drive from path // instead, but this is the job for wxFileName... - if ( !::GetDiskFreeSpace(path.fn_str(), + if ( !::GetDiskFreeSpace(path.t_str(), &lSectorsPerCluster, &lBytesPerSector, &lNumberOfFreeClusters, &lTotalNumberOfClusters) ) { - wxLogLastError(_T("GetDiskFreeSpace")); + wxLogLastError(wxT("GetDiskFreeSpace")); return false; } @@ -619,7 +626,7 @@ bool wxDoSetEnv(const wxString& var, const wxChar *value) // // TODO: add checks for the other compilers (and update wxSetEnv() // documentation in interface/wx/utils.h accordingly) -#if defined(__VISUALC__) +#if defined(__VISUALC__) || defined(__MINGW32__) // notice that Microsoft _putenv() has different semantics from POSIX // function with almost the same name: in particular it makes a copy of the // string instead of using it as part of environment so we can safely call @@ -629,11 +636,12 @@ bool wxDoSetEnv(const wxString& var, const wxChar *value) envstr += '='; if ( value ) envstr += value; - _tputenv(envstr.t_str()); + if ( _tputenv(envstr.t_str()) != 0 ) + return false; #else // other compiler if ( !::SetEnvironmentVariable(var.t_str(), value) ) { - wxLogLastError(_T("SetEnvironmentVariable")); + wxLogLastError(wxT("SetEnvironmentVariable")); return false; } @@ -700,11 +708,11 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags) wxKillAllChildren(pid, sig, krc); // get the process handle to operate on - HANDLE hProcess = ::OpenProcess(SYNCHRONIZE | - PROCESS_TERMINATE | - PROCESS_QUERY_INFORMATION, - FALSE, // not inheritable - (DWORD)pid); + DWORD dwAccess = PROCESS_QUERY_INFORMATION | SYNCHRONIZE; + if ( sig == wxSIGKILL ) + dwAccess |= PROCESS_TERMINATE; + + HANDLE hProcess = ::OpenProcess(dwAccess, FALSE, (DWORD)pid); if ( hProcess == NULL ) { if ( krc ) @@ -722,6 +730,12 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags) wxON_BLOCK_EXIT1(::CloseHandle, hProcess); + // Default timeout for waiting for the process termination after killing + // it. It should be long enough to allow the process to terminate even on a + // busy system but short enough to avoid blocking the main thread for too + // long. + DWORD waitTimeout = 500; // ms + bool ok = true; switch ( sig ) { @@ -743,10 +757,14 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags) break; case wxSIGNONE: - // do nothing, we just want to test for process existence - if ( krc ) - *krc = wxKILL_OK; - return 0; + // Opening the process handle may succeed for a process even if it + // doesn't run any more (typically because open handles to it still + // exist elsewhere, possibly in this process itself if we're + // killing a child process) so we still need check if it hasn't + // terminated yet but, unlike when killing it, we don't need to + // wait for any time at all. + waitTimeout = 0; + break; default: // any other signal means "terminate" @@ -770,12 +788,12 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags) // can also use SendMesageTimeout(WM_CLOSE) if ( !::PostMessage(params.hwnd, WM_QUIT, 0, 0) ) { - wxLogLastError(_T("PostMessage(WM_QUIT)")); + wxLogLastError(wxT("PostMessage(WM_QUIT)")); } } else // it was an error then { - wxLogLastError(_T("EnumWindows")); + wxLogLastError(wxT("EnumWindows")); ok = false; } @@ -791,34 +809,43 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags) } // the return code - DWORD rc wxDUMMY_INITIALIZE(0); if ( ok ) { // as we wait for a short time, we can use just WaitForSingleObject() // and not MsgWaitForMultipleObjects() - switch ( ::WaitForSingleObject(hProcess, 500 /* msec */) ) + switch ( ::WaitForSingleObject(hProcess, waitTimeout) ) { case WAIT_OBJECT_0: - // process terminated - if ( !::GetExitCodeProcess(hProcess, &rc) ) + // Process terminated: normally this indicates that we + // successfully killed it but when testing for the process + // existence, this means failure. + if ( sig == wxSIGNONE ) { - wxLogLastError(_T("GetExitCodeProcess")); + if ( krc ) + *krc = wxKILL_NO_PROCESS; + + ok = false; } break; default: - wxFAIL_MSG( _T("unexpected WaitForSingleObject() return") ); + wxFAIL_MSG( wxT("unexpected WaitForSingleObject() return") ); // fall through case WAIT_FAILED: - wxLogLastError(_T("WaitForSingleObject")); + wxLogLastError(wxT("WaitForSingleObject")); // fall through case WAIT_TIMEOUT: - if ( krc ) - *krc = wxKILL_ERROR; + // Process didn't terminate: normally this is a failure but not + // when we're just testing for its existence. + if ( sig != wxSIGNONE ) + { + if ( krc ) + *krc = wxKILL_ERROR; - rc = STILL_ACTIVE; + ok = false; + } break; } } @@ -826,7 +853,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags) // the return code is the same as from Unix kill(): 0 if killed // successfully or -1 on error - if ( !ok || rc == STILL_ACTIVE ) + if ( !ok ) return -1; if ( krc ) @@ -856,7 +883,7 @@ static void InitToolHelp32() #if wxUSE_DYNLIB_CLASS - wxDynamicLibrary dllKernel(_T("kernel32.dll"), wxDL_VERBATIM); + wxDynamicLibrary dllKernel(wxT("kernel32.dll"), wxDL_VERBATIM); // Get procedure addresses. // We are linking to these functions of Kernel32 @@ -865,13 +892,13 @@ static void InitToolHelp32() // which does not have the Toolhelp32 // functions in the Kernel 32. lpfCreateToolhelp32Snapshot = - (CreateToolhelp32Snapshot_t)dllKernel.RawGetSymbol(_T("CreateToolhelp32Snapshot")); + (CreateToolhelp32Snapshot_t)dllKernel.RawGetSymbol(wxT("CreateToolhelp32Snapshot")); lpfProcess32First = - (Process32_t)dllKernel.RawGetSymbol(_T("Process32First")); + (Process32_t)dllKernel.RawGetSymbol(wxT("Process32First")); lpfProcess32Next = - (Process32_t)dllKernel.RawGetSymbol(_T("Process32Next")); + (Process32_t)dllKernel.RawGetSymbol(wxT("Process32Next")); #endif // wxUSE_DYNLIB_CLASS } @@ -1014,7 +1041,7 @@ bool wxShutdown(int WXUNUSED_IN_WINCE(flags)) break; default: - wxFAIL_MSG( _T("unknown wxShutdown() flag") ); + wxFAIL_MSG( wxT("unknown wxShutdown() flag") ); return false; } @@ -1050,31 +1077,88 @@ unsigned long wxGetProcessId() return ::GetCurrentProcessId(); } -// Emit a beeeeeep -void wxBell() -{ - ::MessageBeep((UINT)-1); // default sound -} - bool wxIsDebuggerRunning() { #if wxUSE_DYNLIB_CLASS // IsDebuggerPresent() is not available under Win95, so load it dynamically - wxDynamicLibrary dll(_T("kernel32.dll"), wxDL_VERBATIM); + wxDynamicLibrary dll(wxT("kernel32.dll"), wxDL_VERBATIM); typedef BOOL (WINAPI *IsDebuggerPresent_t)(); - if ( !dll.HasSymbol(_T("IsDebuggerPresent")) ) + if ( !dll.HasSymbol(wxT("IsDebuggerPresent")) ) { // no way to know, assume no return false; } - return (*(IsDebuggerPresent_t)dll.GetSymbol(_T("IsDebuggerPresent")))() != 0; + return (*(IsDebuggerPresent_t)dll.GetSymbol(wxT("IsDebuggerPresent")))() != 0; #else return false; #endif } +// ---------------------------------------------------------------------------- +// working with MSW resources +// ---------------------------------------------------------------------------- + +bool +wxLoadUserResource(const void **outData, + size_t *outLen, + const wxString& resourceName, + const wxChar* resourceType, + WXHINSTANCE instance) +{ + wxCHECK_MSG( outData && outLen, false, "output pointers can't be NULL" ); + + HRSRC hResource = ::FindResource(instance, + resourceName.t_str(), + resourceType); + if ( !hResource ) + return false; + + HGLOBAL hData = ::LoadResource(instance, hResource); + if ( !hData ) + { + wxLogSysError(_("Failed to load resource \"%s\"."), resourceName); + return false; + } + + *outData = ::LockResource(hData); + if ( !*outData ) + { + wxLogSysError(_("Failed to lock resource \"%s\"."), resourceName); + return false; + } + + *outLen = ::SizeofResource(instance, hResource); + + // Notice that we do not need to call neither UnlockResource() (which is + // obsolete in Win32) nor GlobalFree() (resources are freed on process + // termination only) + + return true; +} + +char * +wxLoadUserResource(const wxString& resourceName, + const wxChar* resourceType, + int* pLen, + WXHINSTANCE instance) +{ + const void *data; + size_t len; + if ( !wxLoadUserResource(&data, &len, resourceName, resourceType, instance) ) + return NULL; + + char *s = new char[len + 1]; + memcpy(s, data, len); + s[len] = '\0'; // NUL-terminate in case the resource itself wasn't + + if (pLen) + *pLen = len; + + return s; +} + // ---------------------------------------------------------------------------- // OS version // ---------------------------------------------------------------------------- @@ -1173,7 +1257,7 @@ wxString wxGetOsDescription() } if ( !wxIsEmpty(info.szCSDVersion) ) { - str << _T(" (") << info.szCSDVersion << _T(')'); + str << wxT(" (") << info.szCSDVersion << wxT(')'); } break; @@ -1184,8 +1268,7 @@ wxString wxGetOsDescription() switch ( info.dwMinorVersion ) { case 0: - str.Printf(_("Windows 2000 (build %lu"), - info.dwBuildNumber); + str = _("Windows 2000"); break; case 2: @@ -1194,41 +1277,49 @@ wxString wxGetOsDescription() // type to resolve this ambiguity if ( wxIsWindowsServer() == 1 ) { - str.Printf(_("Windows Server 2003 (build %lu"), - info.dwBuildNumber); + str = _("Windows Server 2003"); break; } //else: must be XP, fall through case 1: - str.Printf(_("Windows XP (build %lu"), - info.dwBuildNumber); + str = _("Windows XP"); break; } break; case 6: - if ( info.dwMinorVersion == 0 ) + switch ( info.dwMinorVersion ) { - str.Printf(_("Windows Vista (build %lu"), - info.dwBuildNumber); + case 0: + str = wxIsWindowsServer() == 1 + ? _("Windows Server 2008") + : _("Windows Vista"); + break; + + case 1: + str = wxIsWindowsServer() == 1 + ? _("Windows Server 2008 R2") + : _("Windows 7"); + break; } break; } if ( str.empty() ) { - str.Printf(_("Windows NT %lu.%lu (build %lu"), - info.dwMajorVersion, - info.dwMinorVersion, - info.dwBuildNumber); + str.Printf(_("Windows NT %lu.%lu"), + info.dwMajorVersion, + info.dwMinorVersion); } + str << wxT(" (") + << wxString::Format(_("build %lu"), info.dwBuildNumber); if ( !wxIsEmpty(info.szCSDVersion) ) { - str << _T(", ") << info.szCSDVersion; + str << wxT(", ") << info.szCSDVersion; } - str << _T(')'); + str << wxT(')'); if ( wxIsPlatform64Bit() ) str << _(", 64-bit edition"); @@ -1237,7 +1328,7 @@ wxString wxGetOsDescription() } else { - wxFAIL_MSG( _T("GetVersionEx() failed") ); // should never happen + wxFAIL_MSG( wxT("GetVersionEx() failed") ); // should never happen } return str; @@ -1251,9 +1342,9 @@ bool wxIsPlatform64Bit() // 32-bit programs run on both 32-bit and 64-bit Windows so check typedef BOOL (WINAPI *IsWow64Process_t)(HANDLE, BOOL *); - wxDynamicLibrary dllKernel32(_T("kernel32.dll")); + wxDynamicLibrary dllKernel32(wxT("kernel32.dll")); IsWow64Process_t pfnIsWow64Process = - (IsWow64Process_t)dllKernel32.RawGetSymbol(_T("IsWow64Process")); + (IsWow64Process_t)dllKernel32.RawGetSymbol(wxT("IsWow64Process")); BOOL wow64 = FALSE; if ( pfnIsWow64Process ) @@ -1627,23 +1718,11 @@ extern long wxCharsetToCodepage(const char *name) #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP -/* - 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 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). - - pclassname is a pointer to a caller stored classname, which must initially be - NULL. classname is the desired wndclass classname. If function successfully - registers the class, pclassname will be set to classname. - */ extern "C" WXDLLIMPEXP_BASE HWND wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc) { wxCHECK_MSG( classname && pclassname && wndproc, NULL, - _T("NULL parameter in wxCreateHiddenWindow") ); + wxT("NULL parameter in wxCreateHiddenWindow") ); // register the class fi we need to first if ( *pclassname == NULL )