forked from mirrors/0ad
fix error propagation/avoid SetLastError pollution
This was SVN commit r9411.
This commit is contained in:
@@ -130,6 +130,7 @@ STATUS_DEFINE(ERR, TIMED_OUT, L"Timed out", -1);
|
||||
STATUS_DEFINE(ERR, REENTERED, L"Single-call function was reentered", -1);
|
||||
STATUS_DEFINE(ERR, CORRUPTED, L"File/memory data is corrupted", -1);
|
||||
STATUS_DEFINE(ERR, VERSION, L"Version mismatch", -1);
|
||||
STATUS_DEFINE(ERR, ABORTED, L"Operation aborted", -1);
|
||||
|
||||
STATUS_DEFINE(ERR, INVALID_PARAM, L"Invalid function argument", EINVAL);
|
||||
STATUS_DEFINE(ERR, INVALID_HANDLE, L"Invalid Handle (argument)", -1);
|
||||
|
||||
+2
-1
@@ -251,7 +251,7 @@ extern Status StatusFromErrno();
|
||||
{\
|
||||
const Status status_ = (expression);\
|
||||
if(status_ < 0)\
|
||||
DEBUG_WARN_ERR(status_);\
|
||||
DEBUG_WARN_ERR(status_);\
|
||||
}\
|
||||
while(0)
|
||||
|
||||
@@ -375,6 +375,7 @@ namespace ERR
|
||||
const Status REENTERED = -100012;
|
||||
const Status CORRUPTED = -100013;
|
||||
const Status VERSION = -100014;
|
||||
const Status ABORTED = -100015;
|
||||
|
||||
// function arguments
|
||||
const Status INVALID_PARAM = -100020;
|
||||
|
||||
@@ -251,7 +251,11 @@ static void StartDriver(const OsPath& driverPathname)
|
||||
{
|
||||
const SC_HANDLE hSCM = OpenServiceControlManager();
|
||||
if(!hSCM)
|
||||
{
|
||||
ENSURE(GetLastError() == ERROR_ACCESS_DENIED);
|
||||
SetLastError(0);
|
||||
return;
|
||||
}
|
||||
|
||||
SC_HANDLE hService = OpenServiceW(hSCM, AKEN_NAME, SERVICE_ALL_ACCESS);
|
||||
|
||||
@@ -328,6 +332,8 @@ static OsPath DriverPathname()
|
||||
|
||||
static Status Init()
|
||||
{
|
||||
WinScopedPreserveLastError s;
|
||||
|
||||
if(wutil_HasCommandLineArgument(L"-wNoMahaf"))
|
||||
return ERR::NOT_SUPPORTED; // NOWARN
|
||||
|
||||
@@ -340,7 +346,11 @@ static Status Init()
|
||||
const DWORD shareMode = 0;
|
||||
hAken = CreateFileW(L"\\\\.\\Aken", GENERIC_READ, shareMode, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if(hAken == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
ENSURE(GetLastError() == ERROR_FILE_NOT_FOUND);
|
||||
SetLastError(0);
|
||||
return ERR::INVALID_HANDLE; // NOWARN (happens often due to security restrictions)
|
||||
}
|
||||
}
|
||||
|
||||
return INFO::OK;
|
||||
|
||||
@@ -333,16 +333,12 @@ public:
|
||||
|
||||
Status Poll(DirWatchNotifications& notifications)
|
||||
{
|
||||
POLL_AGAIN:
|
||||
DWORD bytesTransferred; ULONG_PTR key; OVERLAPPED* ovl;
|
||||
for(;;) // skip notifications of canceled watches
|
||||
{
|
||||
const Status ret = PollCompletionPort(hIOCP, 0, bytesTransferred, key, ovl);
|
||||
if(ret == INFO::OK)
|
||||
break;
|
||||
if(GetLastError() == ERROR_OPERATION_ABORTED)
|
||||
continue; // watch was canceled - ignore
|
||||
return ret;
|
||||
}
|
||||
const Status ret = PollCompletionPort(hIOCP, 0, bytesTransferred, key, ovl);
|
||||
if(ret == ERR::ABORTED) // watch was canceled
|
||||
goto POLL_AGAIN;
|
||||
RETURN_STATUS_IF_ERR(ret);
|
||||
|
||||
DirWatchRequest* request = (DirWatchRequest*)key;
|
||||
request->RetrieveNotifications(notifications);
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include <process.h> // _beginthreadex
|
||||
|
||||
#include "lib/sysdep/cpu.h"
|
||||
#include "lib/sysdep/os/win/win.h"
|
||||
#include "lib/sysdep/os/win/wutil.h"
|
||||
#include "lib/sysdep/os/win/winit.h"
|
||||
#include "lib/sysdep/acpi.h"
|
||||
#include "lib/bits.h"
|
||||
@@ -261,6 +261,8 @@ static unsigned __stdcall UpdateThread(void* UNUSED(data))
|
||||
|
||||
static inline Status InitUpdateThread()
|
||||
{
|
||||
WinScopedPreserveLastError s; // CreateEvent
|
||||
|
||||
// make sure our interval isn't too long
|
||||
// (counterBits can be 64 => Bit() would overflow => calculate period/2)
|
||||
const double period_2 = Bit<u64>(counterBits-1) / nominalFrequency;
|
||||
|
||||
@@ -20,13 +20,15 @@ Status PollCompletionPort(HANDLE hIOCP, DWORD timeout, DWORD& bytesTransferred,
|
||||
if(hIOCP == 0)
|
||||
return ERR::INVALID_HANDLE; // NOWARN (happens if called before the first Attach)
|
||||
|
||||
WinScopedPreserveLastError s;
|
||||
|
||||
bytesTransferred = 0;
|
||||
key = 0;
|
||||
ovl = 0;
|
||||
if(GetQueuedCompletionStatus(hIOCP, &bytesTransferred, &key, &ovl, timeout))
|
||||
return INFO::OK;
|
||||
if(GetLastError() == WAIT_TIMEOUT)
|
||||
return ERR::AGAIN; // NOWARN (nothing pending)
|
||||
else
|
||||
return ERR::FAIL; // NOWARN (let caller decide what to do)
|
||||
const Status ret = StatusFromWin();
|
||||
if(ret == ERR::AGAIN || ret == ERR::ABORTED) // avoid polluting last error
|
||||
SetLastError(0);
|
||||
return StatusFromWin(); // NOWARN (let caller decide what to do)
|
||||
}
|
||||
|
||||
@@ -156,8 +156,10 @@ struct wdirent* wreaddir(WDIR* d)
|
||||
{
|
||||
if(!FindNextFileW(d->hFind, &d->findData))
|
||||
{
|
||||
if(GetLastError() != ERROR_NO_MORE_FILES) // an actual error occurred
|
||||
WARN_IF_ERR(StatusFromWin());
|
||||
if(GetLastError() == ERROR_NO_MORE_FILES)
|
||||
SetLastError(0);
|
||||
else // unexpected error
|
||||
DEBUG_WARN_ERR(StatusFromWin());
|
||||
return 0; // end of directory or error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1485,6 +1485,8 @@ static void RedirectStdout()
|
||||
if(wutil_IsValidHandle(GetStdHandle(STD_OUTPUT_HANDLE)))
|
||||
return;
|
||||
|
||||
WinScopedPreserveLastError s; // ChangeExtension
|
||||
|
||||
// this code may be included in multiple executables sharing the same
|
||||
// directory, so include the executable's name in the filename. use its
|
||||
// full path since the current directory is unreliable.
|
||||
@@ -1495,9 +1497,12 @@ static void RedirectStdout()
|
||||
// that means stdout isn't associated with a lowio handle; _close is
|
||||
// called with fd = -1. oh well, there's nothing we can do.
|
||||
FILE* f = 0;
|
||||
// (return value ignored - it indicates 'file already exists' even
|
||||
// if f is valid)
|
||||
(void)_wfreopen_s(&f, OsString(pathname).c_str(), L"wt", stdout);
|
||||
errno_t ret = _wfreopen_s(&f, OsString(pathname).c_str(), L"wt", stdout);
|
||||
// (ignore return value - it might indicate 'file already exists' even
|
||||
// if f is valid, which is what actually counts)
|
||||
UNUSED2(ret);
|
||||
if(GetLastError() == ERROR_ALREADY_EXISTS)
|
||||
SetLastError(0);
|
||||
// executable directory (probably Program Files) is read-only for
|
||||
// non-Administrators. we can't pick another directory because
|
||||
// ah_log_dir might not be valid until the app's init has run,
|
||||
|
||||
@@ -390,6 +390,7 @@ Status sys_get_module_filename(void* addr, OsPath& pathname)
|
||||
|
||||
OsPath sys_ExecutablePathname()
|
||||
{
|
||||
WinScopedPreserveLastError s;
|
||||
OsPath pathname;
|
||||
ENSURE(GetModulePathname(0, pathname) == INFO::OK);
|
||||
return pathname;
|
||||
|
||||
@@ -145,7 +145,10 @@ Status StatusFromWin()
|
||||
case ERROR_PROC_NOT_FOUND:
|
||||
return ERR::NO_SYS;
|
||||
case ERROR_BUSY:
|
||||
case WAIT_TIMEOUT:
|
||||
return ERR::AGAIN;
|
||||
case ERROR_OPERATION_ABORTED:
|
||||
return ERR::ABORTED;
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
return ERR::VFS_FILE_NOT_FOUND;
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
@@ -289,6 +292,8 @@ static void GetDirectories()
|
||||
wchar_t path[MAX_PATH]; // mandated by SHGetFolderPathW
|
||||
const HRESULT ret = SHGetFolderPathW(hwnd, CSIDL_APPDATA, token, 0, path);
|
||||
ENSURE(SUCCEEDED(ret));
|
||||
if(GetLastError() == ERROR_NO_TOKEN) // avoid polluting last error
|
||||
SetLastError(0);
|
||||
appdataPath = new(wutil_Allocate(sizeof(OsPath))) OsPath(path);
|
||||
}
|
||||
}
|
||||
@@ -340,6 +345,14 @@ static void FreeUser32Dll()
|
||||
|
||||
static void EnableLowFragmentationHeap()
|
||||
{
|
||||
if(IsDebuggerPresent())
|
||||
{
|
||||
// and the debug heap isn't explicitly disabled,
|
||||
char* var = getenv("_NO_DEBUG_HEAP");
|
||||
if(!var || var[0] != '1')
|
||||
return; // we can't enable the LFH
|
||||
}
|
||||
|
||||
#if WINVER >= 0x0501
|
||||
WUTIL_FUNC(pHeapSetInformation, BOOL, (HANDLE, HEAP_INFORMATION_CLASS, void*, size_t));
|
||||
WUTIL_IMPORT_KERNEL32(HeapSetInformation, pHeapSetInformation);
|
||||
|
||||
Reference in New Issue
Block a user