]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/utils.cpp
merge msw/gsocket.cpp into msw/sockmsw.cpp
[wxWidgets.git] / src / msw / utils.cpp
index 71f5e6521e775a864eb66094b9670987acb7b7b3..328839265aec279761462467f174546c0e2b17b1 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        msw/utils.cpp
+// Name:        src/msw/utils.cpp
 // Purpose:     Various utilities
 // Author:      Julian Smart
 // Modified by:
     #include "wx/log.h"
 #endif  //WX_PRECOMP
 
+#include "wx/msw/registry.h"
 #include "wx/apptrait.h"
+#include "wx/dynlib.h"
 #include "wx/dynload.h"
+#include "wx/scopeguard.h"
 
 #include "wx/confbase.h"        // for wxExpandEnvVars()
 
 #include "wx/msw/private.h"     // includes <windows.h>
-#include "wx/msw/missing.h"     // CHARSET_HANGUL
+#include "wx/msw/missing.h"     // for CHARSET_HANGUL
+
+#if defined(__CYGWIN__)
+    //CYGWIN gives annoying warning about runtime stuff if we don't do this
+#   define USE_SYS_TYPES_FD_SET
+#   include <sys/types.h>
+#endif
 
-#if defined(__GNUWIN32_OLD__) || defined(__WXWINCE__) \
-    || defined(__CYGWIN32__)
+// Doesn't work with Cygwin at present
+#if wxUSE_SOCKETS && (defined(__GNUWIN32_OLD__) || defined(__WXWINCE__) || defined(__CYGWIN32__))
     // apparently we need to include winsock.h to get WSADATA and other stuff
     // used in wxGetFullHostName() with the old mingw32 versions
     #include <winsock.h>
 #endif
 
-#include "wx/timer.h"
-
-#if !defined(__GNUWIN32__) && !defined(__SALFORDC__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
+#if !defined(__GNUWIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
     #include <direct.h>
 
     #ifndef __MWERKS__
 // ----------------------------------------------------------------------------
 
 // In the WIN.INI file
+#if (!defined(USE_NET_API) && !defined(__WXWINCE__)) || defined(__WXMICROWIN__)
 static const wxChar WX_SECTION[] = wxT("wxWindows");
+#endif
+
+#if (!defined(USE_NET_API) && !defined(__WXWINCE__))
 static const wxChar eUSERNAME[]  = wxT("UserName");
+#endif
 
 // ============================================================================
 // implementation
@@ -114,11 +126,13 @@ static const wxChar eUSERNAME[]  = wxT("UserName");
 // ----------------------------------------------------------------------------
 
 // Get hostname only (without domain name)
-bool wxGetHostName(wxChar *buf, int maxSize)
+bool wxGetHostName(wxChar *WXUNUSED_IN_WINCE(buf),
+                   int WXUNUSED_IN_WINCE(maxSize))
 {
 #if defined(__WXWINCE__)
+    // TODO-CE
     return false;
-#elif defined(__WIN32__) && !defined(__WXMICROWIN__)
+#else
     DWORD nSize = maxSize;
     if ( !::GetComputerName(buf, &nSize) )
     {
@@ -128,23 +142,13 @@ bool wxGetHostName(wxChar *buf, int maxSize)
     }
 
     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)
 bool wxGetFullHostName(wxChar *buf, int maxSize)
 {
-#if !defined( __WXMICROWIN__) && wxUSE_DYNAMIC_LOADER
+#if !defined( __WXMICROWIN__) && wxUSE_DYNLIB_CLASS && wxUSE_SOCKETS
     // TODO should use GetComputerNameEx() when available
 
     // we don't want to always link with Winsock DLL as we might not use it at
@@ -214,7 +218,7 @@ bool wxGetFullHostName(wxChar *buf, int maxSize)
 
             if ( !host.empty() )
             {
-                wxStrncpy(buf, host, maxSize);
+                wxStrlcpy(buf, host.c_str(), maxSize);
 
                 return true;
             }
@@ -226,11 +230,13 @@ bool wxGetFullHostName(wxChar *buf, int maxSize)
 }
 
 // Get user ID e.g. jacs
