1
0
forked from 0ad/0ad

fixes+improvements from work (overhaul wutil, add convenience macros for DLL imports)

This was SVN commit r7717.
This commit is contained in:
janwas 2010-07-08 10:18:42 +00:00
parent 0c149cf447
commit 8c1bd05ab9
6 changed files with 173 additions and 102 deletions

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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();
/** /**