diff 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 diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/foosdk/sdk/foobar2000/shared/Utility.cpp	Mon Jan 05 02:15:46 2026 -0500
@@ -0,0 +1,131 @@
+#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(); 
+	}
+}