-bool wxGetUserId(wxChar *buf, int maxSize)
+bool wxGetUserId(wxChar *WXUNUSED_IN_WINCE(buf),
+                 int WXUNUSED_IN_WINCE(maxSize))
 {
 #if defined(__WXWINCE__)
+    // TODO-CE
     return false;
-#elif defined(__WIN32__) && !defined(__WXMICROWIN__)
+#else
     DWORD nSize = maxSize;
     if ( ::GetUserName(buf, &nSize) == 0 )
     {
@@ -244,32 +250,24 @@ bool wxGetUserId(wxChar *buf, int maxSize)
     }
 
     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
 }
 
 // Get user name e.g. Julian Smart
 bool wxGetUserName(wxChar *buf, int maxSize)
 {
-#if defined(__WXWINCE__)
-    return false;
+    wxCHECK_MSG( buf && ( maxSize > 0 ), false,
+                    _T("empty buffer in wxGetUserName") );
+#if defined(__WXWINCE__) && wxUSE_REGKEY
+    wxLogNull noLog;
+    wxRegKey key(wxRegKey::HKCU, wxT("ControlPanel\\Owner"));
+    if(!key.Open(wxRegKey::Read))
+        return false;
+    wxString name;
+    if(!key.QueryValue(wxT("Owner"),name))
+        return false;
+    wxStrlcpy(buf, name.c_str(), maxSize);
+    return true;
 #elif defined(USE_NET_API)
     CHAR szUserName[256];
     if ( !wxGetUserId(szUserName, WXSIZEOF(szUserName)) )
@@ -347,11 +345,11 @@ error:
 
     if ( !ok )
     {
-        wxStrncpy(buf, wxT("Unknown User"), maxSize);
+        wxStrlcpy(buf, wxT("Unknown User"), maxSize);
     }
-#endif // Win32/16
 
     return true;
+#endif // Win32/16
 }
 
 const wxChar* wxGetHomeDir(wxString *pstr)
@@ -359,7 +357,7 @@ const wxChar* wxGetHomeDir(wxString *pstr)
     wxString& strDir = *pstr;
 
     // first branch is for Cygwin
-#if defined(__UNIX__)
+#if defined(__UNIX__) && !defined(__WINE__)
     const wxChar *szHome = wxGetenv("HOME");
     if ( szHome == NULL ) {
       // we're homeless...
@@ -380,7 +378,7 @@ const wxChar* wxGetHomeDir(wxString *pstr)
         strDir = windowsPath;
     #endif
 #elif defined(__WXWINCE__)
-      // Nothing
+    strDir = wxT("\\");
 #else
     strDir.clear();
 
@@ -440,29 +438,22 @@ const wxChar* wxGetHomeDir(wxString *pstr)
     return strDir.c_str();
 }
 
-wxChar *wxGetUserHome(const wxString& WXUNUSED(user))
+wxString wxGetUserHome(const wxString& user)
 {
-    // VZ: the old code here never worked for user != "" anyhow! Moreover, it
-    //     returned sometimes a malloc()'d pointer, sometimes a pointer to a
-    //     static buffer and sometimes I don't even know what.
-    static wxString s_home;
+    wxString home;
 
-    return (wxChar *)wxGetHomeDir(&s_home);
-}
+    if ( user.empty() || user == wxGetUserId() )
+        wxGetHomeDir(&home);
 
-bool wxDirExists(const wxString& dir)
-{
-#ifdef __WXMICROWIN__
-    return wxPathExist(dir);
-#elif defined(__WIN32__)
-    DWORD attribs = GetFileAttributes(dir);
-    return ((attribs != (DWORD)-1) && (attribs & FILE_ATTRIBUTE_DIRECTORY));
-#endif // Win32/__WXMICROWIN__
+    return home;
 }
 
-bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree)
+bool wxGetDiskSpace(const wxString& WXUNUSED_IN_WINCE(path),
+                    wxDiskspaceSize_t *WXUNUSED_IN_WINCE(pTotal),
+                    wxDiskspaceSize_t *WXUNUSED_IN_WINCE(pFree))
 {
 #ifdef __WXWINCE__
+    // TODO-CE
     return false;
 #else
     if ( path.empty() )
@@ -494,7 +485,7 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree)
         ULARGE_INTEGER bytesFree, bytesTotal;
 
         // may pass the path as is, GetDiskFreeSpaceEx() is smart enough
