#include "wx/dynlib.h"
#include "wx/dynload.h"
#include "wx/scopeguard.h"
+#include "wx/filename.h"
#include "wx/confbase.h" // for wxExpandEnvVars()
#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
static const wxChar eUSERNAME[] = wxT("UserName");
#endif
+WXDLLIMPEXP_DATA_BASE(const wxChar *) wxUserResourceStr = wxT("TEXT");
+
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// 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) )
{
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)
// 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 *);
#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);
if ( !host.empty() )
{
- wxStrncpy(buf, host, maxSize);
+ wxStrlcpy(buf, host.c_str(), maxSize);
return true;
}
#if defined(__WXWINCE__)
// TODO-CE
return false;
-#elif defined(__WIN32__) && !defined(__WXMICROWIN__)
+#else
DWORD nSize = maxSize;
if ( ::GetUserName(buf, &nSize) == 0 )
{
}
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
}
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"));
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];
// Get the computer name of a DC for the domain.
if ( NetGetDCName( NULL, wszDomain, &ComputerName ) != NERR_Success )
{
- wxLogError(wxT("Can not find domain controller"));
+ wxLogError(wxT("Cannot find domain controller"));
goto error;
}
if ( !ok )
{
- wxStrncpy(buf, wxT("Unknown User"), maxSize);
+ wxStrlcpy(buf, wxT("Unknown User"), maxSize);
}
return true;
// 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."));
#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__)
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
GetDiskFreeSpaceEx_t
pGetDiskFreeSpaceEx = (GetDiskFreeSpaceEx_t)::GetProcAddress
(
- ::GetModuleHandle(_T("kernel32.dll")),
+ ::GetModuleHandle(wxT("kernel32.dll")),
#if wxUSE_UNICODE
"GetDiskFreeSpaceExW"
#else
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;
}
// 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;
}
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
if ( value )
{
- (void)::GetEnvironmentVariable(var.wx_str(),
+ (void)::GetEnvironmentVariable(var.t_str(),
wxStringBuffer(*value, dwRet),
dwRet);
}
#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__) || defined(__MINGW32__)
+ // notice that Microsoft _putenv() has different semantics from POSIX
+ // function with almost the same name: in particular it makes a copy of the
+ // string instead of using it as part of environment so we can safely call
+ // 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)
// 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
wxKillAllChildren(pid, sig, krc);
// get the process handle to operate on
- HANDLE hProcess = ::OpenProcess(SYNCHRONIZE |
- PROCESS_TERMINATE |
- PROCESS_QUERY_INFORMATION,
- FALSE, // not inheritable
- (DWORD)pid);
+ DWORD dwAccess = PROCESS_QUERY_INFORMATION | SYNCHRONIZE;
+ if ( sig == wxSIGKILL )
+ dwAccess |= PROCESS_TERMINATE;
+
+ HANDLE hProcess = ::OpenProcess(dwAccess, FALSE, (DWORD)pid);
if ( hProcess == NULL )
{
if ( krc )
wxON_BLOCK_EXIT1(::CloseHandle, hProcess);
+ // Default timeout for waiting for the process termination after killing
+ // it. It should be long enough to allow the process to terminate even on a
+ // busy system but short enough to avoid blocking the main thread for too
+ // long.
+ DWORD waitTimeout = 500; // ms
+
bool ok = true;
switch ( sig )
{
break;
case wxSIGNONE:
- // do nothing, we just want to test for process existence
- if ( krc )
- *krc = wxKILL_OK;
- return 0;
+ // Opening the process handle may succeed for a process even if it
+ // doesn't run any more (typically because open handles to it still
+ // exist elsewhere, possibly in this process itself if we're
+ // killing a child process) so we still need check if it hasn't
+ // terminated yet but, unlike when killing it, we don't need to
+ // wait for any time at all.
+ waitTimeout = 0;
+ break;
default:
// any other signal means "terminate"
// 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;
}
}
// the return code
- DWORD rc wxDUMMY_INITIALIZE(0);
if ( ok )
{
// as we wait for a short time, we can use just WaitForSingleObject()
// and not MsgWaitForMultipleObjects()
- switch ( ::WaitForSingleObject(hProcess, 500 /* msec */) )
+ switch ( ::WaitForSingleObject(hProcess, waitTimeout) )
{
case WAIT_OBJECT_0:
- // process terminated
- if ( !::GetExitCodeProcess(hProcess, &rc) )
+ // Process terminated: normally this indicates that we
+ // successfully killed it but when testing for the process
+ // existence, this means failure.
+ if ( sig == wxSIGNONE )
{
- wxLogLastError(_T("GetExitCodeProcess"));
+ if ( krc )
+ *krc = wxKILL_NO_PROCESS;
+
+ ok = false;
}
break;
default:
- wxFAIL_MSG( _T("unexpected WaitForSingleObject() return") );
+ wxFAIL_MSG( wxT("unexpected WaitForSingleObject() return") );
// fall through
case WAIT_FAILED:
- wxLogLastError(_T("WaitForSingleObject"));
+ wxLogLastError(wxT("WaitForSingleObject"));
// fall through
case WAIT_TIMEOUT:
- if ( krc )
- *krc = wxKILL_ERROR;
+ // Process didn't terminate: normally this is a failure but not
+ // when we're just testing for its existence.
+ if ( sig != wxSIGNONE )
+ {
+ if ( krc )
+ *krc = wxKILL_ERROR;
- rc = STILL_ACTIVE;
+ ok = false;
+ }
break;
}
}
// the return code is the same as from Unix kill(): 0 if killed
// successfully or -1 on error
- if ( !ok || rc == STILL_ACTIVE )
+ if ( !ok )
return -1;
if ( krc )
#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
// 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
}
}
// Shutdown or reboot the PC
-bool wxShutdown(wxShutdownFlags WXUNUSED_IN_WINCE(wFlags))
+bool wxShutdown(int WXUNUSED_IN_WINCE(flags))
{
#ifdef __WXWINCE__
// TODO-CE
TOKEN_PRIVILEGES tkp;
// Get the LUID for the shutdown privilege.
- ::LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
- &tkp.Privileges[0].Luid);
+ bOK = ::LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
+ &tkp.Privileges[0].Luid) != 0;
+
+ if ( bOK )
+ {
+ tkp.PrivilegeCount = 1; // one privilege to set
+ tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- tkp.PrivilegeCount = 1; // one privilege to set
- tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ // Get the shutdown privilege for this process.
+ ::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
+ (PTOKEN_PRIVILEGES)NULL, 0);
- // Get the shutdown privilege for this process.
- ::AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
- (PTOKEN_PRIVILEGES)NULL, 0);
+ // Cannot test the return value of AdjustTokenPrivileges.
+ bOK = ::GetLastError() == ERROR_SUCCESS;
+ }
- // Cannot test the return value of AdjustTokenPrivileges.
- bOK = ::GetLastError() == ERROR_SUCCESS;
+ ::CloseHandle(hToken);
}
}
if ( bOK )
{
- UINT flags = EWX_SHUTDOWN | EWX_FORCE;
- switch ( wFlags )
+ UINT wFlags = 0;
+ if ( flags & wxSHUTDOWN_FORCE )
+ {
+ wFlags = EWX_FORCE;
+ flags &= ~wxSHUTDOWN_FORCE;
+ }
+
+ switch ( flags )
{
case wxSHUTDOWN_POWEROFF:
- flags |= EWX_POWEROFF;
+ wFlags |= EWX_POWEROFF;
break;
case wxSHUTDOWN_REBOOT:
- flags |= EWX_REBOOT;
+ wFlags |= EWX_REBOOT;
+ break;
+
+ case wxSHUTDOWN_LOGOFF:
+ wFlags |= EWX_LOGOFF;
break;
default:
- wxFAIL_MSG( _T("unknown wxShutdown() flag") );
+ wxFAIL_MSG( wxT("unknown wxShutdown() flag") );
return false;
}
- bOK = ::ExitWindowsEx(flags, 0) != 0;
+ bOK = ::ExitWindowsEx(wFlags, 0) != 0;
}
return bOK;
-#endif // Win32/16
+#endif // WinCE/!WinCE
}
// ----------------------------------------------------------------------------
{
#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;
}
if ( !wxIsEmpty(info.szCSDVersion) )
{
- str << _T(" (") << info.szCSDVersion << _T(')');
+ str << wxT(" (") << info.szCSDVersion << wxT(')');
}
break;
info.dwBuildNumber);
break;
+ case 2:
+ // we can't distinguish between XP 64 and 2003
+ // as they both are 5.2, so examine the product
+ // type to resolve this ambiguity
+ if ( wxIsWindowsServer() == 1 )
+ {
+ str.Printf(_("Windows Server 2003 (build %lu"),
+ info.dwBuildNumber);
+ break;
+ }
+ //else: must be XP, fall through
+
case 1:
str.Printf(_("Windows XP (build %lu"),
info.dwBuildNumber);
break;
-
- case 2:
- str.Printf(_("Windows Server 2003 (build %lu"),
- info.dwBuildNumber);
- break;
}
break;
if ( !wxIsEmpty(info.szCSDVersion) )
{
- str << _T(", ") << info.szCSDVersion;
+ str << wxT(", ") << info.szCSDVersion;
}
- str << _T(')');
+ str << wxT(')');
if ( wxIsPlatform64Bit() )
str << _(", 64-bit edition");
}
else
{
- wxFAIL_MSG( _T("GetVersionEx() failed") ); // should never happen
+ wxFAIL_MSG( wxT("GetVersionEx() failed") ); // should never happen
}
return str;
// 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 )
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 )