aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2020-11-03 17:06:20 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2020-11-03 18:29:52 +0100
commit677ba8680f21539460644ffe16a060be22855894 (patch)
tree5a08b2cf3446f677196ccd23a3971a907d3471d2
parentapi: move nci.lib generation to custom step (diff)
downloadwintun-677ba8680f21539460644ffe16a060be22855894.tar.xz
wintun-677ba8680f21539460644ffe16a060be22855894.zip
wintun: extract inf driverver at compile time into C header
This requires us to make some insane conversions between INF date, JavaScript time, and finally Windows file time. The point is to mimic SystemTimeToFileTime, which is what SpInf.dll's pSetupStringToDriverDate does on the YYYY-MM-DD from the INF. The result is that we no longer have to parse an ancient text format in C at runtime. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--api/adapter.c115
-rw-r--r--api/api.vcxproj1
-rw-r--r--extract-driverver.js17
-rw-r--r--wintun.vcxproj6
4 files changed, 28 insertions, 111 deletions
diff --git a/api/adapter.c b/api/adapter.c
index 602bc8c..d87ed56 100644
--- a/api/adapter.c
+++ b/api/adapter.c
@@ -12,6 +12,7 @@
#include "ntdll.h"
#include "registry.h"
#include "resource.h"
+#include "wintun-inf.h"
#include <Windows.h>
#include <winternl.h>
@@ -950,109 +951,6 @@ cleanupTcpipAdapterRegKey:
return Result;
}
-static const CHAR *
-SkipWSpace(_In_ const CHAR *Beg, _In_ const CHAR *End)
-{
- for (; Beg < End && iswspace(*Beg); ++Beg)
- ;
- return Beg;
-}
-
-static const CHAR *
-SkipNonLF(_In_ const CHAR *Beg, _In_ const CHAR *End)
-{
- for (; Beg < End && *Beg != '\n'; ++Beg)
- ;
- return Beg;
-}
-
-static WINTUN_STATUS
-VersionOfInf(_Out_ FILETIME *DriverDate, _Out_ DWORDLONG *DriverVersion)
-{
- const VOID *LockedResource;
- DWORD SizeResource;
- DWORD Result = ResourceGetAddress(HaveWHQL() ? L"wintun-whql.inf" : L"wintun.inf", &LockedResource, &SizeResource);
- if (Result != ERROR_SUCCESS)
- return LOG(WINTUN_LOG_ERR, L"Failed to locate resource"), Result;
- enum
- {
- SectNone,
- SectUnknown,
- SectVersion
- } Section = SectNone;
- for (const char *Inf = (const char *)LockedResource, *InfEnd = Inf + SizeResource; Inf < InfEnd; ++Inf)
- {
- if (*Inf == ';')
- {
- Inf = SkipNonLF(Inf + 1, InfEnd);
- continue;
- }
- Inf = SkipWSpace(Inf, InfEnd);
- if (*Inf == '[')
- {
- Section = Inf + 9 <= InfEnd && !_strnicmp(Inf, "[Version]", 9) ? SectVersion : SectUnknown;
- }
- else if (Section == SectVersion)
- {
- if (Inf + 9 <= InfEnd && !_strnicmp(Inf, "DriverVer", 9))
- {
- Inf = SkipWSpace(Inf + 9, InfEnd);
- if (Inf < InfEnd && *Inf == '=')
- {
- Inf = SkipWSpace(Inf + 1, InfEnd);
- /* Duplicate buffer, as resource is not zero-terminated. */
- char Buffer[0x100];
- size_t BufferLen = InfEnd - Inf;
- if (BufferLen >= _countof(Buffer))
- BufferLen = _countof(Buffer) - 1;
- strncpy_s(Buffer, _countof(Buffer), Inf, BufferLen);
- Buffer[BufferLen] = 0;
- const char *Ptr = Buffer;
- unsigned long Date[3] = { 0 };
- for (size_t i = 0;; ++i, ++Ptr)
- {
- char *PtrNext;
- Date[i] = strtoul(Ptr, &PtrNext, 10);
- Ptr = PtrNext;
- if (i >= _countof(Date) - 1)
- break;
- if (*Ptr != '/' && *Ptr != '-')
- return LOG(WINTUN_LOG_ERR, L"Unexpected date delimiter"), ERROR_INVALID_DATA;
- }
- if (Date[0] < 1 || Date[0] > 12 || Date[1] < 1 || Date[1] > 31 || Date[2] < 1601 || Date[2] > 30827)
- return LOG(WINTUN_LOG_ERR, L"Invalid date"), ERROR_INVALID_DATA;
- const SYSTEMTIME SystemTime = { .wYear = (WORD)Date[2], .wMonth = (WORD)Date[0], .wDay = (WORD)Date[1] };
- if (!SystemTimeToFileTime(&SystemTime, DriverDate))
- return LOG_LAST_ERROR(L"Failed to convert system time to file time");
- Ptr = SkipWSpace(Ptr, Buffer + BufferLen);
- ULONGLONG Version[4] = { 0 };
- if (*Ptr == ',')
- {
- Ptr = SkipWSpace(Ptr + 1, Buffer + BufferLen);
- for (size_t i = 0;; ++i, ++Ptr)
- {
- char *PtrNext;
- Version[i] = strtoul(Ptr, &PtrNext, 10);
- if (Version[i] > 0xffff)
- return LOG(WINTUN_LOG_ERR, L"Version field may not exceed 65535"), ERROR_INVALID_DATA;
- Ptr = PtrNext;
- if (i >= _countof(Version) - 1 || !*Ptr || *Ptr == ';' || iswspace(*Ptr))
- break;
- if (*Ptr != '.')
- return LOG(WINTUN_LOG_ERR, L"Unexpected version delimiter"), ERROR_INVALID_DATA;
- }
- }
- *DriverVersion = (Version[0] << 48) | (Version[1] << 32) | (Version[2] << 16) | (Version[3] << 0);
- return ERROR_SUCCESS;
- }
- }
- }
- Inf = SkipNonLF(Inf, InfEnd);
- }
- LOG(WINTUN_LOG_ERR, L"DriverVer not found in INF resource");
- return ERROR_FILE_NOT_FOUND;
-}
-
static DWORD
VersionOfFile(_In_z_ const WCHAR *Filename)
{
@@ -1164,17 +1062,12 @@ SelectDriver(
_Inout_ SP_DEVINSTALL_PARAMS_W *DevInstallParams,
_Inout_ BOOL *RebootRequired)
{
- FILETIME OurDriverDate;
- DWORDLONG OurDriverVersion;
- DWORD Result = VersionOfInf(&OurDriverDate, &OurDriverVersion);
- if (Result != ERROR_SUCCESS)
- {
- LOG(WINTUN_LOG_ERR, L"Failed to determine own driver version");
- return Result;
- }
+ static const FILETIME OurDriverDate = WINTUN_INF_FILETIME;
+ static const DWORDLONG OurDriverVersion = WINTUN_INF_VERSION;
HANDLE DriverInstallationLock = NamespaceTakeDriverInstallationMutex();
if (!DriverInstallationLock)
return LOG_LAST_ERROR(L"Failed to take driver installation mutex");
+ DWORD Result = ERROR_SUCCESS;
if (!SetupDiBuildDriverInfoList(DevInfo, DevInfoData, SPDIT_COMPATDRIVER))
{
Result = LOG_LAST_ERROR(L"Failed building driver info list");
diff --git a/api/api.vcxproj b/api/api.vcxproj
index f75cb0d..fcd3047 100644
--- a/api/api.vcxproj
+++ b/api/api.vcxproj
@@ -106,6 +106,7 @@
<PreprocessorDefinitions>_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="Exists('$(OutDir)whql\')">HAVE_WHQL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/volatile:iso %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\$(Configuration)\$(WintunPlatform);..\$(Configuration);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ResourceCompile>
<AdditionalIncludeDirectories>..\$(Configuration)\$(WintunPlatform);..\$(Configuration);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
diff --git a/extract-driverver.js b/extract-driverver.js
new file mode 100644
index 0000000..688e356
--- /dev/null
+++ b/extract-driverver.js
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2018-2020 WireGuard LLC. All Rights Reserved.
+ */
+
+while (!WScript.StdIn.AtEndOfStream) {
+ var line = WScript.StdIn.ReadLine();
+ if (line.substr(0, 12) != "DriverVer = ")
+ continue;
+ var val = line.substr(12).split(",");
+ var date = val[0].split("/");
+ var ver = val[1].split(".");
+ var time = Date.UTC(date[2], date[0] - 1, date[1]).toString()
+ WScript.Echo("#define WINTUN_INF_FILETIME { (DWORD)((" + time + "ULL * 10000ULL + 116444736000000000ULL) & 0xffffffffU), (DWORD)((" + time + "ULL * 10000ULL + 116444736000000000ULL) >> 32) }")
+ WScript.Echo("#define WINTUN_INF_VERSION ((" + ver[0] + "ULL << 48) | (" + ver[1] + "ULL << 32) | (" + ver[2] + "ULL << 16) | (" + ver[3] + "ULL << 0))")
+ break;
+}
diff --git a/wintun.vcxproj b/wintun.vcxproj
index dbfd824..af0e0c3 100644
--- a/wintun.vcxproj
+++ b/wintun.vcxproj
@@ -139,6 +139,7 @@
<IntDir>$(ConfigurationName)\$(WintunPlatform)\</IntDir>
<OutDir>$(ConfigurationName)\$(WintunPlatform)\</OutDir>
<RunCodeAnalysis>true</RunCodeAnalysis>
+ <CustomBuildAfterTargets>StampInf</CustomBuildAfterTargets>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<CodeAnalysisRuleSet>$(WDKContentRoot)CodeAnalysis\DriverMustFixRules.ruleset</CodeAnalysisRuleSet>
@@ -168,6 +169,11 @@
<DriverSign>
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
</DriverSign>
+ <CustomBuildStep>
+ <Command>cscript.exe /nologo "$(ProjectDir)\extract-driverver.js" &lt; "$(IntDir)wintun.inf" &gt; "$(IntDir)wintun-inf.h"</Command>
+ <Outputs>$(IntDir)wintun-inf.h</Outputs>
+ <Inputs>$(IntDir)wintun.inf</Inputs>
+ </CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<Inf>