-        if ( !pGetDiskFreeSpaceEx(path,
+        if ( !pGetDiskFreeSpaceEx(path.fn_str(),
                                   &bytesFree,
                                   &bytesTotal,
                                   NULL) )
@@ -514,12 +505,20 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree)
 #endif
         if ( pTotal )
         {
-            *pTotal = wxLongLong(UL(bytesTotal).HighPart, UL(bytesTotal).LowPart);
+#if wxUSE_LONGLONG
+            *pTotal = wxDiskspaceSize_t(UL(bytesTotal).HighPart, UL(bytesTotal).LowPart);
+#else
+            *pTotal = wxDiskspaceSize_t(UL(bytesTotal).LowPart);
+#endif
         }
 
         if ( pFree )
         {
+#if wxUSE_LONGLONG
             *pFree = wxLongLong(UL(bytesFree).HighPart, UL(bytesFree).LowPart);
+#else
+            *pFree = wxDiskspaceSize_t(UL(bytesFree).LowPart);
+#endif
         }
     }
     else
@@ -536,7 +535,7 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree)
 
         // FIXME: this is wrong, we should extract the root drive from path
         //        instead, but this is the job for wxFileName...
-        if ( !::GetDiskFreeSpace(path,
+        if ( !::GetDiskFreeSpace(path.fn_str(),
                                  &lSectorsPerCluster,
                                  &lBytesPerSector,
                                  &lNumberOfFreeClusters,
@@ -547,7 +546,7 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree)
             return false;
         }
 
-        wxLongLong lBytesPerCluster = lSectorsPerCluster;
+        wxDiskspaceSize_t lBytesPerCluster = (wxDiskspaceSize_t) lSectorsPerCluster;
         lBytesPerCluster *= lBytesPerSector;
 
         if ( pTotal )
@@ -572,13 +571,15 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree)
 // env vars
 // ----------------------------------------------------------------------------
 
-bool wxGetEnv(const wxString& var, wxString *value)
+bool wxGetEnv(const wxString& WXUNUSED_IN_WINCE(var),
+              wxString *WXUNUSED_IN_WINCE(value))
 {
 #ifdef __WXWINCE__
+    // no environment variables under CE
     return false;
 #else // Win32
     // first get the size of the buffer
-    DWORD dwRet = ::GetEnvironmentVariable(var, NULL, 0);
+    DWORD dwRet = ::GetEnvironmentVariable(var.t_str(), NULL, 0);
     if ( !dwRet )
     {
         // this means that there is no such variable
@@ -587,7 +588,8 @@ bool wxGetEnv(const wxString& var, wxString *value)
 
     if ( value )
     {
-        (void)::GetEnvironmentVariable(var, wxStringBuffer(*value, dwRet),
+        (void)::GetEnvironmentVariable(var.t_str(),
+                                       wxStringBuffer(*value, dwRet),
                                        dwRet);
     }
 
@@ -595,12 +597,16 @@ bool wxGetEnv(const wxString& var, wxString *value)
 #endif // WinCE/32
 }
 
-bool wxSetEnv(const wxString& var, const wxChar *value)
+bool wxDoSetEnv(const wxString& WXUNUSED_IN_WINCE(var),
+                const wxChar *WXUNUSED_IN_WINCE(value))
 {
     // some compilers have putenv() or _putenv() or _wputenv() but it's better
     // to always use Win32 function directly instead of dealing with them
-#if defined(__WIN32__) && !defined(__WXWINCE__)
-    if ( !::SetEnvironmentVariable(var, value) )
+#ifdef __WXWINCE__
+    // no environment variables under CE
+    return false;
+#else
+    if ( !::SetEnvironmentVariable(var.t_str(), value) )
     {
         wxLogLastError(_T("SetEnvironmentVariable"));
 
@@ -608,11 +614,19 @@ bool wxSetEnv(const wxString& var, const wxChar *value)
     }
 
     return true;
-#else // no way to set env vars
-    return false;
 #endif
 }
 
+bool wxSetEnv(const wxString& variable, const wxString& value)
+{
+    return wxDoSetEnv(variable, value.t_str());
+}
+
+bool wxUnsetEnv(const wxString& variable)
+{
+    return wxDoSetEnv(variable, NULL);
+}
+
 // ----------------------------------------------------------------------------
 // process management
 // ----------------------------------------------------------------------------
@@ -669,19 +683,19 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags)
     {
         if ( krc )
         {
-            if ( ::GetLastError() == ERROR_ACCESS_DENIED )
-            {
-                *krc = wxKILL_ACCESS_DENIED;
-            }
-            else
-            {
-                *krc = wxKILL_NO_PROCESS;
-            }
+            // recognize wxKILL_ACCESS_DENIED as special because this doesn't
+            // mean that the process doesn't exist and this is important for
+            // wxProcess::Exists()
+            *krc = ::GetLastError() == ERROR_ACCESS_DENIED
+                        ? wxKILL_ACCESS_DENIED
+                        : wxKILL_NO_PROCESS;
         }
 
         return -1;
     }
 
+    wxON_BLOCK_EXIT1(::CloseHandle, hProcess);
+
     bool ok = true;
     switch ( sig )
     {
@@ -704,7 +718,9 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags)
 
         case wxSIGNONE:
             // do nothing, we just want to test for process existence
-            break;
+            if ( krc )
+                *krc = wxKILL_OK;
+            return 0;
 
         default:
             // any other signal means "terminate"
@@ -713,7 +729,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags)
                 params.pid = (DWORD)pid;
 
                 // EnumWindows() has nice semantics: it returns 0 if it found
-                // something or if an error occured and non zero if it
+                // something or if an error occurred and non zero if it
                 // enumerated all the window
                 if ( !::EnumWindows(wxEnumFindByPidProc, (LPARAM)&params) )
                 {
@@ -722,7 +738,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags)
                     {
                         // tell the app to close
                         //
-                        // NB: this is the harshest way, the app won't have
+                        // NB: this is the harshest way, the app won't have an
                         //     opportunity to save any files, for example, but
                         //     this is probably what we want here. If not we
                         //     can also use SendMesageTimeout(WM_CLOSE)
@@ -741,9 +757,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags)
                 else // no windows for this PID
                 {
                     if ( krc )
-                    {
                         *krc = wxKILL_ERROR;
-                    }
 
                     ok = false;
                 }
@@ -751,8 +765,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags)
     }
 
     // the return code
