aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2020-11-18 13:50:20 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2020-11-18 14:30:02 +0100
commit4bade83f0813e94dc2b02942740143edfeb43679 (patch)
tree2ceaf37e432a75392d65ef460e234e609115d3ee
parentconf: do not remigrate configs that are pending deletion (diff)
downloadwireguard-windows-4bade83f0813e94dc2b02942740143edfeb43679.tar.xz
wireguard-windows-4bade83f0813e94dc2b02942740143edfeb43679.zip
installer: check for KB2921916's setupapi.dll directly
Some people might have the right setupapi.dll without actually having installed the quickfix. Search for a distinguishing feature instead. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--installer/customactions.c167
1 files changed, 144 insertions, 23 deletions
diff --git a/installer/customactions.c b/installer/customactions.c
index b61fd554..2cb629c2 100644
--- a/installer/customactions.c
+++ b/installer/customactions.c
@@ -122,6 +122,118 @@ out:
return ret;
}
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define BITOP(a, b, op) ((a)[(size_t)(b) / (8 * sizeof *(a))] op(size_t) 1 << ((size_t)(b) % (8 * sizeof *(a))))
+
+static char *memmem(const void *h0, size_t k, const void *n0, size_t l)
+{
+ const unsigned char *n = n0;
+ const unsigned char *h = h0;
+ const unsigned char *z = h + k;
+ size_t i, ip, jp, p, ms, p0, mem, mem0;
+ size_t byteset[32 / sizeof(size_t)] = { 0 };
+ size_t shift[256];
+
+ /* Computing length of needle and fill shift table */
+ for (i = 0; i < l; i++)
+ BITOP(byteset, n[i], |=), shift[n[i]] = i + 1;
+
+ /* Compute maximal suffix */
+ ip = -1;
+ jp = 0;
+ k = p = 1;
+ while (jp + k < l) {
+ if (n[ip + k] == n[jp + k]) {
+ if (k == p) {
+ jp += p;
+ k = 1;
+ } else
+ k++;
+ } else if (n[ip + k] > n[jp + k]) {
+ jp += k;
+ k = 1;
+ p = jp - ip;
+ } else {
+ ip = jp++;
+ k = p = 1;
+ }
+ }
+ ms = ip;
+ p0 = p;
+
+ /* And with the opposite comparison */
+ ip = -1;
+ jp = 0;
+ k = p = 1;
+ while (jp + k < l) {
+ if (n[ip + k] == n[jp + k]) {
+ if (k == p) {
+ jp += p;
+ k = 1;
+ } else
+ k++;
+ } else if (n[ip + k] < n[jp + k]) {
+ jp += k;
+ k = 1;
+ p = jp - ip;
+ } else {
+ ip = jp++;
+ k = p = 1;
+ }
+ }
+ if (ip + 1 > ms + 1)
+ ms = ip;
+ else
+ p = p0;
+
+ /* Periodic needle? */
+ if (memcmp(n, n + p, ms + 1)) {
+ mem0 = 0;
+ p = MAX(ms, l - ms - 1) + 1;
+ } else
+ mem0 = l - p;
+ mem = 0;
+
+ /* Search loop */
+ for (;;) {
+ /* If remainder of haystack is shorter than needle, done */
+ if (z - h < l)
+ return 0;
+
+ /* Check last byte first; advance by shift on mismatch */
+ if (BITOP(byteset, h[l - 1], &)) {
+ k = l - shift[h[l - 1]];
+ if (k) {
+ if (k < mem)
+ k = mem;
+ h += k;
+ mem = 0;
+ continue;
+ }
+ } else {
+ h += l;
+ mem = 0;
+ continue;
+ }
+
+ /* Compare right half */
+ for (k = MAX(ms + 1, mem); k < l && n[k] == h[k]; k++)
+ ;
+ if (k < l) {
+ h += k - ms;
+ mem = 0;
+ continue;
+ }
+ /* Compare left half */
+ for (k = ms + 1; k > mem && n[k - 1] == h[k - 1]; k--)
+ ;
+ if (k <= mem)
+ return (char *)h;
+ h += p;
+ mem = mem0;
+ }
+}
+
extern NTAPI __declspec(dllimport) void RtlGetNtVersionNumbers(DWORD *MajorVersion, DWORD *MinorVersion, DWORD *BuildNumber);
__declspec(dllexport) UINT __stdcall CheckKB2921916(MSIHANDLE installer)
@@ -129,39 +241,44 @@ __declspec(dllexport) UINT __stdcall CheckKB2921916(MSIHANDLE installer)
bool is_com_initialized = SUCCEEDED(CoInitialize(NULL));
UINT ret = ERROR_SUCCESS;
DWORD maj, min, build, len;
- HKEY packageKey;
- TCHAR subkeyName[0x1000], uiLevel[10];
+ TCHAR uiLevel[10];
MSIHANDLE record;
+ TCHAR setupapi_path[MAX_PATH];
+ HANDLE setupapi_handle = INVALID_HANDLE_VALUE;
+ HANDLE setupapi_filemapping = NULL;
+ void *setupapi_bytes = NULL;
+ MEMORY_BASIC_INFORMATION setupapi_meminfo;
+ static const char setupapi_marker[] = "Signature Hash";
RtlGetNtVersionNumbers(&maj, &min, &build);
if (maj != 6 || min != 1)
goto out;
- ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Component Based Servicing\\Packages"), 0, KEY_ENUMERATE_SUB_KEYS, &packageKey);
- if (ret != ERROR_SUCCESS) {
- log_errorf(installer, LOG_LEVEL_ERR, ret, TEXT("Unable to open Component Based Servicing\\Packages registry key"));
+ ret = ERROR_INSTALL_FAILURE;
+ if (!GetSystemDirectory(setupapi_path, _countof(setupapi_path)))
+ goto out;
+ if (!PathAppend(setupapi_path, TEXT("setupapi.dll")))
+ goto out;
+ setupapi_handle = CreateFile(setupapi_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (setupapi_handle == INVALID_HANDLE_VALUE)
+ goto out;
+ setupapi_filemapping = CreateFileMapping(setupapi_handle, NULL, PAGE_READONLY, 0, 0, NULL);
+ if (!setupapi_filemapping)
+ goto out;
+ setupapi_bytes = MapViewOfFile(setupapi_filemapping, FILE_MAP_READ, 0, 0, 0);
+ if (!setupapi_bytes)
+ goto out;
+ if (VirtualQuery(setupapi_bytes, &setupapi_meminfo, sizeof(setupapi_meminfo)) != sizeof(setupapi_meminfo))
+ goto out;
+ if (memmem(setupapi_bytes, setupapi_meminfo.RegionSize, setupapi_marker, strlen(setupapi_marker))) {
+ ret = ERROR_SUCCESS;
goto out;
}
- for (DWORD i = 0;; ++i) {
- len = _countof(subkeyName);
- ret = RegEnumKeyEx(packageKey, i, subkeyName, &len, NULL, NULL, NULL, NULL);
- if (ret == ERROR_NO_MORE_ITEMS)
- break;
- if (ret == ERROR_MORE_DATA)
- continue;
- if (ret != ERROR_SUCCESS) {
- log_errorf(installer, LOG_LEVEL_ERR, ret, TEXT("Unable to enumerate Component Based Servicing\\Packages registry key"));
- goto close_key;
- }
- if (_tcsstr(subkeyName, TEXT("KB2921916")))
- goto close_key;
- }
- ret = ERROR_INSTALL_FAILURE;
len = _countof(uiLevel);
if (MsiGetProperty(installer, TEXT("UILevel"), uiLevel, &len) != ERROR_SUCCESS || _tcstoul(uiLevel, NULL, 10) < INSTALLUILEVEL_BASIC) {
log_messagef(installer, LOG_LEVEL_MSIERR, TEXT("Use of WireGuard on Windows 7 requires KB2921916."));
- goto close_key;
+ goto out;
}
#ifdef _WIN64
@@ -176,9 +293,13 @@ __declspec(dllexport) UINT __stdcall CheckKB2921916(MSIHANDLE installer)
ShellExecute(GetForegroundWindow(), NULL, url, NULL, NULL, SW_SHOWNORMAL);
MsiCloseHandle(record);
-close_key:
- RegCloseKey(packageKey);
out:
+ if (setupapi_bytes)
+ UnmapViewOfFile(setupapi_bytes);
+ if (setupapi_filemapping)
+ CloseHandle(setupapi_filemapping);
+ if (setupapi_handle != INVALID_HANDLE_VALUE)
+ CloseHandle(setupapi_handle);
if (is_com_initialized)
CoUninitialize();
return ret;