]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/utils.cpp
Preserve client data pointers when setting bitmaps in wxBitmapComboBox.
[wxWidgets.git] / src / msw / utils.cpp
index 7779e616da28a2f1f06e872ffe3ba126f85bcd0e..afd0bb2e6c0f38742c9bbf3cc2ac680ad7ea31c5 100644 (file)
@@ -41,6 +41,7 @@
 #include "wx/confbase.h"        // for wxExpandEnvVars()
 
 #include "wx/msw/private.h"     // includes <windows.h>
+#include "wx/msw/private/hiddenwin.h"
 #include "wx/msw/missing.h"     // for CHARSET_HANGUL
 
 #if defined(__CYGWIN__)
 #if !defined(__GNUWIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
     #include <direct.h>
 
-    #ifndef __MWERKS__
-        #include <dos.h>
-    #endif
+    #include <dos.h>
 #endif  //GNUWIN32
 
 #if defined(__CYGWIN__)
     #include <sys/unistd.h>
     #include <sys/stat.h>
-    #include <sys/cygwin.h> // for cygwin_conv_to_full_win32_path()
+    #include <sys/cygwin.h> // for cygwin_conv_path()
+    // and cygwin_conv_to_full_win32_path()
+    #include <cygwin/version.h>
 #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
 // ============================================================================
@@ -127,13 +130,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;
-#else
+    // 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.t_str(), maxSize);
+#else // !__WXWINCE__
     DWORD nSize = maxSize;
     if ( !::GetComputerName(buf, &nSize) )
     {
@@ -141,9 +150,9 @@ bool wxGetHostName(wxChar *WXUNUSED_IN_WINCE(buf),
 
         return false;
     }
+#endif // __WXWINCE__/!__WXWINCE__
 
     return true;
-#endif
 }
 
 // get full hostname (with domain name if possible)
@@ -157,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 *);
@@ -168,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);
 
@@ -258,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"));
@@ -293,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;
     }
@@ -359,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."));
@@ -375,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__)
@@ -473,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
@@ -486,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;
         }
@@ -536,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;
         }
@@ -613,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
@@ -623,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;
     }
@@ -694,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 )
@@ -716,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 )
     {
@@ -737,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"
@@ -764,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;
                     }
@@ -785,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;
         }
     }
@@ -820,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 )
@@ -850,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
@@ -859,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
 }
@@ -1008,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;
         }
 
@@ -1044,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
 // ----------------------------------------------------------------------------
@@ -1167,7 +1257,7 @@ wxString wxGetOsDescription()
                 }
                 if ( !wxIsEmpty(info.szCSDVersion) )
                 {
-                    str << _T(" (") << info.szCSDVersion << _T(')');
+                    str << wxT(" (") << info.szCSDVersion << wxT(')');
                 }
                 break;
 
@@ -1178,8 +1268,7 @@ wxString wxGetOsDescription()
                         switch ( info.dwMinorVersion )
                         {
                             case 0:
-                                str.Printf(_("Windows 2000 (build %lu"),
-                                           info.dwBuildNumber);
+                                str = _("Windows 2000");
                                 break;
 
                             case 2:
@@ -1188,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");
@@ -1231,7 +1328,7 @@ wxString wxGetOsDescription()
     }
     else
     {
-        wxFAIL_MSG( _T("GetVersionEx() failed") ); // should never happen
+        wxFAIL_MSG( wxT("GetVersionEx() failed") ); // should never happen
     }
 
     return str;
@@ -1245,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 )
@@ -1621,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 )