-    DWORD rc;
-
+    DWORD rc wxDUMMY_INITIALIZE(0);
     if ( ok )
     {
         // as we wait for a short time, we can use just WaitForSingleObject()
@@ -777,45 +790,30 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags)
 
             case WAIT_TIMEOUT:
                 if ( krc )
-                {
                     *krc = wxKILL_ERROR;
-                }
 
                 rc = STILL_ACTIVE;
                 break;
         }
     }
-    else // !ok
-    {
-        // just to suppress the warnings about uninitialized variable
-        rc = 0;
-    }
 
-    ::CloseHandle(hProcess);
 
     // the return code is the same as from Unix kill(): 0 if killed
     // successfully or -1 on error
-    //
-    // be careful to interpret rc correctly: for wxSIGNONE we return success if
-    // the process exists, for all the other sig values -- if it doesn't
-    if ( ok &&
-            ((sig == wxSIGNONE) == (rc == STILL_ACTIVE)) )
-    {
-        if ( krc )
-        {
-            *krc = wxKILL_OK;
-        }
+    if ( !ok || rc == STILL_ACTIVE )
+        return -1;
 
-        return 0;
-    }
+    if ( krc )
+        *krc = wxKILL_OK;
 
-    // error
-    return -1;
+    return 0;
 }
 
-HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD) ;
-BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32) ;
-BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32) ;
+typedef HANDLE (WINAPI *CreateToolhelp32Snapshot_t)(DWORD,DWORD);
+typedef BOOL (WINAPI *Process32_t)(HANDLE,LPPROCESSENTRY32);
+
+CreateToolhelp32Snapshot_t lpfCreateToolhelp32Snapshot;
+Process32_t lpfProcess32First, lpfProcess32Next;
 
 static void InitToolHelp32()
 {
@@ -830,9 +828,9 @@ static void InitToolHelp32()
     lpfProcess32First = NULL;
     lpfProcess32Next = NULL;
 
-    HINSTANCE hInstLib = LoadLibrary( wxT("Kernel32.DLL") ) ;
-    if( hInstLib == NULL )
-        return ;
+#if wxUSE_DYNLIB_CLASS
+
+    wxDynamicLibrary dllKernel(_T("kernel32.dll"), wxDL_VERBATIM);
 
     // Get procedure addresses.
     // We are linking to these functions of Kernel32
@@ -840,37 +838,16 @@ static void InitToolHelp32()
     // 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
-        ) ;
+    lpfCreateToolhelp32Snapshot =
+        (CreateToolhelp32Snapshot_t)dllKernel.RawGetSymbol(_T("CreateToolhelp32Snapshot"));
 
-    lpfProcess32First=
-        (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
-        GetProcAddress( hInstLib,
-#ifdef __WXWINCE__
-        wxT("Process32First")
-#else
-        "Process32First"
-#endif
-        ) ;
+    lpfProcess32First =
+        (Process32_t)dllKernel.RawGetSymbol(_T("Process32First"));
 
-    lpfProcess32Next=
-        (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
-        GetProcAddress( hInstLib,
-#ifdef __WXWINCE__
-        wxT("Process32Next")
-#else
-        "Process32Next"
-#endif
-        ) ;
+    lpfProcess32Next =
+        (Process32_t)dllKernel.RawGetSymbol(_T("Process32Next"));
 
-    FreeLibrary( hInstLib ) ;
+#endif // wxUSE_DYNLIB_CLASS
 }
 
 // By John Skiff
@@ -894,7 +871,8 @@ int wxKillAllChildren(long pid, wxSignal sig, wxKillError *krc)
     }
 
     //Fill in the size of the structure before using it.
-    PROCESSENTRY32 pe = {0};
+    PROCESSENTRY32 pe;
+    wxZeroMemory(pe);
     pe.dwSize = sizeof(PROCESSENTRY32);
 
     // Walk the snapshot of the processes, and for each process,
@@ -946,14 +924,15 @@ bool wxShell(const wxString& command)
 }
 
 // Shutdown or reboot the PC
-bool wxShutdown(wxShutdownFlags wFlags)
+bool wxShutdown(int WXUNUSED_IN_WINCE(flags))
 {
 #ifdef __WXWINCE__
+    // TODO-CE
     return false;
 #elif defined(__WIN32__)
     bool bOK = true;
 
-    if ( wxGetOsVersion(NULL, NULL) == wxWINDOWS_NT ) // if is NT or 2K
+    if ( wxGetOsVersion(NULL, NULL) == wxOS_WINDOWS_NT ) // if is NT or 2K
     {
         // Get a token for this process.
         HANDLE hToken;
@@ -965,32 +944,47 @@ bool wxShutdown(wxShutdownFlags 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:
@@ -998,11 +992,11 @@ bool wxShutdown(wxShutdownFlags wFlags)
                 return false;
         }
 
-        bOK = ::ExitWindowsEx(flags, 0) != 0;
+        bOK = ::ExitWindowsEx(wFlags, 0) != 0;
     }
 
     return bOK;
-#endif // Win32/16
+#endif // WinCE/!WinCE
 }
 
 // ----------------------------------------------------------------------------
