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