]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/utils.cpp
Fix MSW compilation with wxUSE_DEFERRED_SIZING==0.
[wxWidgets.git] / src / msw / utils.cpp
index 4e674fcbde6b67fbe91903d1ee328fac1ba5d87d..e23656dfa91a86f03f812fbc2328b90648ee240f 100644 (file)
@@ -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 <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
@@ -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;
 
-            tkp.PrivilegeCount = 1;  // one privilege to set
-            tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+            if ( bOK )
+            {
+                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<OSVERSIONINFO *>(&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,29 +1244,49 @@ wxString wxGetOsDescription()
                 }
                 if ( !wxIsEmpty(info.szCSDVersion) )
                 {
-                    str << _T(" (") << info.szCSDVersion << _T(')');
+                    str << wxT(" (") << info.szCSDVersion << wxT(')');
                 }
                 break;
 
             case VER_PLATFORM_WIN32_NT:
-                if ( info.dwMajorVersion == 5 )
+                switch ( info.dwMajorVersion )
                 {
-                    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"),
+                    case 5:
+                        switch ( info.dwMinorVersion )
+                        {
+                            case 0:
+                                str.Printf(_("Windows 2000 (build %lu"),
+                                           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;
+                        }
+                        break;
+
+                    case 6:
+                        if ( info.dwMinorVersion == 0 )
+                        {
+                            str.Printf(_("Windows Vista (build %lu"),
                                        info.dwBuildNumber);
-                            break;
-                    }
+                        }
+                        break;
                 }
+
                 if ( str.empty() )
                 {
                     str.Printf(_("Windows NT %lu.%lu (build %lu"),
@@ -1156,17 +1294,21 @@ wxString wxGetOsDescription()
                            info.dwMinorVersion,
                            info.dwBuildNumber);
                 }
+
                 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;
@@ -1180,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 )
@@ -1572,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 )