@@ -1014,9 +1008,9 @@ wxMemorySize wxGetFreeMemory()
 {
 #if defined(__WIN64__)
     MEMORYSTATUSEX memStatex;
-    statex.dwLength = sizeof (statex);
-    ::GlobalMemoryStatusEx (&statex);
-    return (wxMemorySize)memStatus.ullAvailPhys;
+    memStatex.dwLength = sizeof (memStatex);
+    ::GlobalMemoryStatusEx (&memStatex);
+    return (wxMemorySize)memStatex.ullAvailPhys;
 #else /* if defined(__WIN32__) */
     MEMORYSTATUS memStatus;
     memStatus.dwLength = sizeof(MEMORYSTATUS);
@@ -1038,6 +1032,7 @@ void wxBell()
 
 bool wxIsDebuggerRunning()
 {
+#if wxUSE_DYNLIB_CLASS
     // IsDebuggerPresent() is not available under Win95, so load it dynamically
     wxDynamicLibrary dll(_T("kernel32.dll"), wxDL_VERBATIM);
 
@@ -1049,12 +1044,50 @@ bool wxIsDebuggerRunning()
     }
 
     return (*(IsDebuggerPresent_t)dll.GetSymbol(_T("IsDebuggerPresent")))() != 0;
+#else
+    return false;
+#endif
 }
 
 // ----------------------------------------------------------------------------
 // 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;
@@ -1067,6 +1100,13 @@ wxString wxGetOsDescription()
     {
         switch ( info.dwPlatformId )
         {
+#ifdef VER_PLATFORM_WIN32_CE
+            case VER_PLATFORM_WIN32_CE:
+                str.Printf(_("Windows CE (%d.%d)"),
+                           info.dwMajorVersion,
+                           info.dwMinorVersion);
+                break;
+#endif
             case VER_PLATFORM_WIN32s:
                 str = _("Win32s on Windows 3.1");
                 break;
@@ -1112,36 +1152,60 @@ wxString wxGetOsDescription()
                 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 ( wxIsEmpty(str) )
+
+                if ( str.empty() )
                 {
                     str.Printf(_("Windows NT %lu.%lu (build %lu"),
                            info.dwMajorVersion,
                            info.dwMinorVersion,
                            info.dwBuildNumber);
                 }
+
                 if ( !wxIsEmpty(info.szCSDVersion) )
                 {
                     str << _T(", ") << info.szCSDVersion;
                 }
                 str << _T(')');
+
+                if ( wxIsPlatform64Bit() )
+                    str << _(", 64-bit edition");
                 break;
         }
     }
@@ -1153,56 +1217,150 @@ wxString wxGetOsDescription()
     return str;
 }
 
