utils.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,558 行 · 第 1/4 页
CPP
1,558 行
strDir = wxT(".");
}
else
strDir = szHome;
// add a trailing slash if needed
if ( strDir.Last() != wxT('/') )
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;
#endif
#elif defined(__WXWINCE__)
strDir = wxT("\\");
#else
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 ( szHome != NULL )
{
strDir = szHome;
}
else // no HOME, try HOMEDRIVE/PATH
{
szHome = wxGetenv(wxT("HOMEDRIVE"));
if ( szHome != NULL )
strDir << szHome;
szHome = wxGetenv(wxT("HOMEPATH"));
if ( szHome != NULL )
{
strDir << szHome;
// the idea is that under NT these variables have default values
// of "%systemdrive%:" and "\\". As we don't want to create our
// config files in the root directory of the system drive, we will
// create it in our program's dir. However, if the user took care
// 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();
}
}
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 )
strDir = szHome;
}
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();
}
wxChar *wxGetUserHome(const wxString& WXUNUSED(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;
return (wxChar *)wxGetHomeDir(&s_home);
}
bool wxGetDiskSpace(const wxString& WXUNUSED_IN_WINCE(path),
wxLongLong *WXUNUSED_IN_WINCE(pTotal),
wxLongLong *WXUNUSED_IN_WINCE(pFree))
{
#ifdef __WXWINCE__
// TODO-CE
return false;
#else
if ( path.empty() )
return false;
// old w32api don't have ULARGE_INTEGER
#if defined(__WIN32__) && \
(!defined(__GNUWIN32__) || wxCHECK_W32API_VERSION( 0, 3 ))
// GetDiskFreeSpaceEx() is not available under original Win95, check for
// it
typedef BOOL (WINAPI *GetDiskFreeSpaceEx_t)(LPCTSTR,
PULARGE_INTEGER,
PULARGE_INTEGER,
PULARGE_INTEGER);
GetDiskFreeSpaceEx_t
pGetDiskFreeSpaceEx = (GetDiskFreeSpaceEx_t)::GetProcAddress
(
::GetModuleHandle(_T("kernel32.dll")),
#if wxUSE_UNICODE
"GetDiskFreeSpaceExW"
#else
"GetDiskFreeSpaceExA"
#endif
);
if ( pGetDiskFreeSpaceEx )
{
ULARGE_INTEGER bytesFree, bytesTotal;
// may pass the path as is, GetDiskFreeSpaceEx() is smart enough
if ( !pGetDiskFreeSpaceEx(path,
&bytesFree,
&bytesTotal,
NULL) )
{
wxLogLastError(_T("GetDiskFreeSpaceEx"));
return false;
}
// ULARGE_INTEGER is a union of a 64 bit value and a struct containing
// two 32 bit fields which may be or may be not named - try to make it
// compile in all cases
#if defined(__BORLANDC__) && !defined(_ANONYMOUS_STRUCT)
#define UL(ul) ul.u
#else // anon union
#define UL(ul) ul
#endif
if ( pTotal )
{
*pTotal = wxLongLong(UL(bytesTotal).HighPart, UL(bytesTotal).LowPart);
}
if ( pFree )
{
*pFree = wxLongLong(UL(bytesFree).HighPart, UL(bytesFree).LowPart);
}
}
else
#endif // Win32
{
// there's a problem with drives larger than 2GB, GetDiskFreeSpaceEx()
// should be used instead - but if it's not available, fall back on
// GetDiskFreeSpace() nevertheless...
DWORD lSectorsPerCluster,
lBytesPerSector,
lNumberOfFreeClusters,
lTotalNumberOfClusters;
// FIXME: this is wrong, we should extract the root drive from path
// instead, but this is the job for wxFileName...
if ( !::GetDiskFreeSpace(path,
&lSectorsPerCluster,
&lBytesPerSector,
&lNumberOfFreeClusters,
&lTotalNumberOfClusters) )
{
wxLogLastError(_T("GetDiskFreeSpace"));
return false;
}
wxLongLong lBytesPerCluster = lSectorsPerCluster;
lBytesPerCluster *= lBytesPerSector;
if ( pTotal )
{
*pTotal = lBytesPerCluster;
*pTotal *= lTotalNumberOfClusters;
}
if ( pFree )
{
*pFree = lBytesPerCluster;
*pFree *= lNumberOfFreeClusters;
}
}
return true;
#endif
// __WXWINCE__
}
// ----------------------------------------------------------------------------
// env vars
// ----------------------------------------------------------------------------
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);
if ( !dwRet )
{
// this means that there is no such variable
return false;
}
if ( value )
{
(void)::GetEnvironmentVariable(var, wxStringBuffer(*value, dwRet),
dwRet);
}
return true;
#endif // WinCE/32
}
bool wxSetEnv(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
#ifdef __WXWINCE__
// no environment variables under CE
return false;
#else
if ( !::SetEnvironmentVariable(var, value) )
{
wxLogLastError(_T("SetEnvironmentVariable"));
return false;
}
return true;
#endif
}
// ----------------------------------------------------------------------------
// process management
// ----------------------------------------------------------------------------
// structure used to pass parameters from wxKill() to wxEnumFindByPidProc()
struct wxFindByPidParams
{
wxFindByPidParams() { hwnd = 0; pid = 0; }
// the HWND used to return the result
HWND hwnd;
// the PID we're looking from
DWORD pid;
DECLARE_NO_COPY_CLASS(wxFindByPidParams)
};
// wxKill helper: EnumWindows() callback which is used to find the first (top
// level) window belonging to the given process
BOOL CALLBACK wxEnumFindByPidProc(HWND hwnd, LPARAM lParam)
{
DWORD pid;
(void)::GetWindowThreadProcessId(hwnd, &pid);
wxFindByPidParams *params = (wxFindByPidParams *)lParam;
if ( pid == params->pid )
{
// remember the window we found
params->hwnd = hwnd;
// return FALSE to stop the enumeration
return FALSE;
}
// continue enumeration
return TRUE;
}
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 |
PROCESS_QUERY_INFORMATION,
FALSE, // not inheritable
(DWORD)pid);
if ( hProcess == NULL )
{
if ( krc )
{
// 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 )
{
case wxSIGKILL:
// kill the process forcefully returning -1 as error code
if ( !::TerminateProcess(hProcess, (UINT)-1) )
{
wxLogSysError(_("Failed to kill process %d"), pid);
if ( krc )
{
// this is not supposed to happen if we could open the
// process
*krc = wxKILL_ERROR;
}
ok = false;
}
break;
case wxSIGNONE:
// do nothing, we just want to test for process existence
if ( krc )
*krc = wxKILL_OK;
return 0;
default:
// any other signal means "terminate"
{
wxFindByPidParams params;
params.pid = (DWORD)pid;
// EnumWindows() has nice semantics: it returns 0 if it found
// something or if an error occurred and non zero if it
// enumerated all the window
if ( !::EnumWindows(wxEnumFindByPidProc, (LPARAM)¶ms) )
{
// did we find any window?
if ( params.hwnd )
{
// tell the app to close
//
// 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)
if ( !::PostMessage(params.hwnd, WM_QUIT, 0, 0) )
{
wxLogLastError(_T("PostMessage(WM_QUIT)"));
}
}
else // it was an error then
{
wxLogLastError(_T("EnumWindows"));
ok = false;
}
}
else // no windows for this PID
{
if ( krc )
*krc = wxKILL_ERROR;
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 */) )
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?