comparison 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
comparison
equal deleted inserted replaced
0:e9bb126753e7 1:20d02a178406
1 #include "shared.h"
2
3 #include <mutex>
4
5 static std::once_flag g_infinitWaitInit;
6 static HANDLE g_infinitWaitEvent = NULL;
7
8 HANDLE SHARED_EXPORT GetInfiniteWaitEvent() {
9 std::call_once(g_infinitWaitInit, [] {
10 g_infinitWaitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
11 } );
12 return g_infinitWaitEvent;
13 }
14
15 struct createFileRequest {
16 TCHAR * lpFileName;
17 DWORD dwDesiredAccess;
18 DWORD dwShareMode;
19 LPSECURITY_ATTRIBUTES lpSecurityAttributes;
20 DWORD dwCreationDisposition;
21 DWORD dwFlagsAndAttributes;
22
23 HANDLE hResultHandle;
24
25 DWORD dwErrorCode;
26
27 volatile LONG refCounter;
28
29 void Delete() {
30 free(lpFileName);
31 if (hResultHandle != INVALID_HANDLE_VALUE) CloseHandle(hResultHandle);
32 delete this;
33 }
34
35 void Release() {
36 if (InterlockedDecrement(&refCounter) == 0) {
37 Delete();
38 }
39 }
40 };
41
42 static unsigned CALLBACK createFileThread(void* p) {
43 createFileRequest * req = reinterpret_cast<createFileRequest*>(p);
44
45 SetLastError(0);
46 req->hResultHandle = CreateFile(req->lpFileName, req->dwDesiredAccess, req->dwShareMode, req->lpSecurityAttributes, req->dwCreationDisposition, req->dwFlagsAndAttributes, NULL);
47 req->dwErrorCode = GetLastError();
48
49 req->Release();
50 return 0;
51 }
52
53
54 HANDLE SHARED_EXPORT CreateFileAbortable( __in LPCWSTR lpFileName,
55 __in DWORD dwDesiredAccess,
56 __in DWORD dwShareMode,
57 __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
58 __in DWORD dwCreationDisposition,
59 __in DWORD dwFlagsAndAttributes,
60 __in_opt HANDLE hAborter
61 ) {
62 if (hAborter == NULL || hAborter == GetInfiniteWaitEvent()) {
63 return CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, NULL);
64 }
65 switch(WaitForSingleObject(hAborter, 0)) {
66 case WAIT_TIMEOUT:
67 break;
68 case WAIT_OBJECT_0:
69 SetLastError(ERROR_OPERATION_ABORTED);
70 return INVALID_HANDLE_VALUE;
71 default:
72 return INVALID_HANDLE_VALUE;
73 }
74
75 createFileRequest * req = new createFileRequest();
76 req->lpFileName = _tcsdup(lpFileName);
77 req->dwDesiredAccess = dwDesiredAccess;
78 req->dwShareMode = dwShareMode;
79 req->lpSecurityAttributes = lpSecurityAttributes;
80 req->dwCreationDisposition = dwCreationDisposition;
81 req->dwFlagsAndAttributes = dwFlagsAndAttributes;
82 req->hResultHandle = INVALID_HANDLE_VALUE;
83 req->dwErrorCode = 0;
84 req->refCounter = 2;
85
86 HANDLE hThread = (HANDLE) _beginthreadex(NULL, 0, createFileThread, req, CREATE_SUSPENDED, NULL);
87 if (hThread == NULL) {
88 req->Delete();
89 return INVALID_HANDLE_VALUE;
90 }
91 SetThreadPriority(hThread, GetThreadPriority(GetCurrentThread()));
92 ResumeThread(hThread);
93
94 DWORD waitStatus;
95 {
96 HANDLE waits[2] = {hThread, hAborter};
97 waitStatus = WaitForMultipleObjects(2, waits, FALSE, INFINITE);
98 }
99 HANDLE hRetVal = INVALID_HANDLE_VALUE;
100 DWORD dwErrorCode = 0;
101 switch(waitStatus) {
102 case WAIT_OBJECT_0: // thread completed
103 hRetVal = req->hResultHandle;
104 req->hResultHandle = INVALID_HANDLE_VALUE;
105 dwErrorCode = req->dwErrorCode;
106 break;
107 case WAIT_OBJECT_0 + 1: // aborted
108 dwErrorCode = ERROR_OPERATION_ABORTED;
109 CancelSynchronousIo(hThread);
110 break;
111 default: // unexpected, use last-error code from WFMO
112 dwErrorCode = GetLastError();
113 CancelSynchronousIo(hThread);
114 break;
115 }
116 req->Release();
117 CloseHandle(hThread);
118 SetLastError(dwErrorCode);
119 return hRetVal;
120 }
121
122 namespace pfc {
123 BOOL winFormatSystemErrorMessageImpl(pfc::string_base & p_out, DWORD p_code);
124 BOOL winFormatSystemErrorMessageHook(pfc::string_base & p_out, DWORD p_code) {
125 return winFormatSystemErrorMessageImpl(p_out, p_code);
126 }
127
128 void crashHook() {
129 uBugCheck();
130 }
131 }