-wxToolkitInfo& wxAppTraits::GetToolkitInfo()
+bool wxIsPlatform64Bit()
+{
+#if defined(_WIN64)
+    return true;  // 64-bit programs run only on Win64
+#elif wxUSE_DYNLIB_CLASS // Win32
+    // 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"));
+    IsWow64Process_t pfnIsWow64Process =
+        (IsWow64Process_t)dllKernel32.RawGetSymbol(_T("IsWow64Process"));
+
+    BOOL wow64 = FALSE;
+    if ( pfnIsWow64Process )
+    {
+        pfnIsWow64Process(::GetCurrentProcess(), &wow64);
+    }
+    //else: running under a system without Win64 support
+
+    return wow64 != FALSE;
+#else
+    return false;
+#endif // Win64/Win32
+}
+
+wxOperatingSystemId wxGetOsVersion(int *verMaj, int *verMin)
 {
-    // cache the version info, it's not going to change
-    //
-    // NB: this is MT-safe, we may use these static vars from different threads
-    //     but as they always have the same value it doesn't matter
-    static int s_ver = -1,
-               s_major = -1,
-               s_minor = -1;
-
-    if ( s_ver == -1 )
+    static struct
+    {
+        // this may be false, true or -1 if we tried to initialize but failed
+        int initialized;
+
+        wxOperatingSystemId os;
+
+        int verMaj,
+            verMin;
+    } s_version;
+
+    // query the OS info only once as it's not supposed to change
+    if ( !s_version.initialized )
     {
         OSVERSIONINFO info;
         wxZeroMemory(info);
-
-        s_ver = wxWINDOWS;
-        info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+        info.dwOSVersionInfoSize = sizeof(info);
         if ( ::GetVersionEx(&info) )
         {
-            s_major = info.dwMajorVersion;
-            s_minor = info.dwMinorVersion;
+            s_version.initialized = true;
 
+#if defined(__WXWINCE__)
+            s_version.os = wxOS_WINDOWS_CE;
+#elif defined(__WXMICROWIN__)
+            s_version.os = wxOS_WINDOWS_MICRO;
+#else // "normal" desktop Windows system, use run-time detection
             switch ( info.dwPlatformId )
             {
-                case VER_PLATFORM_WIN32s:
-                    s_ver = wxWIN32S;
+                case VER_PLATFORM_WIN32_NT:
+                    s_version.os = wxOS_WINDOWS_NT;
                     break;
 
                 case VER_PLATFORM_WIN32_WINDOWS:
-                    s_ver = wxWIN95;
+                    s_version.os = wxOS_WINDOWS_9X;
                     break;
+            }
+#endif // Windows versions
 
-                case VER_PLATFORM_WIN32_NT:
-                    s_ver = wxWINDOWS_NT;
-                    break;
-#ifdef __WXWINCE__
-                case VER_PLATFORM_WIN32_CE:
-                    s_ver = wxWINDOWS_CE;
+            s_version.verMaj = info.dwMajorVersion;
+            s_version.verMin = info.dwMinorVersion;
+        }
+        else // GetVersionEx() failed
+        {
+            s_version.initialized = -1;
+        }
+    }
+
+    if ( s_version.initialized == 1 )
+    {
+        if ( verMaj )
+            *verMaj = s_version.verMaj;
+        if ( verMin )
+            *verMin = s_version.verMin;
+    }
+
+    // this works even if we were not initialized successfully as the initial
+    // values of this field is 0 which is wxOS_UNKNOWN and exactly what we need
+    return s_version.os;
+}
+
+wxWinVersion wxGetWinVersion()
+{
+    int verMaj,
+        verMin;
+    switch ( wxGetOsVersion(&verMaj, &verMin) )
+    {
+        case wxOS_WINDOWS_9X:
+            if ( verMaj == 4 )
+            {
+                switch ( verMin )
+                {
+                    case 0:
+                        return wxWinVersion_95;
+
+                    case 10:
+                        return wxWinVersion_98;
+
+                    case 90:
+                        return wxWinVersion_ME;
+                }
+            }
+            break;
+
+        case wxOS_WINDOWS_NT:
+            switch ( verMaj )
+            {
+                case 3:
+                    return wxWinVersion_NT3;
+
+                case 4:
+                    return wxWinVersion_NT4;
+
+                case 5:
+                    switch ( verMin )
+                    {
+                        case 0:
+                            return wxWinVersion_2000;
+
+                        case 1:
+                            return wxWinVersion_XP;
+
+                        case 2:
+                            return wxWinVersion_2003;
+                    }
                     break;
-#endif
+
+                case 6:
+                    return wxWinVersion_NT6;
             }
-        }
+            break;
+
+        default:
+            // Do nothing just to silence GCC warning
+            break;
     }
 
-    static wxToolkitInfo info;
-    info.versionMajor = s_major;
-    info.versionMinor = s_minor;
-    info.os = s_ver;
-    info.name = _T("wxBase");
-    return info;
+    return wxWinVersion_Unknown;
 }
 
 // ----------------------------------------------------------------------------
@@ -1250,8 +1408,10 @@ extern WXDLLIMPEXP_BASE long wxEncodingToCharset(wxFontEncoding encoding)
         case wxFONTENCODING_CP936:
             return GB2312_CHARSET;
 
+#ifndef __WXWINCE__
         case wxFONTENCODING_CP949:
             return HANGUL_CHARSET;
+#endif
 
         case wxFONTENCODING_CP950:
             return CHINESEBIG5_CHARSET;
@@ -1304,9 +1464,9 @@ extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding)
     // There don't seem to be symbolic names for
     // these under Windows so I just copied the
     // values from MSDN.
-    
+
     unsigned int ret;
-    
+
     switch (encoding)
     {
         case wxFONTENCODING_ISO8859_1:      ret = 28591; break;
@@ -1319,13 +1479,15 @@ extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding)
         case wxFONTENCODING_ISO8859_8:      ret = 28598; break;
         case wxFONTENCODING_ISO8859_9:      ret = 28599; break;
         case wxFONTENCODING_ISO8859_10:     ret = 28600; break;
