|
1
|
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 }
|