fixes+improvements from work (overhaul wutil, add convenience macros for DLL imports)
This was SVN commit r7717.
This commit is contained in:
parent
0c149cf447
commit
8c1bd05ab9
@ -206,4 +206,21 @@ bool IsAligned(T t, uintptr_t multiple)
|
|||||||
return ((uintptr_t)t % multiple) == 0;
|
return ((uintptr_t)t % multiple) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T MaxPowerOfTwoDivisor(T value)
|
||||||
|
{
|
||||||
|
debug_assert(value != T(0));
|
||||||
|
|
||||||
|
for(size_t log2 = 0; log2 < sizeof(T)*CHAR_BIT; log2++)
|
||||||
|
{
|
||||||
|
if(IsBitSet(value, log2))
|
||||||
|
return T(1) << log2;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_assert(0); // unreachable (!= 0 => there is a set bit)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // #ifndef INCLUDED_BITS
|
#endif // #ifndef INCLUDED_BITS
|
||||||
|
@ -247,7 +247,7 @@ again:
|
|||||||
// initializer returns pthread_mutex_t directly and CRITICAL_SECTIONS
|
// initializer returns pthread_mutex_t directly and CRITICAL_SECTIONS
|
||||||
// shouldn't be copied.
|
// shouldn't be copied.
|
||||||
//
|
//
|
||||||
// note: we use win_alloc instead of new because the (no longer extant)
|
// note: we use wutil_Allocate instead of new because the (no longer extant)
|
||||||
// memory manager used a pthread_mutex.
|
// memory manager used a pthread_mutex.
|
||||||
|
|
||||||
static CRITICAL_SECTION* CRITICAL_SECTION_from_pthread_mutex_t(pthread_mutex_t* m)
|
static CRITICAL_SECTION* CRITICAL_SECTION_from_pthread_mutex_t(pthread_mutex_t* m)
|
||||||
@ -262,7 +262,7 @@ static CRITICAL_SECTION* CRITICAL_SECTION_from_pthread_mutex_t(pthread_mutex_t*
|
|||||||
|
|
||||||
pthread_mutex_t pthread_mutex_initializer()
|
pthread_mutex_t pthread_mutex_initializer()
|
||||||
{
|
{
|
||||||
CRITICAL_SECTION* cs = (CRITICAL_SECTION*)win_alloc(sizeof(CRITICAL_SECTION));
|
CRITICAL_SECTION* cs = (CRITICAL_SECTION*)wutil_Allocate(sizeof(CRITICAL_SECTION));
|
||||||
InitializeCriticalSection(cs);
|
InitializeCriticalSection(cs);
|
||||||
return (pthread_mutex_t)cs;
|
return (pthread_mutex_t)cs;
|
||||||
}
|
}
|
||||||
@ -273,7 +273,7 @@ int pthread_mutex_destroy(pthread_mutex_t* m)
|
|||||||
if(!cs)
|
if(!cs)
|
||||||
return -1;
|
return -1;
|
||||||
DeleteCriticalSection(cs);
|
DeleteCriticalSection(cs);
|
||||||
win_free(cs);
|
wutil_Free(cs);
|
||||||
*m = 0; // cause double-frees to be noticed
|
*m = 0; // cause double-frees to be noticed
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -546,7 +546,7 @@ int sem_msgwait_np(sem_t* sem)
|
|||||||
// - a local variable in pthread_create isn't safe because the
|
// - a local variable in pthread_create isn't safe because the
|
||||||
// new thread might not start before pthread_create returns.
|
// new thread might not start before pthread_create returns.
|
||||||
// - using one static FuncAndArg protected by critical section doesn't
|
// - using one static FuncAndArg protected by critical section doesn't
|
||||||
// work. win_lock allows recursive locking, so if creating 2 threads,
|
// work. wutil_Lock allows recursive locking, so if creating 2 threads,
|
||||||
// the parent thread may create both without being stopped and thus
|
// the parent thread may create both without being stopped and thus
|
||||||
// stomp on the first thread's func_and_arg.
|
// stomp on the first thread's func_and_arg.
|
||||||
// - blocking pthread_create until the trampoline has latched func_and_arg
|
// - blocking pthread_create until the trampoline has latched func_and_arg
|
||||||
@ -572,7 +572,7 @@ static unsigned __stdcall thread_start(void* param)
|
|||||||
const FuncAndArg* func_and_arg = (const FuncAndArg*)param;
|
const FuncAndArg* func_and_arg = (const FuncAndArg*)param;
|
||||||
void* (*func)(void*) = func_and_arg->func;
|
void* (*func)(void*) = func_and_arg->func;
|
||||||
void* arg = func_and_arg->arg;
|
void* arg = func_and_arg->arg;
|
||||||
win_free(param);
|
wutil_Free(param);
|
||||||
|
|
||||||
void* ret = 0;
|
void* ret = 0;
|
||||||
__try
|
__try
|
||||||
@ -592,11 +592,11 @@ static unsigned __stdcall thread_start(void* param)
|
|||||||
int pthread_create(pthread_t* thread_id, const void* UNUSED(attr), void* (*func)(void*), void* arg)
|
int pthread_create(pthread_t* thread_id, const void* UNUSED(attr), void* (*func)(void*), void* arg)
|
||||||
{
|
{
|
||||||
// notes:
|
// notes:
|
||||||
// - use win_alloc instead of the normal heap because we /might/
|
// - use wutil_Allocate instead of the normal heap because we /might/
|
||||||
// potentially be called before _cinit.
|
// potentially be called before _cinit.
|
||||||
// - placement new is more trouble than it's worth
|
// - placement new is more trouble than it's worth
|
||||||
// (see REDEFINED_NEW), so we don't bother with a ctor.
|
// (see REDEFINED_NEW), so we don't bother with a ctor.
|
||||||
FuncAndArg* func_and_arg = (FuncAndArg*)win_alloc(sizeof(FuncAndArg));
|
FuncAndArg* func_and_arg = (FuncAndArg*)wutil_Allocate(sizeof(FuncAndArg));
|
||||||
if(!func_and_arg)
|
if(!func_and_arg)
|
||||||
{
|
{
|
||||||
WARN_ERR(ERR::NO_MEM);
|
WARN_ERR(ERR::NO_MEM);
|
||||||
|
@ -257,7 +257,7 @@ long __stdcall wseh_ExceptionFilter(struct _EXCEPTION_POINTERS* ep)
|
|||||||
// someone is already holding the dbghelp lock - this is bad.
|
// someone is already holding the dbghelp lock - this is bad.
|
||||||
// we'll report this problem first and then try to display the
|
// we'll report this problem first and then try to display the
|
||||||
// exception info regardless (maybe dbghelp won't blow up).
|
// exception info regardless (maybe dbghelp won't blow up).
|
||||||
if(win_is_locked(WDBG_SYM_CS) == 1)
|
if(wutil_IsLocked(WDBG_SYM_CS) == 1)
|
||||||
DEBUG_DISPLAY_ERROR(L"Exception raised while critical section is held - may deadlock..");
|
DEBUG_DISPLAY_ERROR(L"Exception raised while critical section is held - may deadlock..");
|
||||||
|
|
||||||
// a dump file is essential for debugging, so write it before
|
// a dump file is essential for debugging, so write it before
|
||||||
|
@ -260,7 +260,7 @@ ErrorReaction sys_display_error(const wchar_t* text, size_t flags)
|
|||||||
MSG msg;
|
MSG msg;
|
||||||
BOOL quit_pending = PeekMessage(&msg, 0, WM_QUIT, WM_QUIT, PM_REMOVE);
|
BOOL quit_pending = PeekMessage(&msg, 0, WM_QUIT, WM_QUIT, PM_REMOVE);
|
||||||
|
|
||||||
const HINSTANCE hInstance = wutil_LibModuleHandle;
|
const HINSTANCE hInstance = wutil_LibModuleHandle();
|
||||||
LPCWSTR lpTemplateName = MAKEINTRESOURCEW(IDD_DIALOG1);
|
LPCWSTR lpTemplateName = MAKEINTRESOURCEW(IDD_DIALOG1);
|
||||||
const DialogParams params = { text, flags };
|
const DialogParams params = { text, flags };
|
||||||
// get the enclosing app's window handle. we can't just pass 0 or
|
// get the enclosing app's window handle. we can't just pass 0 or
|
||||||
|
@ -30,7 +30,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h> // __argc
|
#include <stdlib.h> // __argc
|
||||||
|
|
||||||
#include "lib/path_util.h"
|
#include "lib/file/file.h"
|
||||||
|
#include "lib/file/vfs/vfs.h"
|
||||||
#include "lib/posix/posix.h"
|
#include "lib/posix/posix.h"
|
||||||
#include "lib/sysdep/os/win/win.h"
|
#include "lib/sysdep/os/win/win.h"
|
||||||
#include "lib/sysdep/os/win/winit.h"
|
#include "lib/sysdep/os/win/winit.h"
|
||||||
@ -45,19 +46,17 @@ WINIT_REGISTER_LATE_SHUTDOWN(wutil_Shutdown);
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// safe allocator
|
// safe allocator
|
||||||
|
|
||||||
//
|
// may be used independently of libc malloc
|
||||||
// safe allocator that may be used independently of libc malloc
|
|
||||||
// (in particular, before _cinit and while calling static dtors).
|
// (in particular, before _cinit and while calling static dtors).
|
||||||
// used by wpthread critical section code.
|
// used by wpthread critical section code.
|
||||||
//
|
|
||||||
|
|
||||||
void* win_alloc(size_t size)
|
void* wutil_Allocate(size_t size)
|
||||||
{
|
{
|
||||||
const DWORD flags = HEAP_ZERO_MEMORY;
|
const DWORD flags = HEAP_ZERO_MEMORY;
|
||||||
return HeapAlloc(GetProcessHeap(), flags, size);
|
return HeapAlloc(GetProcessHeap(), flags, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void win_free(void* p)
|
void wutil_Free(void* p)
|
||||||
{
|
{
|
||||||
const DWORD flags = 0;
|
const DWORD flags = 0;
|
||||||
HeapFree(GetProcessHeap(), flags, p);
|
HeapFree(GetProcessHeap(), flags, p);
|
||||||
@ -74,21 +73,21 @@ void win_free(void* p)
|
|||||||
static CRITICAL_SECTION cs[NUM_CS];
|
static CRITICAL_SECTION cs[NUM_CS];
|
||||||
static bool cs_valid;
|
static bool cs_valid;
|
||||||
|
|
||||||
void win_lock(WinLockId id)
|
void wutil_Lock(WinLockId id)
|
||||||
{
|
{
|
||||||
if(!cs_valid)
|
if(!cs_valid)
|
||||||
return;
|
return;
|
||||||
EnterCriticalSection(&cs[id]);
|
EnterCriticalSection(&cs[id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void win_unlock(WinLockId id)
|
void wutil_Unlock(WinLockId id)
|
||||||
{
|
{
|
||||||
if(!cs_valid)
|
if(!cs_valid)
|
||||||
return;
|
return;
|
||||||
LeaveCriticalSection(&cs[id]);
|
LeaveCriticalSection(&cs[id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool win_is_locked(WinLockId id)
|
bool wutil_IsLocked(WinLockId id)
|
||||||
{
|
{
|
||||||
if(!cs_valid)
|
if(!cs_valid)
|
||||||
return false;
|
return false;
|
||||||
@ -128,20 +127,40 @@ LibError LibError_from_GLE(bool warn_if_failed)
|
|||||||
switch(GetLastError())
|
switch(GetLastError())
|
||||||
{
|
{
|
||||||
case ERROR_OUTOFMEMORY:
|
case ERROR_OUTOFMEMORY:
|
||||||
err = ERR::NO_MEM; break;
|
case ERROR_NOT_ENOUGH_MEMORY:
|
||||||
|
err = ERR::NO_MEM;
|
||||||
|
break;
|
||||||
|
case ERROR_INVALID_HANDLE:
|
||||||
case ERROR_INVALID_PARAMETER:
|
case ERROR_INVALID_PARAMETER:
|
||||||
err = ERR::INVALID_PARAM; break;
|
case ERROR_BAD_ARGUMENTS:
|
||||||
|
err = ERR::INVALID_PARAM;
|
||||||
|
break;
|
||||||
case ERROR_INSUFFICIENT_BUFFER:
|
case ERROR_INSUFFICIENT_BUFFER:
|
||||||
err = ERR::BUF_SIZE; break;
|
err = ERR::BUF_SIZE;
|
||||||
|
break;
|
||||||
/*
|
|
||||||
case ERROR_ACCESS_DENIED:
|
case ERROR_ACCESS_DENIED:
|
||||||
err = ERR::FILE_ACCESS; break;
|
err = ERR::FILE_ACCESS;
|
||||||
|
break;
|
||||||
|
case ERROR_NOT_SUPPORTED:
|
||||||
|
err = ERR::NOT_SUPPORTED;
|
||||||
|
break;
|
||||||
|
case ERROR_CALL_NOT_IMPLEMENTED:
|
||||||
|
err = ERR::NOT_IMPLEMENTED;
|
||||||
|
break;
|
||||||
|
case ERROR_PROC_NOT_FOUND:
|
||||||
|
err = ERR::NO_SYS;
|
||||||
|
break;
|
||||||
|
case ERROR_BUSY:
|
||||||
|
err = ERR::AGAIN;
|
||||||
|
break;
|
||||||
case ERROR_FILE_NOT_FOUND:
|
case ERROR_FILE_NOT_FOUND:
|
||||||
|
err = ERR::VFS_FILE_NOT_FOUND;
|
||||||
|
break;
|
||||||
case ERROR_PATH_NOT_FOUND:
|
case ERROR_PATH_NOT_FOUND:
|
||||||
err = ERR::TNODE_NOT_FOUND; break;
|
err = ERR::VFS_DIR_NOT_FOUND;
|
||||||
*/
|
break;
|
||||||
|
default:
|
||||||
|
break; // err already set above
|
||||||
}
|
}
|
||||||
|
|
||||||
if(warn_if_failed)
|
if(warn_if_failed)
|
||||||
@ -150,10 +169,6 @@ LibError LibError_from_GLE(bool warn_if_failed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// return the LibError equivalent of GetLastError(), or ERR::FAIL if
|
|
||||||
// there's no equal.
|
|
||||||
// you should SetLastError(0) before calling whatever will set ret
|
|
||||||
// to make sure we do not return any stale errors.
|
|
||||||
LibError LibError_from_win32(DWORD ret, bool warn_if_failed)
|
LibError LibError_from_win32(DWORD ret, bool warn_if_failed)
|
||||||
{
|
{
|
||||||
if(ret != FALSE)
|
if(ret != FALSE)
|
||||||
@ -169,8 +184,8 @@ LibError LibError_from_win32(DWORD ret, bool warn_if_failed)
|
|||||||
// the argv pointers.
|
// the argv pointers.
|
||||||
static wchar_t* argvContents;
|
static wchar_t* argvContents;
|
||||||
|
|
||||||
int wutil_argc = 0;
|
int s_argc = 0;
|
||||||
wchar_t** wutil_argv = 0;
|
wchar_t** s_argv = 0;
|
||||||
|
|
||||||
static void ReadCommandLine()
|
static void ReadCommandLine()
|
||||||
{
|
{
|
||||||
@ -198,36 +213,48 @@ static void ReadCommandLine()
|
|||||||
if(!ignoreSpace)
|
if(!ignoreSpace)
|
||||||
{
|
{
|
||||||
argvContents[i] = '\0';
|
argvContents[i] = '\0';
|
||||||
wutil_argc++;
|
s_argc++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wutil_argc++;
|
s_argc++;
|
||||||
|
|
||||||
// have argv entries point into the tokenized string
|
// have argv entries point into the tokenized string
|
||||||
wutil_argv = (wchar_t**)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, wutil_argc*sizeof(wchar_t*));
|
s_argv = (wchar_t**)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, s_argc*sizeof(wchar_t*));
|
||||||
wchar_t* nextArg = argvContents;
|
wchar_t* nextArg = argvContents;
|
||||||
for(int i = 0; i < wutil_argc; i++)
|
for(int i = 0; i < s_argc; i++)
|
||||||
{
|
{
|
||||||
wutil_argv[i] = nextArg;
|
s_argv[i] = nextArg;
|
||||||
nextArg += wcslen(nextArg)+1;
|
nextArg += wcslen(nextArg)+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wutil_argc()
|
||||||
|
{
|
||||||
|
return s_argc;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t** wutil_argv()
|
||||||
|
{
|
||||||
|
debug_assert(s_argv);
|
||||||
|
return s_argv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void FreeCommandLine()
|
static void FreeCommandLine()
|
||||||
{
|
{
|
||||||
HeapFree(GetProcessHeap(), 0, wutil_argv);
|
HeapFree(GetProcessHeap(), 0, s_argv);
|
||||||
HeapFree(GetProcessHeap(), 0, argvContents);
|
HeapFree(GetProcessHeap(), 0, argvContents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool wutil_HasCommandLineArgument(const wchar_t* arg)
|
bool wutil_HasCommandLineArgument(const wchar_t* arg)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < wutil_argc; i++)
|
for(int i = 0; i < s_argc; i++)
|
||||||
{
|
{
|
||||||
if(!wcscmp(wutil_argv[i], arg))
|
if(!wcscmp(s_argv[i], arg))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,11 +304,11 @@ static void GetDirectories()
|
|||||||
{
|
{
|
||||||
const UINT charsWritten = GetSystemDirectoryW(path, MAX_PATH);
|
const UINT charsWritten = GetSystemDirectoryW(path, MAX_PATH);
|
||||||
debug_assert(charsWritten != 0);
|
debug_assert(charsWritten != 0);
|
||||||
systemPath = new(win_alloc(sizeof(fs::wpath))) fs::wpath(path);
|
systemPath = new(wutil_Allocate(sizeof(fs::wpath))) fs::wpath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// executable's directory
|
// executable's directory
|
||||||
executablePath = new(win_alloc(sizeof(fs::wpath))) fs::wpath(wutil_DetectExecutablePath());
|
executablePath = new(wutil_Allocate(sizeof(fs::wpath))) fs::wpath(wutil_DetectExecutablePath());
|
||||||
|
|
||||||
// application data
|
// application data
|
||||||
{
|
{
|
||||||
@ -289,7 +316,7 @@ static void GetDirectories()
|
|||||||
HANDLE token = 0;
|
HANDLE token = 0;
|
||||||
const HRESULT ret = SHGetFolderPathW(hwnd, CSIDL_APPDATA, token, 0, path);
|
const HRESULT ret = SHGetFolderPathW(hwnd, CSIDL_APPDATA, token, 0, path);
|
||||||
debug_assert(SUCCEEDED(ret));
|
debug_assert(SUCCEEDED(ret));
|
||||||
appdataPath = new(win_alloc(sizeof(fs::wpath))) fs::wpath(path);
|
appdataPath = new(wutil_Allocate(sizeof(fs::wpath))) fs::wpath(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,11 +324,11 @@ static void GetDirectories()
|
|||||||
static void FreeDirectories()
|
static void FreeDirectories()
|
||||||
{
|
{
|
||||||
systemPath->~basic_path();
|
systemPath->~basic_path();
|
||||||
win_free(systemPath);
|
wutil_Free(systemPath);
|
||||||
executablePath->~basic_path();
|
executablePath->~basic_path();
|
||||||
win_free(executablePath);
|
wutil_Free(executablePath);
|
||||||
appdataPath->~basic_path();
|
appdataPath->~basic_path();
|
||||||
win_free(appdataPath);
|
wutil_Free(appdataPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -311,7 +338,7 @@ static void FreeDirectories()
|
|||||||
// HACK: make sure a reference to user32 is held, even if someone
|
// HACK: make sure a reference to user32 is held, even if someone
|
||||||
// decides to delay-load it. this fixes bug #66, which was the
|
// decides to delay-load it. this fixes bug #66, which was the
|
||||||
// Win32 mouse cursor (set via user32!SetCursor) appearing as a
|
// Win32 mouse cursor (set via user32!SetCursor) appearing as a
|
||||||
// black 32x32(?) rectangle. underlying cause was as follows:
|
// black 32x32(?) rectangle. the underlying cause was as follows:
|
||||||
// powrprof.dll was the first client of user32, causing it to be
|
// powrprof.dll was the first client of user32, causing it to be
|
||||||
// loaded. after we were finished with powrprof, we freed it, in turn
|
// loaded. after we were finished with powrprof, we freed it, in turn
|
||||||
// causing user32 to unload. later code would then reload user32,
|
// causing user32 to unload. later code would then reload user32,
|
||||||
@ -341,14 +368,13 @@ static void FreeUser32Dll()
|
|||||||
static void EnableLowFragmentationHeap()
|
static void EnableLowFragmentationHeap()
|
||||||
{
|
{
|
||||||
#if WINVER >= 0x0501
|
#if WINVER >= 0x0501
|
||||||
const HMODULE hKernel32Dll = GetModuleHandleW(L"kernel32.dll");
|
WUTIL_FUNC(pHeapSetInformation, BOOL, (HANDLE, HEAP_INFORMATION_CLASS, void*, size_t));
|
||||||
typedef BOOL (WINAPI* PHeapSetInformation)(HANDLE, HEAP_INFORMATION_CLASS, void*, size_t);
|
WUTIL_IMPORT_KERNEL32(HeapSetInformation, pHeapSetInformation);
|
||||||
PHeapSetInformation pHeapSetInformation = (PHeapSetInformation)GetProcAddress(hKernel32Dll, "HeapSetInformation");
|
if(pHeapSetInformation)
|
||||||
if(!pHeapSetInformation)
|
{
|
||||||
return;
|
ULONG flags = 2; // enable LFH
|
||||||
|
pHeapSetInformation(GetProcessHeap(), HeapCompatibilityInformation, &flags, sizeof(flags));
|
||||||
ULONG flags = 2; // enable LFH
|
}
|
||||||
pHeapSetInformation(GetProcessHeap(), HeapCompatibilityInformation, &flags, sizeof(flags));
|
|
||||||
#endif // #if WINVER >= 0x0501
|
#endif // #if WINVER >= 0x0501
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,6 +421,8 @@ const wchar_t* wutil_WindowsFamily()
|
|||||||
return L"WinXP64";
|
return L"WinXP64";
|
||||||
case WUTIL_VERSION_VISTA:
|
case WUTIL_VERSION_VISTA:
|
||||||
return L"Vista";
|
return L"Vista";
|
||||||
|
case WUTIL_VERSION_7:
|
||||||
|
return L"Win7";
|
||||||
default:
|
default:
|
||||||
return L"Windows";
|
return L"Windows";
|
||||||
}
|
}
|
||||||
@ -422,21 +450,17 @@ size_t wutil_WindowsVersion()
|
|||||||
// that's bad, because the actual drivers are not in the subdirectory. to
|
// that's bad, because the actual drivers are not in the subdirectory. to
|
||||||
// work around this, provide for temporarily disabling redirection.
|
// work around this, provide for temporarily disabling redirection.
|
||||||
|
|
||||||
typedef BOOL (WINAPI *PIsWow64Process)(HANDLE, PBOOL);
|
static WUTIL_FUNC(pIsWow64Process, BOOL, (HANDLE, PBOOL));
|
||||||
typedef BOOL (WINAPI *PWow64DisableWow64FsRedirection)(PVOID*);
|
static WUTIL_FUNC(pWow64DisableWow64FsRedirection, BOOL, (PVOID*));
|
||||||
typedef BOOL (WINAPI *PWow64RevertWow64FsRedirection)(PVOID);
|
static WUTIL_FUNC(pWow64RevertWow64FsRedirection, BOOL, (PVOID));
|
||||||
static PIsWow64Process pIsWow64Process;
|
|
||||||
static PWow64DisableWow64FsRedirection pWow64DisableWow64FsRedirection;
|
|
||||||
static PWow64RevertWow64FsRedirection pWow64RevertWow64FsRedirection;
|
|
||||||
|
|
||||||
static bool isWow64;
|
static bool isWow64;
|
||||||
|
|
||||||
static void ImportWow64Functions()
|
static void ImportWow64Functions()
|
||||||
{
|
{
|
||||||
const HMODULE hKernel32Dll = GetModuleHandleW(L"kernel32.dll");
|
WUTIL_IMPORT_KERNEL32(IsWow64Process, pIsWow64Process);
|
||||||
pIsWow64Process = (PIsWow64Process)GetProcAddress(hKernel32Dll, "IsWow64Process");
|
WUTIL_IMPORT_KERNEL32(Wow64DisableWow64FsRedirection, pWow64DisableWow64FsRedirection);
|
||||||
pWow64DisableWow64FsRedirection = (PWow64DisableWow64FsRedirection)GetProcAddress(hKernel32Dll, "Wow64DisableWow64FsRedirection");
|
WUTIL_IMPORT_KERNEL32(Wow64RevertWow64FsRedirection, pWow64RevertWow64FsRedirection);
|
||||||
pWow64RevertWow64FsRedirection = (PWow64RevertWow64FsRedirection)GetProcAddress(hKernel32Dll, "Wow64RevertWow64FsRedirection");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DetectWow64()
|
static void DetectWow64()
|
||||||
@ -468,7 +492,7 @@ WinScopedDisableWow64Redirection::WinScopedDisableWow64Redirection()
|
|||||||
// more need to verify the pointers (their existence is implied).
|
// more need to verify the pointers (their existence is implied).
|
||||||
if(!wutil_IsWow64())
|
if(!wutil_IsWow64())
|
||||||
return;
|
return;
|
||||||
BOOL ok = pWow64DisableWow64FsRedirection(&m_wasRedirectionEnabled);
|
const BOOL ok = pWow64DisableWow64FsRedirection(&m_wasRedirectionEnabled);
|
||||||
WARN_IF_FALSE(ok);
|
WARN_IF_FALSE(ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -476,7 +500,7 @@ WinScopedDisableWow64Redirection::~WinScopedDisableWow64Redirection()
|
|||||||
{
|
{
|
||||||
if(!wutil_IsWow64())
|
if(!wutil_IsWow64())
|
||||||
return;
|
return;
|
||||||
BOOL ok = pWow64RevertWow64FsRedirection(m_wasRedirectionEnabled);
|
const BOOL ok = pWow64RevertWow64FsRedirection(m_wasRedirectionEnabled);
|
||||||
WARN_IF_FALSE(ok);
|
WARN_IF_FALSE(ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,22 +510,31 @@ WinScopedDisableWow64Redirection::~WinScopedDisableWow64Redirection()
|
|||||||
|
|
||||||
#ifndef LIB_STATIC_LINK
|
#ifndef LIB_STATIC_LINK
|
||||||
|
|
||||||
HMODULE wutil_LibModuleHandle;
|
static HMODULE s_hModule;
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD UNUSED(reason), LPVOID UNUSED(reserved))
|
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD UNUSED(reason), LPVOID UNUSED(reserved))
|
||||||
{
|
{
|
||||||
DisableThreadLibraryCalls(hInstance);
|
DisableThreadLibraryCalls(hInstance);
|
||||||
wutil_LibModuleHandle = hInstance;
|
s_hModule = hInstance;
|
||||||
return TRUE; // success (ignored unless reason == DLL_PROCESS_ATTACH)
|
return TRUE; // success (ignored unless reason == DLL_PROCESS_ATTACH)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HMODULE wutil_LibModuleHandle()
|
||||||
|
{
|
||||||
|
return s_hModule;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
HMODULE wutil_LibModuleHandle = GetModuleHandle(0);
|
HMODULE wutil_LibModuleHandle()
|
||||||
|
{
|
||||||
|
return GetModuleHandle(0);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// find main window
|
// find main window
|
||||||
|
|
||||||
|
@ -27,10 +27,6 @@
|
|||||||
#ifndef INCLUDED_WUTIL
|
#ifndef INCLUDED_WUTIL
|
||||||
#define INCLUDED_WUTIL
|
#define INCLUDED_WUTIL
|
||||||
|
|
||||||
#if !OS_WIN
|
|
||||||
#error "wutil.h: do not include if not compiling for Windows"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "lib/sysdep/os/win/win.h"
|
#include "lib/sysdep/os/win/win.h"
|
||||||
|
|
||||||
template<typename H>
|
template<typename H>
|
||||||
@ -40,17 +36,42 @@ bool wutil_IsValidHandle(H h)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//-----------------------------------------------------------------------------
|
||||||
|
// dynamic linking
|
||||||
|
|
||||||
|
// define a function pointer (optionally prepend 'static')
|
||||||
|
#define WUTIL_FUNC(varName, ret, params)\
|
||||||
|
ret (WINAPI* varName) params
|
||||||
|
|
||||||
|
// rationale:
|
||||||
|
// - splitting up WUTIL_FUNC and WUTIL_IMPORT is a bit verbose in
|
||||||
|
// the common case of a local function pointer definition,
|
||||||
|
// but allows one-time initialization of static variables.
|
||||||
|
// - differentiating between procName and varName allows searching
|
||||||
|
// for the actual definition of the function pointer in the code.
|
||||||
|
// - a cast would require passing in ret/params.
|
||||||
|
// - writing a type-punned pointer breaks strict-aliasing rules.
|
||||||
|
#define WUTIL_IMPORT(hModule, procName, varName)\
|
||||||
|
STMT(\
|
||||||
|
const FARPROC f = GetProcAddress(hModule, #procName);\
|
||||||
|
memcpy(&varName, &f, sizeof(FARPROC));\
|
||||||
|
)
|
||||||
|
|
||||||
|
// note: Kernel32 is guaranteed to be loaded, so we don't
|
||||||
|
// need to LoadLibrary and FreeLibrary.
|
||||||
|
#define WUTIL_IMPORT_KERNEL32(procName, varName)\
|
||||||
|
WUTIL_IMPORT(GetModuleHandleW(L"kernel32.dll"), procName, varName)
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
// safe allocator
|
// safe allocator
|
||||||
//
|
|
||||||
|
|
||||||
extern void* win_alloc(size_t size);
|
extern void* wutil_Allocate(size_t size);
|
||||||
extern void win_free(void* p);
|
extern void wutil_Free(void* p);
|
||||||
|
|
||||||
|
|
||||||
//
|
//-----------------------------------------------------------------------------
|
||||||
// locks
|
// locks
|
||||||
//
|
|
||||||
|
|
||||||
// critical sections used by win-specific code
|
// critical sections used by win-specific code
|
||||||
enum WinLockId
|
enum WinLockId
|
||||||
@ -64,11 +85,11 @@ enum WinLockId
|
|||||||
NUM_CS
|
NUM_CS
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void win_lock(WinLockId id);
|
extern void wutil_Lock(WinLockId id);
|
||||||
extern void win_unlock(WinLockId id);
|
extern void wutil_Unlock(WinLockId id);
|
||||||
|
|
||||||
// used in a desperate attempt to avoid deadlock in wseh.
|
// used in a desperate attempt to avoid deadlock in wseh.
|
||||||
extern bool win_is_locked(WinLockId id);
|
extern bool wutil_IsLocked(WinLockId id);
|
||||||
|
|
||||||
class WinScopedLock
|
class WinScopedLock
|
||||||
{
|
{
|
||||||
@ -76,12 +97,12 @@ public:
|
|||||||
WinScopedLock(WinLockId id)
|
WinScopedLock(WinLockId id)
|
||||||
: m_id(id)
|
: m_id(id)
|
||||||
{
|
{
|
||||||
win_lock(m_id);
|
wutil_Lock(m_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
~WinScopedLock()
|
~WinScopedLock()
|
||||||
{
|
{
|
||||||
win_unlock(m_id);
|
wutil_Unlock(m_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -89,9 +110,8 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
//-----------------------------------------------------------------------------
|
||||||
// errors
|
// errors
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* some WinAPI functions SetLastError(0) on success, which is bad because
|
* some WinAPI functions SetLastError(0) on success, which is bad because
|
||||||
@ -131,23 +151,23 @@ LibError LibError_from_GLE(bool warn_if_failed = true);
|
|||||||
|
|
||||||
#define WARN_WIN32_ERR (void)LibError_from_GLE(true)
|
#define WARN_WIN32_ERR (void)LibError_from_GLE(true)
|
||||||
|
|
||||||
/// if ret is false, returns LibError_from_GLE.
|
/**
|
||||||
|
* @return INFO::OK if ret != FALSE, else LibError_from_GLE().
|
||||||
|
**/
|
||||||
extern LibError LibError_from_win32(DWORD ret, bool warn_if_failed = true);
|
extern LibError LibError_from_win32(DWORD ret, bool warn_if_failed = true);
|
||||||
|
|
||||||
|
|
||||||
//
|
//-----------------------------------------------------------------------------
|
||||||
// command line
|
// command line
|
||||||
//
|
|
||||||
|
|
||||||
extern int wutil_argc;
|
extern int wutil_argc();
|
||||||
extern wchar_t** wutil_argv;
|
extern wchar_t** wutil_argv();
|
||||||
|
|
||||||
extern bool wutil_HasCommandLineArgument(const wchar_t* arg);
|
extern bool wutil_HasCommandLineArgument(const wchar_t* arg);
|
||||||
|
|
||||||
|
|
||||||
//
|
//-----------------------------------------------------------------------------
|
||||||
// directories
|
// directories
|
||||||
//
|
|
||||||
|
|
||||||
// used by wutil_ExecutablePath, but provided in case other code
|
// used by wutil_ExecutablePath, but provided in case other code
|
||||||
// needs to know this before our wutil_Init runs.
|
// needs to know this before our wutil_Init runs.
|
||||||
@ -158,9 +178,8 @@ extern const fs::wpath& wutil_ExecutablePath();
|
|||||||
extern const fs::wpath& wutil_AppdataPath();
|
extern const fs::wpath& wutil_AppdataPath();
|
||||||
|
|
||||||
|
|
||||||
//
|
//-----------------------------------------------------------------------------
|
||||||
// version
|
// version
|
||||||
//
|
|
||||||
|
|
||||||
extern const wchar_t* wutil_WindowsVersionString();
|
extern const wchar_t* wutil_WindowsVersionString();
|
||||||
|
|
||||||
@ -169,6 +188,7 @@ const size_t WUTIL_VERSION_2K = 0x0500;
|
|||||||
const size_t WUTIL_VERSION_XP = 0x0501;
|
const size_t WUTIL_VERSION_XP = 0x0501;
|
||||||
const size_t WUTIL_VERSION_XP64 = 0x0502;
|
const size_t WUTIL_VERSION_XP64 = 0x0502;
|
||||||
const size_t WUTIL_VERSION_VISTA = 0x0600;
|
const size_t WUTIL_VERSION_VISTA = 0x0600;
|
||||||
|
const size_t WUTIL_VERSION_7 = 0x0601;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return short textual representation of the appropriate WUTIL_VERSION
|
* @return short textual representation of the appropriate WUTIL_VERSION
|
||||||
@ -178,9 +198,8 @@ extern const wchar_t* wutil_WindowsFamily();
|
|||||||
extern size_t wutil_WindowsVersion();
|
extern size_t wutil_WindowsVersion();
|
||||||
|
|
||||||
|
|
||||||
//
|
//-----------------------------------------------------------------------------
|
||||||
// Wow64
|
// Wow64
|
||||||
//
|
|
||||||
|
|
||||||
extern bool wutil_IsWow64();
|
extern bool wutil_IsWow64();
|
||||||
|
|
||||||
@ -195,12 +214,14 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* module handle of lib code (that of the main EXE if linked statically,
|
* @return module handle of lib code (that of the main EXE if
|
||||||
* otherwise the DLL).
|
* linked statically, otherwise the DLL).
|
||||||
* this is necessary for the error dialog.
|
* this is necessary for the error dialog.
|
||||||
**/
|
**/
|
||||||
extern HMODULE wutil_LibModuleHandle;
|
extern HMODULE wutil_LibModuleHandle();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user