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>
This commit is contained in:
parent
55345ae386
commit
677ba8680f
115
api/adapter.c
115
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");
|
||||
|
@ -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>
|
||||
|
17
extract-driverver.js
Normal file
17
extract-driverver.js
Normal file
@ -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;
|
||||
}
|
@ -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" < "$(IntDir)wintun.inf" > "$(IntDir)wintun-inf.h"</Command>
|
||||
<Outputs>$(IntDir)wintun-inf.h</Outputs>
|
||||
<Inputs>$(IntDir)wintun.inf</Inputs>
|
||||
</CustomBuildStep>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<Inf>
|
||||
|
Loading…
Reference in New Issue
Block a user