X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f07dc2e2a71f2c9dc9886a67e834a1b12a14df47..4f433feff9251ded00bba26b633f93e660cd44c4:/src/msw/utils.cpp diff --git a/src/msw/utils.cpp b/src/msw/utils.cpp index aec073c7e5..d0a591dab4 100644 --- a/src/msw/utils.cpp +++ b/src/msw/utils.cpp @@ -32,11 +32,22 @@ #endif //WX_PRECOMP #include "wx/apptrait.h" +#include "wx/dynlib.h" +#include "wx/dynload.h" + +#include "wx/confbase.h" // for wxExpandEnvVars() #include "wx/msw/private.h" // includes #include "wx/msw/missing.h" // CHARSET_HANGUL -#ifdef __GNUWIN32_OLD__ +#if defined(__CYGWIN__) + //CYGWIN gives annoying warning about runtime stuff if we don't do this +# define USE_SYS_TYPES_FD_SET +# include +#endif + +// 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 @@ -90,13 +101,8 @@ #endif #endif -// ---------------------------------------------------------------------------- -// module globals -// ---------------------------------------------------------------------------- - -#if wxUSE_ON_FATAL_EXCEPTION - static bool gs_handleExceptions = FALSE; -#endif +// For wxKillAllChildren +#include // ---------------------------------------------------------------------------- // constants @@ -106,12 +112,6 @@ static const wxChar WX_SECTION[] = wxT("wxWindows"); static const wxChar eUSERNAME[] = wxT("UserName"); -// these are only used under Win16 -#if !defined(__WIN32__) && !defined(__WXMICROWIN__) -static const wxChar eHOSTNAME[] = wxT("HostName"); -static const wxChar eUSERID[] = wxT("UserId"); -#endif // !Win32 - // ============================================================================ // implementation // ============================================================================ @@ -124,17 +124,20 @@ static const wxChar eUSERID[] = wxT("UserId"); bool wxGetHostName(wxChar *buf, int maxSize) { #if defined(__WXWINCE__) - return FALSE; + // TODO-CE + wxUnusedVar(buf); + wxUnusedVar(maxSize); + return false; #elif defined(__WIN32__) && !defined(__WXMICROWIN__) DWORD nSize = maxSize; if ( !::GetComputerName(buf, &nSize) ) { wxLogLastError(wxT("GetComputerName")); - return FALSE; + return false; } - return TRUE; + return true; #else wxChar *sysname; const wxChar *default_host = wxT("noname"); @@ -144,60 +147,90 @@ bool wxGetHostName(wxChar *buf, int maxSize) } else wxStrncpy(buf, sysname, maxSize - 1); buf[maxSize] = wxT('\0'); - return *buf ? TRUE : FALSE; + return *buf ? true : false; #endif } // get full hostname (with domain name if possible) bool wxGetFullHostName(wxChar *buf, int maxSize) { -#if defined(__WIN32__) && !defined(__WXMICROWIN__) && ! (defined(__GNUWIN32__) && !defined(__MINGW32__)) +#if !defined( __WXMICROWIN__) && wxUSE_DYNAMIC_LOADER && wxUSE_SOCKETS // TODO should use GetComputerNameEx() when available - // the idea is that if someone had set wxUSE_SOCKETS to 0 the code - // shouldn't use winsock.dll (a.k.a. ws2_32.dll) at all so only use this - // code if we link with it anyhow -#if wxUSE_SOCKETS + // we don't want to always link with Winsock DLL as we might not use it at + // all, so load it dynamically here if needed (and don't complain if it is + // missing, we handle this) + wxLogNull noLog; - WSADATA wsa; - if ( WSAStartup(MAKEWORD(1, 1), &wsa) == 0 ) + wxDynamicLibrary dllWinsock(_T("ws2_32.dll"), wxDL_VERBATIM); + if ( dllWinsock.IsLoaded() ) { - wxString host; - char bufA[256]; - if ( gethostname(bufA, WXSIZEOF(bufA)) == 0 ) + typedef int (PASCAL *WSAStartup_t)(WORD, WSADATA *); + typedef int (PASCAL *gethostname_t)(char *, int); + typedef hostent* (PASCAL *gethostbyname_t)(const char *); + typedef hostent* (PASCAL *gethostbyaddr_t)(const char *, int , int); + typedef int (PASCAL *WSACleanup_t)(void); + + #define LOAD_WINSOCK_FUNC(func) \ + func ## _t \ + pfn ## func = (func ## _t)dllWinsock.GetSymbol(_T(#func)) + + LOAD_WINSOCK_FUNC(WSAStartup); + + WSADATA wsa; + if ( pfnWSAStartup && pfnWSAStartup(MAKEWORD(1, 1), &wsa) == 0 ) { - // gethostname() won't usually include the DNS domain name, for - // this we need to work a bit more - if ( !strchr(bufA, '.') ) - { - struct hostent *pHostEnt = gethostbyname(bufA); + LOAD_WINSOCK_FUNC(gethostname); - if ( pHostEnt ) + wxString host; + if ( pfngethostname ) + { + char bufA[256]; + if ( pfngethostname(bufA, WXSIZEOF(bufA)) == 0 ) { - // Windows will use DNS internally now - pHostEnt = gethostbyaddr(pHostEnt->h_addr, 4, AF_INET); - } + // gethostname() won't usually include the DNS domain name, + // for this we need to work a bit more + if ( !strchr(bufA, '.') ) + { + LOAD_WINSOCK_FUNC(gethostbyname); - if ( pHostEnt ) - { - host = wxString::FromAscii(pHostEnt->h_name); + struct hostent *pHostEnt = pfngethostbyname + ? pfngethostbyname(bufA) + : NULL; + + if ( pHostEnt ) + { + // Windows will use DNS internally now + LOAD_WINSOCK_FUNC(gethostbyaddr); + + pHostEnt = pfngethostbyaddr + ? pfngethostbyaddr(pHostEnt->h_addr, + 4, AF_INET) + : NULL; + } + + if ( pHostEnt ) + { + host = wxString::FromAscii(pHostEnt->h_name); + } + } } } - } - WSACleanup(); + LOAD_WINSOCK_FUNC(WSACleanup); + if ( pfnWSACleanup ) + pfnWSACleanup(); - if ( !host.empty() ) - { - wxStrncpy(buf, host, maxSize); - return TRUE; + if ( !host.empty() ) + { + wxStrncpy(buf, host, maxSize); + + return true; + } } } - -#endif // wxUSE_SOCKETS - -#endif // Win32 +#endif // !__WXMICROWIN__ return wxGetHostName(buf, maxSize); } @@ -206,8 +239,11 @@ bool wxGetFullHostName(wxChar *buf, int maxSize) bool wxGetUserId(wxChar *buf, int maxSize) { #if defined(__WXWINCE__) - return FALSE; -#elif defined(__WIN32__) && !defined(__win32s__) && !defined(__WXMICROWIN__) + // TODO-CE + wxUnusedVar(buf); + wxUnusedVar(maxSize); + return false; +#elif defined(__WIN32__) && !defined(__WXMICROWIN__) DWORD nSize = maxSize; if ( ::GetUserName(buf, &nSize) == 0 ) { @@ -216,12 +252,12 @@ bool wxGetUserId(wxChar *buf, int maxSize) if ( res == 0 ) { // not found - return FALSE; + return false; } } - return TRUE; -#else // Win16 or Win32s + return true; +#else // __WXMICROWIN__ wxChar *user; const wxChar *default_id = wxT("anonymous"); @@ -230,7 +266,7 @@ bool wxGetUserId(wxChar *buf, int maxSize) if ( (user = wxGetenv(wxT("USER"))) == NULL && (user = wxGetenv(wxT("LOGNAME"))) == NULL ) { - // Use wxWindows configuration data (comming soon) + // Use wxWidgets configuration data (comming soon) GetProfileString(WX_SECTION, eUSERID, default_id, buf, maxSize - 1); } else @@ -238,7 +274,7 @@ bool wxGetUserId(wxChar *buf, int maxSize) wxStrncpy(buf, user, maxSize - 1); } - return *buf ? TRUE : FALSE; + return *buf ? true : false; #endif } @@ -246,11 +282,14 @@ bool wxGetUserId(wxChar *buf, int maxSize) bool wxGetUserName(wxChar *buf, int maxSize) { #if defined(__WXWINCE__) - return FALSE; + // TODO-CE + wxUnusedVar(buf); + wxUnusedVar(maxSize); + return false; #elif defined(USE_NET_API) CHAR szUserName[256]; if ( !wxGetUserId(szUserName, WXSIZEOF(szUserName)) ) - return FALSE; + return false; // TODO how to get the domain name? CHAR *szDomain = ""; @@ -307,15 +346,15 @@ bool wxGetUserName(wxChar *buf, int maxSize) WideCharToMultiByte( CP_ACP, 0, ui2->usri2_full_name, -1, buf, maxSize, NULL, NULL ); - return TRUE; + return true; error: wxLogError(wxT("Couldn't look up full user name.")); - return FALSE; + return false; #else // !USE_NET_API // Could use NIS, MS-Mail or other site specific programs - // Use wxWindows configuration data + // Use wxWidgets configuration data bool ok = GetProfileString(WX_SECTION, eUSERNAME, wxEmptyString, buf, maxSize - 1) != 0; if ( !ok ) { @@ -326,15 +365,16 @@ error: { wxStrncpy(buf, wxT("Unknown User"), maxSize); } -#endif // Win32/16 - return TRUE; + return true; +#endif // Win32/16 } const wxChar* wxGetHomeDir(wxString *pstr) { - wxString& strDir = *pstr; + wxString& strDir = *pstr; + // first branch is for Cygwin #if defined(__UNIX__) const wxChar *szHome = wxGetenv("HOME"); if ( szHome == NULL ) { @@ -350,34 +390,33 @@ const wxChar* wxGetHomeDir(wxString *pstr) strDir << wxT('/'); #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); - strDir = windowsPath; + // Cygwin returns unix type path but that does not work well + static wxChar windowsPath[MAX_PATH]; + cygwin_conv_to_full_win32_path(strDir, windowsPath); + strDir = windowsPath; #endif #elif defined(__WXWINCE__) - // Nothing + strDir = wxT("\\"); #else - #ifdef __WIN32__ - strDir.clear(); + strDir.clear(); - // If we have a valid HOME directory, as is used on many machines that - // have unix utilities on them, we should use that. - const wxChar *szHome = wxGetenv(wxT("HOME")); + // If we have a valid HOME directory, as is used on many machines that + // have unix utilities on them, we should use that. + const wxChar *szHome = wxGetenv(wxT("HOME")); - if ( szHome != NULL ) - { + if ( szHome != NULL ) + { strDir = szHome; - } - else // no HOME, try HOMEDRIVE/PATH - { - szHome = wxGetenv(wxT("HOMEDRIVE")); - if ( szHome != NULL ) + } + else // no HOME, try HOMEDRIVE/PATH + { + szHome = wxGetenv(wxT("HOMEDRIVE")); + if ( szHome != NULL ) strDir << szHome; - szHome = wxGetenv(wxT("HOMEPATH")); + szHome = wxGetenv(wxT("HOMEPATH")); - if ( szHome != NULL ) - { + if ( szHome != NULL ) + { strDir << szHome; // the idea is that under NT these variables have default values @@ -387,45 +426,34 @@ const wxChar* wxGetHomeDir(wxString *pstr) // to set HOMEPATH to something other than "\\", we suppose that he // knows what he is doing and use the supplied value. if ( wxStrcmp(szHome, wxT("\\")) == 0 ) - strDir.clear(); - } - } + strDir.clear(); + } + } - if ( strDir.empty() ) - { - // If we have a valid USERPROFILE directory, as is the case in - // Windows NT, 2000 and XP, we should use that as our home directory. - szHome = wxGetenv(wxT("USERPROFILE")); + if ( strDir.empty() ) + { + // If we have a valid USERPROFILE directory, as is the case in + // Windows NT, 2000 and XP, we should use that as our home directory. + szHome = wxGetenv(wxT("USERPROFILE")); - if ( szHome != NULL ) + if ( szHome != NULL ) strDir = szHome; - } - - if ( !strDir.empty() ) - { - return strDir.c_str(); - } - //else: fall back to the prograrm directory - #else // Win16 - // Win16 has no idea about home, so use the executable directory instead - #endif // WIN16/32 - - // 260 was taken from windef.h - #ifndef MAX_PATH - #define MAX_PATH 260 - #endif - - wxString strPath; - ::GetModuleFileName(::GetModuleHandle(NULL), - strPath.GetWriteBuf(MAX_PATH), MAX_PATH); - strPath.UngetWriteBuf(); - - // extract the dir name - wxSplitPath(strPath, &strDir, NULL, NULL); + } + if ( !strDir.empty() ) + { + // sometimes the value of HOME may be "%USERPROFILE%", so reexpand the + // value once again, it shouldn't hurt anyhow + strDir = wxExpandEnvVars(strDir); + } + else // fall back to the program directory + { + // extract the directory component of the program file name + wxSplitPath(wxGetFullModuleName(), &strDir, NULL, NULL); + } #endif // UNIX/Win - return strDir.c_str(); + return strDir.c_str(); } wxChar *wxGetUserHome(const wxString& WXUNUSED(user)) @@ -438,39 +466,17 @@ wxChar *wxGetUserHome(const wxString& WXUNUSED(user)) return (wxChar *)wxGetHomeDir(&s_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)); -#else // Win16 - #ifdef __BORLANDC__ - struct ffblk fileInfo; - #else - struct find_t fileInfo; - #endif - // In Borland findfirst has a different argument - // ordering from _dos_findfirst. But _dos_findfirst - // _should_ be ok in both MS and Borland... why not? - #ifdef __BORLANDC__ - return (findfirst(dir, &fileInfo, _A_SUBDIR) == 0 && - (fileInfo.ff_attrib & _A_SUBDIR) != 0); - #else - return (_dos_findfirst(dir, _A_SUBDIR, &fileInfo) == 0) && - ((fileInfo.attrib & _A_SUBDIR) != 0); - #endif -#endif // Win32/16 -} - bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) { #ifdef __WXWINCE__ - return FALSE; + // TODO-CE + wxUnusedVar(path); + wxUnusedVar(pTotal); + wxUnusedVar(pFree); + return false; #else if ( path.empty() ) - return FALSE; + return false; // old w32api don't have ULARGE_INTEGER #if defined(__WIN32__) && \ @@ -505,7 +511,7 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) { wxLogLastError(_T("GetDiskFreeSpaceEx")); - return FALSE; + return false; } // ULARGE_INTEGER is a union of a 64 bit value and a struct containing @@ -548,7 +554,7 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) { wxLogLastError(_T("GetDiskFreeSpace")); - return FALSE; + return false; } wxLongLong lBytesPerCluster = lSectorsPerCluster; @@ -567,7 +573,7 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) } } - return TRUE; + return true; #endif // __WXWINCE__ } @@ -579,35 +585,27 @@ bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree) bool wxGetEnv(const wxString& var, wxString *value) { #ifdef __WXWINCE__ - return FALSE; -#elif defined(__WIN16__) - const wxChar* ret = wxGetenv(var); - if ( !ret ) - return FALSE; - - if ( value ) - { - *value = ret; - } - - return TRUE; + // no environment variables under CE + wxUnusedVar(var); + wxUnusedVar(value); + return false; #else // Win32 // first get the size of the buffer DWORD dwRet = ::GetEnvironmentVariable(var, NULL, 0); if ( !dwRet ) { // this means that there is no such variable - return FALSE; + return false; } if ( value ) { - (void)::GetEnvironmentVariable(var, value->GetWriteBuf(dwRet), dwRet); - value->UngetWriteBuf(); + (void)::GetEnvironmentVariable(var, wxStringBuffer(*value, dwRet), + dwRet); } - return TRUE; -#endif // Win16/32 + return true; +#endif // WinCE/32 } bool wxSetEnv(const wxString& var, const wxChar *value) @@ -619,12 +617,15 @@ bool wxSetEnv(const wxString& var, const wxChar *value) { wxLogLastError(_T("SetEnvironmentVariable")); - return FALSE; + return false; } - return TRUE; + return true; #else // no way to set env vars - return FALSE; + // no environment variables under CE + wxUnusedVar(var); + wxUnusedVar(value); + return false; #endif } @@ -667,8 +668,13 @@ BOOL CALLBACK wxEnumFindByPidProc(HWND hwnd, LPARAM lParam) return TRUE; } -int wxKill(long pid, wxSignal sig, wxKillError *krc) +int wxKillAllChildren(long pid, wxSignal sig, wxKillError *krc); + +int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags) { + if (flags & wxKILL_CHILDREN) + wxKillAllChildren(pid, sig, krc); + // get the process handle to operate on HANDLE hProcess = ::OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE | @@ -692,7 +698,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc) return -1; } - bool ok = TRUE; + bool ok = true; switch ( sig ) { case wxSIGKILL: @@ -708,7 +714,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc) *krc = wxKILL_ERROR; } - ok = FALSE; + ok = false; } break; @@ -723,7 +729,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc) 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)¶ms) ) { @@ -732,7 +738,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc) { // 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) @@ -745,7 +751,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc) { wxLogLastError(_T("EnumWindows")); - ok = FALSE; + ok = false; } } else // no windows for this PID @@ -755,7 +761,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc) *krc = wxKILL_ERROR; } - ok = FALSE; + ok = false; } } } @@ -823,17 +829,124 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc) return -1; } +HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD) ; +BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32) ; +BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32) ; + +static void InitToolHelp32() +{ + static bool s_initToolHelpDone = false; + + if (s_initToolHelpDone) + return; + + s_initToolHelpDone = true; + + lpfCreateToolhelp32Snapshot = NULL; + lpfProcess32First = NULL; + lpfProcess32Next = NULL; + + HINSTANCE hInstLib = LoadLibrary( wxT("Kernel32.DLL") ) ; + if( hInstLib == NULL ) + return ; + + // Get procedure addresses. + // We are linking to these functions of Kernel32 + // explicitly, because otherwise a module using + // 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 + ) ; + + lpfProcess32First= + (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32)) + GetProcAddress( hInstLib, +#ifdef __WXWINCE__ + wxT("Process32First") +#else + "Process32First" +#endif + ) ; + + lpfProcess32Next= + (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32)) + GetProcAddress( hInstLib, +#ifdef __WXWINCE__ + wxT("Process32Next") +#else + "Process32Next" +#endif + ) ; + + FreeLibrary( hInstLib ) ; +} + +// By John Skiff +int wxKillAllChildren(long pid, wxSignal sig, wxKillError *krc) +{ + InitToolHelp32(); + + if (krc) + *krc = wxKILL_OK; + + // If not implemented for this platform (e.g. NT 4.0), silently ignore + if (!lpfCreateToolhelp32Snapshot || !lpfProcess32First || !lpfProcess32Next) + return 0; + + // Take a snapshot of all processes in the system. + HANDLE hProcessSnap = lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hProcessSnap == INVALID_HANDLE_VALUE) { + if (krc) + *krc = wxKILL_ERROR; + return -1; + } + + //Fill in the size of the structure before using it. + PROCESSENTRY32 pe; + wxZeroMemory(pe); + pe.dwSize = sizeof(PROCESSENTRY32); + + // Walk the snapshot of the processes, and for each process, + // kill it if its parent is pid. + if (!lpfProcess32First(hProcessSnap, &pe)) { + // Can't get first process. + if (krc) + *krc = wxKILL_ERROR; + CloseHandle (hProcessSnap); + return -1; + } + + do { + if (pe.th32ParentProcessID == (DWORD) pid) { + if (wxKill(pe.th32ProcessID, sig, krc)) + return -1; + } + } while (lpfProcess32Next (hProcessSnap, &pe)); + + + return 0; +} + // Execute a program in an Interactive Shell bool wxShell(const wxString& command) { + wxString cmd; + #ifdef __WXWINCE__ - return FALSE; + cmd = command; #else wxChar *shell = wxGetenv(wxT("COMSPEC")); if ( !shell ) shell = (wxChar*) wxT("\\COMMAND.COM"); - wxString cmd; if ( !command ) { // just the shell @@ -844,18 +957,20 @@ bool wxShell(const wxString& command) // pass the command to execute to the command processor cmd.Printf(wxT("%s /c %s"), shell, command.c_str()); } +#endif return wxExecute(cmd, wxEXEC_SYNC) == 0; -#endif } // Shutdown or reboot the PC bool wxShutdown(wxShutdownFlags wFlags) { #ifdef __WXWINCE__ - return FALSE; + // TODO-CE + wxUnusedVar(wFlags); + return false; #elif defined(__WIN32__) - bool bOK = TRUE; + bool bOK = true; if ( wxGetOsVersion(NULL, NULL) == wxWINDOWS_NT ) // if is NT or 2K { @@ -899,42 +1014,51 @@ bool wxShutdown(wxShutdownFlags wFlags) default: wxFAIL_MSG( _T("unknown wxShutdown() flag") ); - return FALSE; + return false; } - bOK = ::ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE | EWX_REBOOT, 0) != 0; + bOK = ::ExitWindowsEx(flags, 0) != 0; } return bOK; -#else // Win16 - return FALSE; #endif // Win32/16 } +wxPowerType wxGetPowerType() +{ + // TODO + return wxPOWER_UNKNOWN; +} + +wxBatteryState wxGetBatteryState() +{ + // TODO + return wxBATTERY_UNKNOWN_STATE; +} + // ---------------------------------------------------------------------------- // misc // ---------------------------------------------------------------------------- // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX) -long wxGetFreeMemory() +wxMemorySize wxGetFreeMemory() { -#if defined(__WIN32__) && !defined(__BORLANDC__) +#if defined(__WIN64__) + MEMORYSTATUSEX memStatex; + memStatex.dwLength = sizeof (memStatex); + ::GlobalMemoryStatusEx (&memStatex); + return (wxMemorySize)memStatex.ullAvailPhys; +#else /* if defined(__WIN32__) */ MEMORYSTATUS memStatus; memStatus.dwLength = sizeof(MEMORYSTATUS); - GlobalMemoryStatus(&memStatus); - return memStatus.dwAvailPhys; -#else - return (long)GetFreeSpace(0); + ::GlobalMemoryStatus(&memStatus); + return (wxMemorySize)memStatus.dwAvailPhys; #endif } unsigned long wxGetProcessId() { -#ifdef __WIN32__ return ::GetCurrentProcessId(); -#else - return 0; -#endif } // Emit a beeeeeep @@ -943,9 +1067,27 @@ void wxBell() ::MessageBeep((UINT)-1); // default sound } +bool wxIsDebuggerRunning() +{ + // IsDebuggerPresent() is not available under Win95, so load it dynamically + wxDynamicLibrary dll(_T("kernel32.dll"), wxDL_VERBATIM); + + typedef BOOL (WINAPI *IsDebuggerPresent_t)(); + if ( !dll.HasSymbol(_T("IsDebuggerPresent")) ) + { + // no way to know, assume no + return false; + } + + return (*(IsDebuggerPresent_t)dll.GetSymbol(_T("IsDebuggerPresent")))() != 0; +} + +// ---------------------------------------------------------------------------- +// OS version +// ---------------------------------------------------------------------------- + wxString wxGetOsDescription() { -#ifdef __WIN32__ wxString str; OSVERSIONINFO info; @@ -961,8 +1103,39 @@ wxString wxGetOsDescription() break; case VER_PLATFORM_WIN32_WINDOWS: - str.Printf(_("Windows 9%c"), - info.dwMinorVersion == 0 ? _T('5') : _T('8')); + switch (info.dwMinorVersion) + { + case 0: + if ( info.szCSDVersion[1] == 'B' || + info.szCSDVersion[1] == 'C' ) + { + str = _("Windows 95 OSR2"); + } + else + { + str = _("Windows 95"); + } + break; + case 10: + if ( info.szCSDVersion[1] == 'B' || + info.szCSDVersion[1] == 'C' ) + { + str = _("Windows 98 SE"); + } + else + { + str = _("Windows 98"); + } + break; + case 90: + str = _("Windows ME"); + break; + default: + str.Printf(_("Windows 9x (%d.%d)"), + info.dwMajorVersion, + info.dwMinorVersion); + break; + } if ( !wxIsEmpty(info.szCSDVersion) ) { str << _T(" (") << info.szCSDVersion << _T(')'); @@ -970,10 +1143,31 @@ wxString wxGetOsDescription() break; case VER_PLATFORM_WIN32_NT: - str.Printf(_T("Windows NT %lu.%lu (build %lu"), + if ( info.dwMajorVersion == 5 ) + { + 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"), + info.dwBuildNumber); + break; + } + } + if ( wxIsEmpty(str) ) + { + str.Printf(_("Windows NT %lu.%lu (build %lu"), info.dwMajorVersion, info.dwMinorVersion, info.dwBuildNumber); + } if ( !wxIsEmpty(info.szCSDVersion) ) { str << _T(", ") << info.szCSDVersion; @@ -988,12 +1182,9 @@ wxString wxGetOsDescription() } return str; -#else // Win16 - return _("Windows 3.1"); -#endif // Win32/16 } -int wxAppTraits::GetOSVersion(int *verMaj, int *verMin) +wxToolkitInfo& wxAppTraits::GetToolkitInfo() { // cache the version info, it's not going to change // @@ -1015,6 +1206,11 @@ int wxAppTraits::GetOSVersion(int *verMaj, int *verMin) s_major = info.dwMajorVersion; s_minor = info.dwMinorVersion; +#ifdef __SMARTPHONE__ + s_ver = wxWINDOWS_SMARTPHONE; +#elif defined(__POCKETPC__) + s_ver = wxWINDOWS_POCKETPC; +#else switch ( info.dwPlatformId ) { case VER_PLATFORM_WIN32s: @@ -1028,34 +1224,40 @@ int wxAppTraits::GetOSVersion(int *verMaj, int *verMin) case VER_PLATFORM_WIN32_NT: s_ver = wxWINDOWS_NT; break; - +#ifdef __WXWINCE__ case VER_PLATFORM_WIN32_CE: s_ver = wxWINDOWS_CE; - break; +#endif } +#endif } } - if ( verMaj ) - *verMaj = s_major; - if ( verMin ) - *verMin = s_minor; - - return s_ver; + static wxToolkitInfo info; + info.versionMajor = s_major; + info.versionMinor = s_minor; + info.os = s_ver; + info.name = _T("wxBase"); + return info; } // ---------------------------------------------------------------------------- // sleep functions // ---------------------------------------------------------------------------- -void wxUsleep(unsigned long milliseconds) +void wxMilliSleep(unsigned long milliseconds) { ::Sleep(milliseconds); } +void wxMicroSleep(unsigned long microseconds) +{ + wxMilliSleep(microseconds/1000); +} + void wxSleep(int nSecs) { - wxUsleep(1000*nSecs); + wxMilliSleep(1000*nSecs); } // ---------------------------------------------------------------------------- @@ -1084,8 +1286,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; @@ -1135,23 +1339,77 @@ extern WXDLLIMPEXP_BASE long wxEncodingToCharset(wxFontEncoding encoding) extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding) { - // translate encoding into the Windows CHARSET - long charset = wxEncodingToCharset(encoding); - if ( charset == -1 ) - return -1; + // There don't seem to be symbolic names for + // these under Windows so I just copied the + // values from MSDN. + + unsigned int ret; - // translate CHARSET to code page - CHARSETINFO csetInfo; - if ( !::TranslateCharsetInfo((DWORD *)(DWORD)charset, - &csetInfo, - TCI_SRCCHARSET) ) + switch (encoding) { - wxLogLastError(_T("TranslateCharsetInfo(TCI_SRCCHARSET)")); + case wxFONTENCODING_ISO8859_1: ret = 28591; break; + case wxFONTENCODING_ISO8859_2: ret = 28592; break; + case wxFONTENCODING_ISO8859_3: ret = 28593; break; + case wxFONTENCODING_ISO8859_4: ret = 28594; break; + case wxFONTENCODING_ISO8859_5: ret = 28595; break; + case wxFONTENCODING_ISO8859_6: ret = 28596; break; + case wxFONTENCODING_ISO8859_7: ret = 28597; break; + 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_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_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; + case wxFONTENCODING_CP855: ret = 855; break; + case wxFONTENCODING_CP866: ret = 866; break; + case wxFONTENCODING_CP874: ret = 874; break; + case wxFONTENCODING_CP932: ret = 932; break; + case wxFONTENCODING_CP936: ret = 936; break; + case wxFONTENCODING_CP949: ret = 949; break; + case wxFONTENCODING_CP950: ret = 950; break; + case wxFONTENCODING_CP1250: ret = 1250; break; + case wxFONTENCODING_CP1251: ret = 1251; break; + case wxFONTENCODING_CP1252: ret = 1252; break; + case wxFONTENCODING_CP1253: ret = 1253; break; + case wxFONTENCODING_CP1254: ret = 1254; break; + case wxFONTENCODING_CP1255: ret = 1255; break; + case wxFONTENCODING_CP1256: ret = 1256; break; + case wxFONTENCODING_CP1257: ret = 1257; 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; + case wxFONTENCODING_MACKOREAN: ret = 10003; break; + case wxFONTENCODING_MACARABIC: ret = 10004; break; + case wxFONTENCODING_MACHEBREW: ret = 10005; break; + case wxFONTENCODING_MACGREEK: ret = 10006; break; + case wxFONTENCODING_MACCYRILLIC: ret = 10007; break; + case wxFONTENCODING_MACTHAI: ret = 10021; break; + case wxFONTENCODING_MACCHINESESIMP: ret = 10008; break; + case wxFONTENCODING_MACCENTRALEUR: ret = 10029; break; + case wxFONTENCODING_MACCROATIAN: ret = 10082; break; + case wxFONTENCODING_MACICELANDIC: ret = 10079; break; + case wxFONTENCODING_MACROMANIAN: ret = 10009; 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; - } - return csetInfo.ciACP; + return (long) ret; } extern long wxCharsetToCodepage(const wxChar *name) @@ -1160,7 +1418,7 @@ extern long wxCharsetToCodepage(const wxChar *name) if ( !name ) return -1; - wxFontEncoding enc = wxFontMapper::Get()->CharsetToEncoding(name, FALSE); + wxFontEncoding enc = wxFontMapperBase::Get()->CharsetToEncoding(name, false); if ( enc == wxFONTENCODING_SYSTEM ) return -1; @@ -1211,40 +1469,62 @@ extern long wxCharsetToCodepage(const wxChar *name) #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP -// ---------------------------------------------------------------------------- -// wxApp::OnFatalException() support -// ---------------------------------------------------------------------------- - -bool wxHandleFatalExceptions(bool doit) +/* + 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) { -#if wxUSE_ON_FATAL_EXCEPTION - // assume this can only be called from the main thread - gs_handleExceptions = doit; + wxCHECK_MSG( classname && pclassname && wndproc, NULL, + _T("NULL parameter in wxCreateHiddenWindow") ); - return TRUE; -#else - wxFAIL_MSG(_T("set wxUSE_ON_FATAL_EXCEPTION to 1 to use this function")); + // register the class fi we need to first + if ( *pclassname == NULL ) + { + WNDCLASS wndclass; + wxZeroMemory(wndclass); - (void)doit; - return FALSE; -#endif -} + wndclass.lpfnWndProc = wndproc; + wndclass.hInstance = wxGetInstance(); + wndclass.lpszClassName = classname; -#if wxUSE_ON_FATAL_EXCEPTION + if ( !::RegisterClass(&wndclass) ) + { + wxLogLastError(wxT("RegisterClass() in wxCreateHiddenWindow")); -extern unsigned long wxGlobalSEHandler() -{ - if ( gs_handleExceptions && wxTheApp ) - { - // give the user a chance to do something special about this - wxTheApp->OnFatalException(); + return NULL; + } - // this will execute our handler and terminate the process - return EXCEPTION_EXECUTE_HANDLER; + *pclassname = classname; } - return EXCEPTION_CONTINUE_SEARCH; -} + // next create the window + HWND hwnd = ::CreateWindow + ( + *pclassname, + NULL, + 0, 0, 0, 0, + 0, + (HWND) NULL, + (HMENU)NULL, + wxGetInstance(), + (LPVOID) NULL + ); + + if ( !hwnd ) + { + wxLogLastError(wxT("CreateWindow() in wxCreateHiddenWindow")); + } -#endif // wxUSE_ON_FATAL_EXCEPTION + return hwnd; +}