Mercurial > foo_out_sdl
view foosdk/sdk/foobar2000/shared/Utility.cpp @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
line wrap: on
line source
#include "shared.h" #include <mutex> static std::once_flag g_infinitWaitInit; static HANDLE g_infinitWaitEvent = NULL; HANDLE SHARED_EXPORT GetInfiniteWaitEvent() { std::call_once(g_infinitWaitInit, [] { g_infinitWaitEvent = CreateEvent(NULL, TRUE, FALSE, NULL); } ); return g_infinitWaitEvent; } struct createFileRequest { TCHAR * lpFileName; DWORD dwDesiredAccess; DWORD dwShareMode; LPSECURITY_ATTRIBUTES lpSecurityAttributes; DWORD dwCreationDisposition; DWORD dwFlagsAndAttributes; HANDLE hResultHandle; DWORD dwErrorCode; volatile LONG refCounter; void Delete() { free(lpFileName); if (hResultHandle != INVALID_HANDLE_VALUE) CloseHandle(hResultHandle); delete this; } void Release() { if (InterlockedDecrement(&refCounter) == 0) { Delete(); } } }; static unsigned CALLBACK createFileThread(void* p) { createFileRequest * req = reinterpret_cast<createFileRequest*>(p); SetLastError(0); req->hResultHandle = CreateFile(req->lpFileName, req->dwDesiredAccess, req->dwShareMode, req->lpSecurityAttributes, req->dwCreationDisposition, req->dwFlagsAndAttributes, NULL); req->dwErrorCode = GetLastError(); req->Release(); return 0; } HANDLE SHARED_EXPORT CreateFileAbortable( __in LPCWSTR lpFileName, __in DWORD dwDesiredAccess, __in DWORD dwShareMode, __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, __in DWORD dwCreationDisposition, __in DWORD dwFlagsAndAttributes, __in_opt HANDLE hAborter ) { if (hAborter == NULL || hAborter == GetInfiniteWaitEvent()) { return CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, NULL); } switch(WaitForSingleObject(hAborter, 0)) { case WAIT_TIMEOUT: break; case WAIT_OBJECT_0: SetLastError(ERROR_OPERATION_ABORTED); return INVALID_HANDLE_VALUE; default: return INVALID_HANDLE_VALUE; } createFileRequest * req = new createFileRequest(); req->lpFileName = _tcsdup(lpFileName); req->dwDesiredAccess = dwDesiredAccess; req->dwShareMode = dwShareMode; req->lpSecurityAttributes = lpSecurityAttributes; req->dwCreationDisposition = dwCreationDisposition; req->dwFlagsAndAttributes = dwFlagsAndAttributes; req->hResultHandle = INVALID_HANDLE_VALUE; req->dwErrorCode = 0; req->refCounter = 2; HANDLE hThread = (HANDLE) _beginthreadex(NULL, 0, createFileThread, req, CREATE_SUSPENDED, NULL); if (hThread == NULL) { req->Delete(); return INVALID_HANDLE_VALUE; } SetThreadPriority(hThread, GetThreadPriority(GetCurrentThread())); ResumeThread(hThread); DWORD waitStatus; { HANDLE waits[2] = {hThread, hAborter}; waitStatus = WaitForMultipleObjects(2, waits, FALSE, INFINITE); } HANDLE hRetVal = INVALID_HANDLE_VALUE; DWORD dwErrorCode = 0; switch(waitStatus) { case WAIT_OBJECT_0: // thread completed hRetVal = req->hResultHandle; req->hResultHandle = INVALID_HANDLE_VALUE; dwErrorCode = req->dwErrorCode; break; case WAIT_OBJECT_0 + 1: // aborted dwErrorCode = ERROR_OPERATION_ABORTED; CancelSynchronousIo(hThread); break; default: // unexpected, use last-error code from WFMO dwErrorCode = GetLastError(); CancelSynchronousIo(hThread); break; } req->Release(); CloseHandle(hThread); SetLastError(dwErrorCode); return hRetVal; } namespace pfc { BOOL winFormatSystemErrorMessageImpl(pfc::string_base & p_out, DWORD p_code); BOOL winFormatSystemErrorMessageHook(pfc::string_base & p_out, DWORD p_code) { return winFormatSystemErrorMessageImpl(p_out, p_code); } void crashHook() { uBugCheck(); } }
