X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a284cce85fc4c1136b82262bfaac3bdf97535433..9741fd45f734ea30e094f5b15f092b8394621204:/src/msw/utils.cpp diff --git a/src/msw/utils.cpp b/src/msw/utils.cpp index d86d45d0c5..e23656dfa9 100644 --- a/src/msw/utils.cpp +++ b/src/msw/utils.cpp @@ -36,6 +36,7 @@ #include "wx/dynlib.h" #include "wx/dynload.h" #include "wx/scopeguard.h" +#include "wx/filename.h" #include "wx/confbase.h" // for wxExpandEnvVars() @@ -66,7 +67,9 @@ #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 @@ -117,6 +120,8 @@ static const wxChar WX_SECTION[] = wxT("wxWindows"); static const wxChar eUSERNAME[] = wxT("UserName"); #endif +WXDLLIMPEXP_DATA_BASE(const wxChar *) wxUserResourceStr = wxT("TEXT"); + // ============================================================================ // implementation // ============================================================================ @@ -126,13 +131,19 @@ static const wxChar eUSERNAME[] = wxT("UserName"); // ---------------------------------------------------------------------------- // Get hostname only (without domain name) -bool wxGetHostName(wxChar *WXUNUSED_IN_WINCE(buf), - int WXUNUSED_IN_WINCE(maxSize)) +bool wxGetHostName(wxChar *buf, int maxSize) { #if defined(__WXWINCE__) - // TODO-CE - return false; -#elif defined(__WIN32__) && !defined(__WXMICROWIN__) + // GetComputerName() is not supported but the name seems to be stored in + // this location in the registry, at least for PPC2003 and WM5 + wxString hostName; + wxRegKey regKey(wxRegKey::HKLM, wxT("Ident")); + if ( !regKey.HasValue(wxT("Name")) || + !regKey.QueryValue(wxT("Name"), hostName) ) + return false; + + wxStrlcpy(buf, hostName.wx_str(), maxSize); +#else // !__WXWINCE__ DWORD nSize = maxSize; if ( !::GetComputerName(buf, &nSize) ) { @@ -140,19 +151,9 @@ bool wxGetHostName(wxChar *WXUNUSED_IN_WINCE(buf), return false; } +#endif // __WXWINCE__/!__WXWINCE__ return true; -#else - wxChar *sysname; - const wxChar *default_host = wxT("noname"); - - if ((sysname = wxGetenv(wxT("SYSTEM_NAME"))) == NULL) { - GetProfileString(WX_SECTION, eHOSTNAME, default_host, buf, maxSize - 1); - } else - wxStrncpy(buf, sysname, maxSize - 1); - buf[maxSize] = wxT('\0'); - return *buf ? true : false; -#endif } // get full hostname (with domain name if possible) @@ -166,7 +167,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 *); @@ -177,7 +178,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); @@ -228,7 +229,7 @@ bool wxGetFullHostName(wxChar *buf, int maxSize) if ( !host.empty() ) { - wxStrncpy(buf, host, maxSize); + wxStrlcpy(buf, host.c_str(), maxSize); return true; } @@ -246,7 +247,7 @@ bool wxGetUserId(wxChar *WXUNUSED_IN_WINCE(buf), #if defined(__WXWINCE__) // TODO-CE return false; -#elif defined(__WIN32__) && !defined(__WXMICROWIN__) +#else DWORD nSize = maxSize; if ( ::GetUserName(buf, &nSize) == 0 ) { @@ -260,24 +261,6 @@ bool wxGetUserId(wxChar *WXUNUSED_IN_WINCE(buf), } return true; -#else // __WXMICROWIN__ - wxChar *user; - const wxChar *default_id = wxT("anonymous"); - - // Can't assume we have NIS (PC-NFS) or some other ID daemon - // So we ... - if ( (user = wxGetenv(wxT("USER"))) == NULL && - (user = wxGetenv(wxT("LOGNAME"))) == NULL ) - { - // Use wxWidgets configuration data (comming soon) - GetProfileString(WX_SECTION, eUSERID, default_id, buf, maxSize - 1); - } - else - { - wxStrncpy(buf, user, maxSize - 1); - } - - return *buf ? true : false; #endif } @@ -285,7 +268,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")); @@ -294,8 +277,7 @@ bool wxGetUserName(wxChar *buf, int maxSize) wxString name; if(!key.QueryValue(wxT("Owner"),name)) return false; - wxStrncpy(buf, name.c_str(), maxSize-1); - buf[maxSize-1] = _T('\0'); + wxStrlcpy(buf, name.c_str(), maxSize); return true; #elif defined(USE_NET_API) CHAR szUserName[256]; @@ -374,7 +356,7 @@ error: if ( !ok ) { - wxStrncpy(buf, wxT("Unknown User"), maxSize); + wxStrlcpy(buf, wxT("Unknown User"), maxSize); } return true; @@ -387,7 +369,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.")); @@ -403,7 +385,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__) @@ -460,7 +446,7 @@ const wxChar* wxGetHomeDir(wxString *pstr) else // fall back to the program directory { // extract the directory component of the program file name - wxSplitPath(wxGetFullModuleName(), &strDir, NULL, NULL); + wxFileName::SplitPath(wxGetFullModuleName(), &strDir, NULL, NULL); } #endif // UNIX/Win @@ -501,7 +487,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 @@ -514,12 +500,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; } @@ -564,13 +550,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; } @@ -608,7 +594,7 @@ bool wxGetEnv(const wxString& WXUNUSED_IN_WINCE(var), return false; #else // Win32 // first get the size of the buffer - DWORD dwRet = ::GetEnvironmentVariable(var.wx_str(), NULL, 0); + DWORD dwRet = ::GetEnvironmentVariable(var.t_str(), NULL, 0); if ( !dwRet ) { // this means that there is no such variable @@ -617,7 +603,7 @@ bool wxGetEnv(const wxString& WXUNUSED_IN_WINCE(var), if ( value ) { - (void)::GetEnvironmentVariable(var.wx_str(), + (void)::GetEnvironmentVariable(var.t_str(), wxStringBuffer(*value, dwRet), dwRet); } @@ -626,29 +612,48 @@ bool wxGetEnv(const wxString& WXUNUSED_IN_WINCE(var), #endif // WinCE/32 } -bool wxDoSetEnv(const wxString& WXUNUSED_IN_WINCE(var), - const wxChar *WXUNUSED_IN_WINCE(value)) +bool wxDoSetEnv(const wxString& var, const wxChar *value) { - // some compilers have putenv() or _putenv() or _wputenv() but it's better - // to always use Win32 function directly instead of dealing with them #ifdef __WXWINCE__ // no environment variables under CE + wxUnusedVar(var); + wxUnusedVar(value); return false; -#else - if ( !::SetEnvironmentVariable(var.wx_str(), value) ) +#else // !__WXWINCE__ + // update the CRT environment if possible as people expect getenv() to also + // work and it is not affected by Win32 SetEnvironmentVariable() call (OTOH + // the CRT does use Win32 call to update the process environment block so + // there is no need to call it) + // + // TODO: add checks for the other compilers (and update wxSetEnv() + // documentation in interface/wx/utils.h accordingly) +#if defined(__VISUALC__) + // 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 + // it here without going through all the troubles with wxSetEnvModule as in + // src/unix/utilsunx.cpp + wxString envstr = var; + envstr += '='; + if ( value ) + envstr += value; + _tputenv(envstr.t_str()); +#else // other compiler + if ( !::SetEnvironmentVariable(var.t_str(), value) ) { - wxLogLastError(_T("SetEnvironmentVariable")); + wxLogLastError(wxT("SetEnvironmentVariable")); return false; } +#endif // compiler return true; -#endif +#endif // __WXWINCE__/!__WXWINCE__ } bool wxSetEnv(const wxString& variable, const wxString& value) { - return wxDoSetEnv(variable, value.wx_str()); + return wxDoSetEnv(variable, value.t_str()); } bool wxUnsetEnv(const wxString& variable) @@ -671,7 +676,7 @@ struct wxFindByPidParams // the PID we're looking from DWORD pid; - DECLARE_NO_COPY_CLASS(wxFindByPidParams) + wxDECLARE_NO_COPY_CLASS(wxFindByPidParams); }; // wxKill helper: EnumWindows() callback which is used to find the first (top @@ -773,12 +778,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; } @@ -805,16 +810,16 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags) // process terminated if ( !::GetExitCodeProcess(hProcess, &rc) ) { - wxLogLastError(_T("GetExitCodeProcess")); + wxLogLastError(wxT("GetExitCodeProcess")); } 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: @@ -859,7 +864,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 @@ -868,13 +873,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 } @@ -953,7 +958,7 @@ bool wxShell(const wxString& command) } // Shutdown or reboot the PC -bool wxShutdown(wxShutdownFlags WXUNUSED_IN_WINCE(wFlags)) +bool wxShutdown(int WXUNUSED_IN_WINCE(flags)) { #ifdef __WXWINCE__ // TODO-CE @@ -973,44 +978,59 @@ bool wxShutdown(wxShutdownFlags WXUNUSED_IN_WINCE(wFlags)) TOKEN_PRIVILEGES tkp; // Get the LUID for the shutdown privilege. - ::LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, - &tkp.Privileges[0].Luid); + bOK = ::LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, + &tkp.Privileges[0].Luid) != 0; + + if ( bOK ) + { + tkp.PrivilegeCount = 1; // one privilege to set + tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - tkp.PrivilegeCount = 1; // one privilege to set - tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + // Get the shutdown privilege for this process. + ::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, + (PTOKEN_PRIVILEGES)NULL, 0); - // Get the shutdown privilege for this process. - ::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, - (PTOKEN_PRIVILEGES)NULL, 0); + // Cannot test the return value of AdjustTokenPrivileges. + bOK = ::GetLastError() == ERROR_SUCCESS; + } - // Cannot test the return value of AdjustTokenPrivileges. - bOK = ::GetLastError() == ERROR_SUCCESS; + ::CloseHandle(hToken); } } if ( bOK ) { - UINT flags = EWX_SHUTDOWN | EWX_FORCE; - switch ( wFlags ) + UINT wFlags = 0; + if ( flags & wxSHUTDOWN_FORCE ) + { + wFlags = EWX_FORCE; + flags &= ~wxSHUTDOWN_FORCE; + } + + switch ( flags ) { case wxSHUTDOWN_POWEROFF: - flags |= EWX_POWEROFF; + wFlags |= EWX_POWEROFF; break; case wxSHUTDOWN_REBOOT: - flags |= EWX_REBOOT; + wFlags |= EWX_REBOOT; + break; + + case wxSHUTDOWN_LOGOFF: + wFlags |= EWX_LOGOFF; break; default: - wxFAIL_MSG( _T("unknown wxShutdown() flag") ); + wxFAIL_MSG( wxT("unknown wxShutdown() flag") ); return false; } - bOK = ::ExitWindowsEx(flags, 0) != 0; + bOK = ::ExitWindowsEx(wFlags, 0) != 0; } return bOK; -#endif // Win32/16 +#endif // WinCE/!WinCE } // ---------------------------------------------------------------------------- @@ -1048,25 +1068,123 @@ 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 wxString& resourceType, + WXHINSTANCE instance) +{ + wxCHECK_MSG( outData && outLen, false, "output pointers can't be NULL" ); + + HRSRC hResource = ::FindResource(instance, + resourceName.wx_str(), + resourceType.wx_str()); + 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 wxString& 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 // ---------------------------------------------------------------------------- +// check if we're running under a server or workstation Windows system: it +// returns true or false with obvious meaning as well as -1 if the system type +// couldn't be determined +// +// this function is currently private but we may want to expose it later if +// it's really useful +namespace +{ + +int wxIsWindowsServer() +{ +#ifdef VER_NT_WORKSTATION + OSVERSIONINFOEX info; + wxZeroMemory(info); + + info.dwOSVersionInfoSize = sizeof(info); + if ( ::GetVersionEx(reinterpret_cast(&info)) ) + { + switch ( info.wProductType ) + { + case VER_NT_WORKSTATION: + return false; + + case VER_NT_SERVER: + case VER_NT_DOMAIN_CONTROLLER: + return true; + } + } +#endif // VER_NT_WORKSTATION + + return -1; +} + +} // anonymous namespace + wxString wxGetOsDescription() { wxString str; @@ -1126,7 +1244,7 @@ wxString wxGetOsDescription() } if ( !wxIsEmpty(info.szCSDVersion) ) { - str << _T(" (") << info.szCSDVersion << _T(')'); + str << wxT(" (") << info.szCSDVersion << wxT(')'); } break; @@ -1141,15 +1259,22 @@ wxString wxGetOsDescription() info.dwBuildNumber); break; + case 2: + // we can't distinguish between XP 64 and 2003 + // as they both are 5.2, so examine the product + // type to resolve this ambiguity + if ( wxIsWindowsServer() == 1 ) + { + str.Printf(_("Windows Server 2003 (build %lu"), + info.dwBuildNumber); + break; + } + //else: must be XP, fall through + case 1: str.Printf(_("Windows XP (build %lu"), info.dwBuildNumber); break; - - case 2: - str.Printf(_("Windows Server 2003 (build %lu"), - info.dwBuildNumber); - break; } break; @@ -1172,15 +1297,18 @@ wxString wxGetOsDescription() if ( !wxIsEmpty(info.szCSDVersion) ) { - str << _T(", ") << info.szCSDVersion; + str << wxT(", ") << info.szCSDVersion; } - str << _T(')'); + str << wxT(')'); + + if ( wxIsPlatform64Bit() ) + str << _(", 64-bit edition"); break; } } else { - wxFAIL_MSG( _T("GetVersionEx() failed") ); // should never happen + wxFAIL_MSG( wxT("GetVersionEx() failed") ); // should never happen } return str; @@ -1194,9 +1322,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 ) @@ -1586,7 +1714,7 @@ 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 )