aboutsummaryrefslogtreecommitdiffstats
path: root/api/resource.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--api/resource.c129
1 files changed, 129 insertions, 0 deletions
diff --git a/api/resource.c b/api/resource.c
new file mode 100644
index 0000000..648f568
--- /dev/null
+++ b/api/resource.c
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
+ */
+
+#include "logger.h"
+#include "main.h"
+#include "resource.h"
+#include <Windows.h>
+#include <Shlwapi.h>
+#include <NTSecAPI.h>
+
+_Use_decl_annotations_
+const VOID *
+ResourceGetAddress(LPCWSTR ResourceName, DWORD *Size)
+{
+ HRSRC FoundResource = FindResourceW(ResourceModule, ResourceName, RT_RCDATA);
+ if (!FoundResource)
+ {
+ LOG_LAST_ERROR(L"Failed to find resource %s", ResourceName);
+ return NULL;
+ }
+ *Size = SizeofResource(ResourceModule, FoundResource);
+ if (!*Size)
+ {
+ LOG_LAST_ERROR(L"Failed to query resource %s size", ResourceName);
+ return NULL;
+ }
+ HGLOBAL LoadedResource = LoadResource(ResourceModule, FoundResource);
+ if (!LoadedResource)
+ {
+ LOG_LAST_ERROR(L"Failed to load resource %s", ResourceName);
+ return NULL;
+ }
+ BYTE *Address = LockResource(LoadedResource);
+ if (!Address)
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to lock resource %s", ResourceName);
+ SetLastError(ERROR_LOCK_FAILED);
+ return NULL;
+ }
+ return Address;
+}
+
+_Use_decl_annotations_
+BOOL
+ResourceCopyToFile(LPCWSTR DestinationPath, LPCWSTR ResourceName)
+{
+ DWORD SizeResource;
+ const VOID *LockedResource = ResourceGetAddress(ResourceName, &SizeResource);
+ if (!LockedResource)
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to locate resource %s", ResourceName);
+ return FALSE;
+ }
+ HANDLE DestinationHandle = CreateFileW(
+ DestinationPath,
+ GENERIC_WRITE,
+ 0,
+ &SecurityAttributes,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY,
+ NULL);
+ if (DestinationHandle == INVALID_HANDLE_VALUE)
+ {
+ LOG_LAST_ERROR(L"Failed to create file %s", DestinationPath);
+ return FALSE;
+ }
+ DWORD BytesWritten;
+ DWORD LastError;
+ if (!WriteFile(DestinationHandle, LockedResource, SizeResource, &BytesWritten, NULL))
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to write file %s", DestinationPath);
+ goto cleanupDestinationHandle;
+ }
+ if (BytesWritten != SizeResource)
+ {
+ LOG(WINTUN_LOG_ERR,
+ L"Incomplete write to %s (written: %u, expected: %u)",
+ DestinationPath,
+ BytesWritten,
+ SizeResource);
+ LastError = ERROR_WRITE_FAULT;
+ goto cleanupDestinationHandle;
+ }
+ LastError = ERROR_SUCCESS;
+cleanupDestinationHandle:
+ CloseHandle(DestinationHandle);
+ return RET_ERROR(TRUE, LastError);
+}
+
+_Return_type_success_(return != FALSE)
+BOOL
+ResourceCreateTemporaryDirectory(_Out_writes_z_(MAX_PATH) LPWSTR RandomTempSubDirectory)
+{
+ WCHAR WindowsDirectory[MAX_PATH];
+ if (!GetWindowsDirectoryW(WindowsDirectory, _countof(WindowsDirectory)))
+ {
+ LOG_LAST_ERROR(L"Failed to get Windows folder");
+ return FALSE;
+ }
+ WCHAR WindowsTempDirectory[MAX_PATH];
+ if (!PathCombineW(WindowsTempDirectory, WindowsDirectory, L"Temp"))
+ {
+ SetLastError(ERROR_BUFFER_OVERFLOW);
+ return FALSE;
+ }
+ UCHAR RandomBytes[32] = { 0 };
+ if (!RtlGenRandom(RandomBytes, sizeof(RandomBytes)))
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to generate random");
+ SetLastError(ERROR_GEN_FAILURE);
+ return FALSE;
+ }
+ WCHAR RandomSubDirectory[sizeof(RandomBytes) * 2 + 1];
+ for (int i = 0; i < sizeof(RandomBytes); ++i)
+ swprintf_s(&RandomSubDirectory[i * 2], 3, L"%02x", RandomBytes[i]);
+ if (!PathCombineW(RandomTempSubDirectory, WindowsTempDirectory, RandomSubDirectory))
+ {
+ SetLastError(ERROR_BUFFER_OVERFLOW);
+ return FALSE;
+ }
+ if (!CreateDirectoryW(RandomTempSubDirectory, &SecurityAttributes))
+ {
+ LOG_LAST_ERROR(L"Failed to create temporary folder %s", RandomTempSubDirectory);
+ return FALSE;
+ }
+ return TRUE;
+}