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;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
@ -247,7 +247,7 @@ again:
|
||||
// initializer returns pthread_mutex_t directly and CRITICAL_SECTIONS
|
||||
// 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.
|
||||
|
||||
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()
|
||||
{
|
||||
CRITICAL_SECTION* cs = (CRITICAL_SECTION*)win_alloc(sizeof(CRITICAL_SECTION));
|
||||
CRITICAL_SECTION* cs = (CRITICAL_SECTION*)wutil_Allocate(sizeof(CRITICAL_SECTION));
|
||||
InitializeCriticalSection(cs);
|
||||
return (pthread_mutex_t)cs;
|
||||
}
|
||||
@ -273,7 +273,7 @@ int pthread_mutex_destroy(pthread_mutex_t* m)
|
||||
if(!cs)
|
||||
return -1;
|
||||
DeleteCriticalSection(cs);
|
||||
win_free(cs);
|
||||
wutil_Free(cs);
|
||||
*m = 0; // cause double-frees to be noticed
|
||||
return 0;
|
||||
}
|
||||
@ -546,7 +546,7 @@ int sem_msgwait_np(sem_t* sem)
|
||||
// - a local variable in pthread_create isn't safe because the
|
||||
// new thread might not start before pthread_create returns.
|
||||
// - 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
|
||||
// stomp on the first thread's 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;
|
||||
void* (*func)(void*) = func_and_arg->func;
|
||||
void* arg = func_and_arg->arg;
|
||||
win_free(param);
|
||||
wutil_Free(param);
|
||||
|
||||
void* ret = 0;
|
||||
__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)
|
||||
{
|
||||
// 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.
|
||||
// - placement new is more trouble than it's worth
|
||||
// (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)
|
||||
{
|
||||
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.
|
||||
// we'll report this problem first and then try to display the
|
||||
// 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..");
|
||||
|
||||
// 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;
|
||||
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);
|
||||
const DialogParams params = { text, flags };
|
||||
// get the enclosing app's window handle. we can't just pass 0 or
|
||||
|
@ -30,7 +30,8 @@
|
||||
#include <stdio.h>
|
||||
#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/sysdep/os/win/win.h"
|
||||
#include "lib/sysdep/os/win/winit.h"
|
||||
@ -45,19 +46,17 @@ WINIT_REGISTER_LATE_SHUTDOWN(wutil_Shutdown);
|
||||
//-----------------------------------------------------------------------------
|
||||
// safe allocator
|
||||
|
||||
//
|
||||
// safe allocator that may be used independently of libc malloc
|
||||
// may be used independently of libc malloc
|
||||
// (in particular, before _cinit and while calling static dtors).
|
||||
// used by wpthread critical section code.
|
||||
//
|
||||
|
||||
void* win_alloc(size_t size)
|
||||
void* wutil_Allocate(size_t size)
|
||||
{
|
||||
const DWORD flags = HEAP_ZERO_MEMORY;
|
||||
return HeapAlloc(GetProcessHeap(), flags, size);
|
||||
}
|
||||
|
||||
void win_free(void* p)
|
||||
void wutil_Free(void* p)
|
||||
{
|
||||
const DWORD flags = 0;
|
||||
HeapFree(GetProcessHeap(), flags, p);
|
||||
@ -74,21 +73,21 @@ void win_free(void* p)
|
||||
static CRITICAL_SECTION cs[NUM_CS];
|
||||
static bool cs_valid;
|
||||
|
||||
void win_lock(WinLockId id)
|
||||
void wutil_Lock(WinLockId id)
|
||||
{
|
||||
if(!cs_valid)
|
||||
return;
|
||||
EnterCriticalSection(&cs[id]);
|
||||
}
|
||||
|
||||
void win_unlock(WinLockId id)
|
||||
void wutil_Unlock(WinLockId id)
|
||||
{
|
||||
if(!cs_valid)
|
||||
return;
|
||||
LeaveCriticalSection(&cs[id]);
|
||||
}
|
||||
|
||||
bool win_is_locked(WinLockId id)
|
||||
bool wutil_IsLocked(WinLockId id)
|
||||
{
|
||||
if(!cs_valid)
|
||||
return false;
|
||||
@ -128,20 +127,40 @@ LibError LibError_from_GLE(bool warn_if_failed)
|
||||
switch(GetLastError())
|
||||
{
|
||||
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:
|
||||
err = ERR::INVALID_PARAM; break;
|
||||
case ERROR_BAD_ARGUMENTS:
|
||||
err = ERR::INVALID_PARAM;
|
||||
break;
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
err = ERR::BUF_SIZE; break;
|
||||
|
||||
/*
|
||||
err = ERR::BUF_SIZE;
|
||||
break;
|
||||
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:
|
||||
err = ERR::VFS_FILE_NOT_FOUND;
|
||||
break;
|
||||
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)
|
||||
@ -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)
|
||||
{
|
||||
if(ret != FALSE)
|
||||
@ -169,8 +184,8 @@ LibError LibError_from_win32(DWORD ret, bool warn_if_failed)
|
||||
// the argv pointers.
|
||||
static wchar_t* argvContents;
|
||||
|
||||
int wutil_argc = 0;
|
||||
wchar_t** wutil_argv = 0;
|
||||
int s_argc = 0;
|
||||
wchar_t** s_argv = 0;
|
||||
|
||||
static void ReadCommandLine()
|
||||
{
|
||||
@ -198,36 +213,48 @@ static void ReadCommandLine()
|
||||
if(!ignoreSpace)
|
||||
{
|
||||
argvContents[i] = '\0';
|
||||
wutil_argc++;
|
||||
s_argc++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
wutil_argc++;
|
||||
s_argc++;
|
||||
|
||||
// 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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int wutil_argc()
|
||||
{
|
||||
return s_argc;
|
||||
}
|
||||
|
||||
wchar_t** wutil_argv()
|
||||
{
|
||||
debug_assert(s_argv);
|
||||
return s_argv;
|
||||
}
|
||||
|
||||
|
||||
static void FreeCommandLine()
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, wutil_argv);
|
||||
HeapFree(GetProcessHeap(), 0, s_argv);
|
||||
HeapFree(GetProcessHeap(), 0, argvContents);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -277,11 +304,11 @@ static void GetDirectories()
|
||||
{
|
||||
const UINT charsWritten = GetSystemDirectoryW(path, MAX_PATH);
|
||||
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
|
||||
executablePath = new(win_alloc(sizeof(fs::wpath))) fs::wpath(wutil_DetectExecutablePath());
|
||||
executablePath = new(wutil_Allocate(sizeof(fs::wpath))) fs::wpath(wutil_DetectExecutablePath());
|
||||
|
||||
// application data
|
||||
{
|
||||
@ -289,7 +316,7 @@ static void GetDirectories()
|
||||
HANDLE token = 0;
|
||||
const HRESULT ret = SHGetFolderPathW(hwnd, CSIDL_APPDATA, token, 0, path);
|
||||
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()
|
||||
{
|
||||
systemPath->~basic_path();
|
||||
win_free(systemPath);
|
||||
wutil_Free(systemPath);
|
||||
executablePath->~basic_path();
|
||||
win_free(executablePath);
|
||||
wutil_Free(executablePath);
|
||||
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
|
||||
// decides to delay-load it. this fixes bug #66, which was the
|
||||
// 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
|
||||
// loaded. after we were finished with powrprof, we freed it, in turn
|
||||
// causing user32 to unload. later code would then reload user32,
|
||||
@ -341,14 +368,13 @@ static void FreeUser32Dll()
|
||||
static void EnableLowFragmentationHeap()
|
||||
{
|
||||
#if WINVER >= 0x0501
|
||||
const HMODULE hKernel32Dll = GetModuleHandleW(L"kernel32.dll");
|
||||
typedef BOOL (WINAPI* PHeapSetInformation)(HANDLE, HEAP_INFORMATION_CLASS, void*, size_t);
|
||||
PHeapSetInformation pHeapSetInformation = (PHeapSetInformation)GetProcAddress(hKernel32Dll, "HeapSetInformation");
|
||||
if(!pHeapSetInformation)
|
||||
return;
|
||||
|
||||
ULONG flags = 2; // enable LFH
|
||||
pHeapSetInformation(GetProcessHeap(), HeapCompatibilityInformation, &flags, sizeof(flags));
|
||||
WUTIL_FUNC(pHeapSetInformation, BOOL, (HANDLE, HEAP_INFORMATION_CLASS, void*, size_t));
|
||||
WUTIL_IMPORT_KERNEL32(HeapSetInformation, pHeapSetInformation);
|
||||
if(pHeapSetInformation)
|
||||
{
|
||||
ULONG flags = 2; // enable LFH
|
||||
pHeapSetInformation(GetProcessHeap(), HeapCompatibilityInformation, &flags, sizeof(flags));
|
||||
}
|
||||
#endif // #if WINVER >= 0x0501
|
||||
}
|
||||
|
||||
@ -395,6 +421,8 @@ const wchar_t* wutil_WindowsFamily()
|
||||
return L"WinXP64";
|
||||
case WUTIL_VERSION_VISTA:
|
||||
return L"Vista";
|
||||
case WUTIL_VERSION_7:
|
||||
return L"Win7";
|
||||
default:
|
||||
return L"Windows";
|
||||
}
|
||||
@ -422,21 +450,17 @@ size_t wutil_WindowsVersion()
|
||||
// that's bad, because the actual drivers are not in the subdirectory. to
|
||||
// work around this, provide for temporarily disabling redirection.
|
||||
|
||||
typedef BOOL (WINAPI *PIsWow64Process)(HANDLE, PBOOL);
|
||||
typedef BOOL (WINAPI *PWow64DisableWow64FsRedirection)(PVOID*);
|
||||
typedef BOOL (WINAPI *PWow64RevertWow64FsRedirection)(PVOID);
|
||||
static PIsWow64Process pIsWow64Process;
|
||||
static PWow64DisableWow64FsRedirection pWow64DisableWow64FsRedirection;
|
||||
static PWow64RevertWow64FsRedirection pWow64RevertWow64FsRedirection;
|
||||
static WUTIL_FUNC(pIsWow64Process, BOOL, (HANDLE, PBOOL));
|
||||
static WUTIL_FUNC(pWow64DisableWow64FsRedirection, BOOL, (PVOID*));
|
||||
static WUTIL_FUNC(pWow64RevertWow64FsRedirection, BOOL, (PVOID));
|
||||
|
||||
static bool isWow64;
|
||||
|
||||
static void ImportWow64Functions()
|
||||
{
|
||||
const HMODULE hKernel32Dll = GetModuleHandleW(L"kernel32.dll");
|
||||
pIsWow64Process = (PIsWow64Process)GetProcAddress(hKernel32Dll, "IsWow64Process");
|
||||
pWow64DisableWow64FsRedirection = (PWow64DisableWow64FsRedirection)GetProcAddress(hKernel32Dll, "Wow64DisableWow64FsRedirection");
|
||||
pWow64RevertWow64FsRedirection = (PWow64RevertWow64FsRedirection)GetProcAddress(hKernel32Dll, "Wow64RevertWow64FsRedirection");
|
||||
WUTIL_IMPORT_KERNEL32(IsWow64Process, pIsWow64Process);
|
||||
WUTIL_IMPORT_KERNEL32(Wow64DisableWow64FsRedirection, pWow64DisableWow64FsRedirection);
|
||||
WUTIL_IMPORT_KERNEL32(Wow64RevertWow64FsRedirection, pWow64RevertWow64FsRedirection);
|
||||
}
|
||||
|
||||
static void DetectWow64()
|
||||
@ -468,7 +492,7 @@ WinScopedDisableWow64Redirection::WinScopedDisableWow64Redirection()
|
||||
// more need to verify the pointers (their existence is implied).
|
||||
if(!wutil_IsWow64())
|
||||
return;
|
||||
BOOL ok = pWow64DisableWow64FsRedirection(&m_wasRedirectionEnabled);
|
||||
const BOOL ok = pWow64DisableWow64FsRedirection(&m_wasRedirectionEnabled);
|
||||
WARN_IF_FALSE(ok);
|
||||
}
|
||||
|
||||
@ -476,7 +500,7 @@ WinScopedDisableWow64Redirection::~WinScopedDisableWow64Redirection()
|
||||
{
|
||||
if(!wutil_IsWow64())
|
||||
return;
|
||||
BOOL ok = pWow64RevertWow64FsRedirection(m_wasRedirectionEnabled);
|
||||
const BOOL ok = pWow64RevertWow64FsRedirection(m_wasRedirectionEnabled);
|
||||
WARN_IF_FALSE(ok);
|
||||
}
|
||||
|
||||
@ -486,22 +510,31 @@ WinScopedDisableWow64Redirection::~WinScopedDisableWow64Redirection()
|
||||
|
||||
#ifndef LIB_STATIC_LINK
|
||||
|
||||
HMODULE wutil_LibModuleHandle;
|
||||
static HMODULE s_hModule;
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD UNUSED(reason), LPVOID UNUSED(reserved))
|
||||
{
|
||||
DisableThreadLibraryCalls(hInstance);
|
||||
wutil_LibModuleHandle = hInstance;
|
||||
s_hModule = hInstance;
|
||||
return TRUE; // success (ignored unless reason == DLL_PROCESS_ATTACH)
|
||||
}
|
||||
|
||||
HMODULE wutil_LibModuleHandle()
|
||||
{
|
||||
return s_hModule;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
HMODULE wutil_LibModuleHandle = GetModuleHandle(0);
|
||||
HMODULE wutil_LibModuleHandle()
|
||||
{
|
||||
return GetModuleHandle(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// find main window
|
||||
|
||||
|
@ -27,10 +27,6 @@
|
||||
#ifndef 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"
|
||||
|
||||
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
|
||||
//
|
||||
|
||||
extern void* win_alloc(size_t size);
|
||||
extern void win_free(void* p);
|
||||
extern void* wutil_Allocate(size_t size);
|
||||
extern void wutil_Free(void* p);
|
||||
|
||||
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// locks
|
||||
//
|
||||
|
||||
// critical sections used by win-specific code
|
||||
enum WinLockId
|
||||
@ -64,11 +85,11 @@ enum WinLockId
|
||||
NUM_CS
|
||||
};
|
||||
|
||||
extern void win_lock(WinLockId id);
|
||||
extern void win_unlock(WinLockId id);
|
||||
extern void wutil_Lock(WinLockId id);
|
||||
extern void wutil_Unlock(WinLockId id);
|
||||
|
||||
// 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
|
||||
{
|
||||
@ -76,12 +97,12 @@ public:
|
||||
WinScopedLock(WinLockId id)
|
||||
: m_id(id)
|
||||
{
|
||||
win_lock(m_id);
|
||||
wutil_Lock(m_id);
|
||||
}
|
||||
|
||||
~WinScopedLock()
|
||||
{
|
||||
win_unlock(m_id);
|
||||
wutil_Unlock(m_id);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -89,9 +110,8 @@ private:
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// errors
|
||||
//
|
||||
|
||||
/**
|
||||
* 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)
|
||||
|
||||
/// 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);
|
||||
|
||||
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// command line
|
||||
//
|
||||
|
||||
extern int wutil_argc;
|
||||
extern wchar_t** wutil_argv;
|
||||
extern int wutil_argc();
|
||||
extern wchar_t** wutil_argv();
|
||||
|
||||
extern bool wutil_HasCommandLineArgument(const wchar_t* arg);
|
||||
|
||||
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// directories
|
||||
//
|
||||
|
||||
// used by wutil_ExecutablePath, but provided in case other code
|
||||
// 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();
|
||||
|
||||
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// version
|
||||
//
|
||||
|
||||
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_XP64 = 0x0502;
|
||||
const size_t WUTIL_VERSION_VISTA = 0x0600;
|
||||
const size_t WUTIL_VERSION_7 = 0x0601;
|
||||
|
||||
/**
|
||||
* @return short textual representation of the appropriate WUTIL_VERSION
|
||||
@ -178,9 +198,8 @@ extern const wchar_t* wutil_WindowsFamily();
|
||||
extern size_t wutil_WindowsVersion();
|
||||
|
||||
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// Wow64
|
||||
//
|
||||
|
||||
extern bool wutil_IsWow64();
|
||||
|
||||
@ -195,12 +214,14 @@ private:
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* module handle of lib code (that of the main EXE if linked statically,
|
||||
* otherwise the DLL).
|
||||
* @return module handle of lib code (that of the main EXE if
|
||||
* linked statically, otherwise the DLL).
|
||||
* this is necessary for the error dialog.
|
||||
**/
|
||||
extern HMODULE wutil_LibModuleHandle;
|
||||
extern HMODULE wutil_LibModuleHandle();
|
||||
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user