janwas
2374caac3e
. completely rewrite waio - use IOCP, add several hardcore optimizations. now outperforms the AS SSD and ATTO benchmarks when writing . refactor file interface - use LIO_READ instead of 'r', allow access to file descriptor. . completely rewrite the IO wrapper. now much more simple, less CPU overhead, adds support for pre-issue/post-completion hooks and preallocation. io::Run defaults to simple synchronous IO; use io::Parameters to get asynchronous. . add alignment.h with constants and Align() function template (more efficient than round_up for compile-time constants) . add UniqueRange - similar to C++0x unique_ptr (emulated for C++03), plus a built-in size. avoids expensive thread-safe reference counting in shared_ptr. cleanup: - move fat_time functions into archive_zip - remove no longer needed io_align and block_cache - reduce dependencies in sysdep/compiler (move parts to code_annotation.h) - move IOCP into separate file (reused by waio) This was SVN commit r9350.
214 lines
5.6 KiB
C++
214 lines
5.6 KiB
C++
/* Copyright (c) 2010 Wildfire Games
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining
|
|
* a copy of this software and associated documentation files (the
|
|
* "Software"), to deal in the Software without restriction, including
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
* the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
/*
|
|
* various Windows-specific utilities
|
|
*/
|
|
|
|
#ifndef INCLUDED_WUTIL
|
|
#define INCLUDED_WUTIL
|
|
|
|
#include "lib/os_path.h"
|
|
#include "lib/sysdep/os/win/win.h"
|
|
|
|
template<typename H>
|
|
bool wutil_IsValidHandle(H h)
|
|
{
|
|
return h != 0 && h != INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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* wutil_Allocate(size_t size);
|
|
extern void wutil_Free(void* p);
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// locks
|
|
|
|
// critical sections used by win-specific code
|
|
enum WinLockId
|
|
{
|
|
WDBG_SYM_CS, // protects (non-reentrant) dbghelp.dll
|
|
WDIR_WATCH_CS,
|
|
|
|
NUM_CS
|
|
};
|
|
|
|
extern void wutil_Lock(WinLockId id);
|
|
extern void wutil_Unlock(WinLockId id);
|
|
|
|
// used in a desperate attempt to avoid deadlock in wseh.
|
|
extern bool wutil_IsLocked(WinLockId id);
|
|
|
|
class WinScopedLock
|
|
{
|
|
public:
|
|
WinScopedLock(WinLockId id)
|
|
: m_id(id)
|
|
{
|
|
wutil_Lock(m_id);
|
|
}
|
|
|
|
~WinScopedLock()
|
|
{
|
|
wutil_Unlock(m_id);
|
|
}
|
|
|
|
private:
|
|
WinLockId m_id;
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// errors
|
|
|
|
/**
|
|
* some WinAPI functions SetLastError(0) on success, which is bad because
|
|
* it can hide previous errors. this class takes care of restoring the
|
|
* previous value.
|
|
**/
|
|
class WinScopedPreserveLastError
|
|
{
|
|
public:
|
|
WinScopedPreserveLastError()
|
|
: m_lastError(GetLastError())
|
|
{
|
|
SetLastError(0);
|
|
}
|
|
|
|
~WinScopedPreserveLastError()
|
|
{
|
|
if(m_lastError != 0 && GetLastError() == 0)
|
|
SetLastError(m_lastError);
|
|
}
|
|
|
|
private:
|
|
DWORD m_lastError;
|
|
};
|
|
|
|
|
|
/**
|
|
* @return the LibError equivalent of GetLastError(), or ERR::FAIL if
|
|
* there's no equivalent.
|
|
* you should SetLastError(0) before calling whatever will set ret
|
|
* to make sure we do not report any stale errors.
|
|
*
|
|
* @param warn_if_failed if set, raises an error dialog that reports
|
|
* the LibError.
|
|
**/
|
|
LibError LibError_from_GLE(bool warn_if_failed = true);
|
|
|
|
#define WARN_WIN32_ERR (void)LibError_from_GLE(true)
|
|
|
|
/**
|
|
* @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 bool wutil_HasCommandLineArgument(const wchar_t* arg);
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// directories
|
|
|
|
extern const OsPath& wutil_SystemPath();
|
|
extern const OsPath& wutil_ExecutablePath();
|
|
extern const OsPath& wutil_AppdataPath();
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Wow64
|
|
|
|
extern bool wutil_IsWow64();
|
|
|
|
class WinScopedDisableWow64Redirection
|
|
{
|
|
public:
|
|
WinScopedDisableWow64Redirection();
|
|
~WinScopedDisableWow64Redirection();
|
|
|
|
private:
|
|
void* m_wasRedirectionEnabled;
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
LIB_API LibError wutil_SetPrivilege(const wchar_t* privilege, bool enable);
|
|
|
|
/**
|
|
* @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();
|
|
|
|
|
|
/**
|
|
* @return handle to the first window owned by the current process, or
|
|
* 0 if none exist (e.g. it hasn't yet created one).
|
|
*
|
|
* enumerates all top-level windows and stops if PID matches.
|
|
* once this function returns a non-NULL handle, it will always
|
|
* return that cached value.
|
|
**/
|
|
extern HWND wutil_AppWindow();
|
|
|
|
#endif // #ifndef INCLUDED_WUTIL
|