-        case wxFONTENCODING_ISO8859_11:     ret = 28601; break;
+        case wxFONTENCODING_ISO8859_11:     ret = 874; break;
         // case wxFONTENCODING_ISO8859_12,      // doesn't exist currently, but put it
-        case wxFONTENCODING_ISO8859_13:     ret = 28603; break;      
-        case wxFONTENCODING_ISO8859_14:     ret = 28604; break;
+        case wxFONTENCODING_ISO8859_13:     ret = 28603; break;
+        // case wxFONTENCODING_ISO8859_14:     ret = 28604; break; // no correspondence on Windows
         case wxFONTENCODING_ISO8859_15:     ret = 28605; break;
+
         case wxFONTENCODING_KOI8:           ret = 20866; break;
         case wxFONTENCODING_KOI8_U:         ret = 21866; break;
+
         case wxFONTENCODING_CP437:          ret = 437; break;
         case wxFONTENCODING_CP850:          ret = 850; break;
         case wxFONTENCODING_CP852:          ret = 852; break;
@@ -1344,7 +1506,9 @@ extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding)
         case wxFONTENCODING_CP1255:         ret = 1255; break;
         case wxFONTENCODING_CP1256:         ret = 1256; break;
         case wxFONTENCODING_CP1257:         ret = 1257; break;
-        case wxFONTENCODING_EUC_JP:         ret = 51932; break;
+
+        case wxFONTENCODING_EUC_JP:         ret = 20932; break;
+
         case wxFONTENCODING_MACROMAN:       ret = 10000; break;
         case wxFONTENCODING_MACJAPANESE:    ret = 10001; break;
         case wxFONTENCODING_MACCHINESETRAD: ret = 10002; break;
@@ -1359,14 +1523,18 @@ extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding)
         case wxFONTENCODING_MACCROATIAN:    ret = 10082; break;
         case wxFONTENCODING_MACICELANDIC:   ret = 10079; break;
         case wxFONTENCODING_MACROMANIAN:    ret = 10009; break;
+
+        case wxFONTENCODING_ISO2022_JP:     ret = 50222; break;
+
         case wxFONTENCODING_UTF7:           ret = 65000; break;
         case wxFONTENCODING_UTF8:           ret = 65001; break;
+
         default:                            return -1;
     }
-    
+
     if (::IsValidCodePage(ret) == 0)
         return -1;
-    
+
     CPINFO info;
     if (::GetCPInfo(ret, &info) == 0)
         return -1;
@@ -1374,13 +1542,13 @@ extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding)
     return (long) ret;
 }
 
-extern long wxCharsetToCodepage(const wxChar *name)
+extern long wxCharsetToCodepage(const char *name)
 {
     // first get the font encoding for this charset
     if ( !name )
         return -1;
 
-    wxFontEncoding enc = wxFontMapper::Get()->CharsetToEncoding(name, false);
+    wxFontEncoding enc = wxFontMapperBase::Get()->CharsetToEncoding(name, false);
     if ( enc == wxFONTENCODING_SYSTEM )
         return -1;
 
@@ -1393,13 +1561,14 @@ extern long wxCharsetToCodepage(const wxChar *name)
 #include "wx/msw/registry.h"
 
 // this should work if Internet Exploiter is installed
-extern long wxCharsetToCodepage(const wxChar *name)
+extern long wxCharsetToCodepage(const char *name)
 {
     if (!name)
         return GetACP();
 
     long CP = -1;
 
+#if wxUSE_REGKEY
     wxString path(wxT("MIME\\Database\\Charset\\"));
     wxString cn(name);
 
@@ -1425,6 +1594,7 @@ extern long wxCharsetToCodepage(const wxChar *name)
             !key.QueryValue(wxT("AliasForCharset"), cn))
             break;
     }
+#endif // wxUSE_REGKEY
 
     return CP;
 }
@@ -1440,7 +1610,7 @@ extern long wxCharsetToCodepage(const wxChar *name)
   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 succesfully
+  NULL. classname is the desired wndclass classname. If function successfully
   registers the class, pclassname will be set to classname.
  */
 extern "C" WXDLLIMPEXP_BASE HWND
@@ -1489,4 +1659,3 @@ wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc)
 
     return hwnd;
 }
-