Skip to content

Commit 464d7c8

Browse files
committed
[misc] update Windows version detection
* Also synchronize safe and UTF-8 calls with what Rufus uses.
1 parent 90278c5 commit 464d7c8

File tree

10 files changed

+423
-126
lines changed

10 files changed

+423
-126
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Main features
1212

1313
* Automated inf creation, using reported USB device name
1414
* Automated catalog file creation and signing, using autogenerated certificate
15-
* Automated driver files extraction, for x86_32 x86_64 and ARM64 platforms
15+
* Automated driver files extraction, for `x86_32`, `x86_64` and `ARM64` platforms
1616
* Automated driver installation, including UAC elevation where necessary
1717
* Single library embedding all the required files
1818
* Supports Windows platform from Windows 7 to Windows 11

examples/wdi-simple.rc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
#endif
88

99
VS_VERSION_INFO VERSIONINFO
10-
FILEVERSION 1,5,0,782
11-
PRODUCTVERSION 1,5,0,782
10+
FILEVERSION 1,5,0,783
11+
PRODUCTVERSION 1,5,0,783
1212
FILEFLAGSMASK 0x17L
1313
#ifdef _DEBUG
1414
FILEFLAGS 0x1L
@@ -25,13 +25,13 @@ BEGIN
2525
BEGIN
2626
VALUE "CompanyName", "akeo.ie"
2727
VALUE "FileDescription", "WDI-Simple"
28-
VALUE "FileVersion", "1.5.0.782"
28+
VALUE "FileVersion", "1.5.0.783"
2929
VALUE "InternalName", "WDI-Simple"
3030
VALUE "LegalCopyright", "� 2010-2023 Pete Batard (LGPL v3)"
3131
VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/lesser.html"
3232
VALUE "OriginalFilename", "wdi-simple.exe"
3333
VALUE "ProductName", "WDI-Simple"
34-
VALUE "ProductVersion", "1.5.0.782"
34+
VALUE "ProductVersion", "1.5.0.783"
3535
VALUE "Comments", "http://libwdi.akeo.ie"
3636
END
3737
END

examples/zadig.c

Lines changed: 73 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
#include <windows.h>
3434
#include <windowsx.h>
35+
#include <assert.h>
3536
#include <stdlib.h>
3637
#include <stdio.h>
3738
#include <string.h>
@@ -813,16 +814,63 @@ void set_loglevel(DWORD menu_cmd)
813814
wdi_set_log_level(log_level);
814815
}
815816

816-
BOOL is_x64(void)
817+
static __inline USHORT get_application_arch(void)
817818
{
818-
BOOL ret = FALSE;
819-
// Detect if we're running a 32 or 64 bit system
820-
if (sizeof(uintptr_t) < 8) {
821-
IsWow64Process(GetCurrentProcess(), &ret);
822-
} else {
823-
ret = TRUE;
819+
#if defined(_M_AMD64)
820+
return IMAGE_FILE_MACHINE_AMD64;
821+
#elif defined(_M_IX86)
822+
return IMAGE_FILE_MACHINE_I386;
823+
#elif defined(_M_ARM64)
824+
return IMAGE_FILE_MACHINE_ARM64;
825+
#elif defined(_M_ARM)
826+
return IMAGE_FILE_MACHINE_ARM;
827+
#else
828+
return IMAGE_FILE_MACHINE_UNKNOWN;
829+
#endif
830+
}
831+
832+
static __inline const char* get_arch_name(USHORT uArch)
833+
{
834+
switch (uArch) {
835+
case IMAGE_FILE_MACHINE_AMD64:
836+
return "x64";
837+
case IMAGE_FILE_MACHINE_I386:
838+
return "x86";
839+
case IMAGE_FILE_MACHINE_ARM64:
840+
return "arm64";
841+
case IMAGE_FILE_MACHINE_ARM:
842+
return "arm";
843+
default:
844+
return "unknown";
824845
}
825-
return ret;
846+
}
847+
848+
// Detect the underlying platform arch.
849+
static USHORT get_platform_arch(void)
850+
{
851+
BOOL is_64bit = FALSE, is_wow64 = FALSE;
852+
USHORT ProcessMachine = IMAGE_FILE_MACHINE_UNKNOWN, NativeMachine = IMAGE_FILE_MACHINE_UNKNOWN;
853+
854+
PF_TYPE_DECL(WINAPI, BOOL, IsWow64Process2, (HANDLE, USHORT*, USHORT*));
855+
PF_INIT(IsWow64Process2, Kernel32);
856+
857+
if ((pfIsWow64Process2 == NULL) ||
858+
!pfIsWow64Process2(GetCurrentProcess(), &ProcessMachine, &NativeMachine)) {
859+
// Assume same arch as the app
860+
NativeMachine = get_application_arch();
861+
// Fix the Arch if we have a 32-bit app running under WOW64
862+
if ((sizeof(uintptr_t) < 8) && IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64) {
863+
if (NativeMachine == IMAGE_FILE_MACHINE_I386)
864+
NativeMachine = IMAGE_FILE_MACHINE_AMD64;
865+
else if (NativeMachine == IMAGE_FILE_MACHINE_ARM)
866+
NativeMachine = IMAGE_FILE_MACHINE_ARM64;
867+
else // I sure wanna be made aware of this scenario...
868+
assert(FALSE);
869+
}
870+
dprintf("Note: Underlying Windows architecture was guessed and may be incorrect...");
871+
}
872+
873+
return NativeMachine;
826874
}
827875

828876
static const char* get_edition(DWORD ProductType)
@@ -913,10 +961,18 @@ static const char* get_edition(DWORD ProductType)
913961
case 0x000000A5: return "Pro for Education N";
914962
case 0x000000AB: return "Enterprise G"; // I swear Microsoft are just making up editions...
915963
case 0x000000AC: return "Enterprise G N";
964+
case 0x000000B2: return "Cloud";
965+
case 0x000000B3: return "Cloud N";
916966
case 0x000000B6: return "Home OS";
917-
case 0x000000B7: return "Cloud E";
918-
case 0x000000B8: return "Cloud E N";
967+
case 0x000000B7: case 0x000000CB: return "Cloud E";
968+
case 0x000000B9: return "IoT OS";
969+
case 0x000000BA: case 0x000000CA: return "Cloud E N";
970+
case 0x000000BB: return "IoT Edge OS";
971+
case 0x000000BC: return "IoT Enterprise";
919972
case 0x000000BD: return "Lite";
973+
case 0x000000BF: return "IoT Enterprise S";
974+
case 0x000000C0: case 0x000000C2: case 0x000000C3: case 0x000000C4: case 0x000000C5: case 0x000000C6: return "XBox";
975+
case 0x000000C7: case 0x000000C8: case 0x00000196: case 0x00000197: case 0x00000198: return "Azure Server";
920976
case 0xABCDABCD: return "(Unlicensed)";
921977
default:
922978
static_sprintf(unknown_edition_str, "(Unknown Edition 0x%02X)", (uint32_t)ProductType);
@@ -931,8 +987,8 @@ int get_windows_version(char* WindowsVersionStr, size_t WindowsVersionStrSize)
931987
{
932988
OSVERSIONINFOEXA vi, vi2;
933989
DWORD dwProductType;
934-
const char* w = 0;
935-
const char* w64 = "32 bit";
990+
const char* w = NULL;
991+
const char* arch_name;
936992
char* vptr;
937993
size_t vlen;
938994
unsigned major, minor;
@@ -1023,22 +1079,21 @@ int get_windows_version(char* WindowsVersionStr, size_t WindowsVersionStrSize)
10231079
}
10241080
}
10251081

1026-
if (is_x64())
1027-
w64 = "64-bit";
1082+
arch_name = get_arch_name(get_platform_arch());
10281083

10291084
GetProductInfo(vi.dwMajorVersion, vi.dwMinorVersion, vi.wServicePackMajor, vi.wServicePackMinor, &dwProductType);
10301085
vptr = &WindowsVersionStr[sizeof("Windows ") - 1];
10311086
vlen = WindowsVersionStrSize - sizeof("Windows ") - 1;
10321087
if (!w)
10331088
safe_sprintf(vptr, vlen, "%s %u.%u %s", (vi.dwPlatformId == VER_PLATFORM_WIN32_NT ? "NT" : "??"),
1034-
(unsigned)vi.dwMajorVersion, (unsigned)vi.dwMinorVersion, w64);
1089+
(unsigned)vi.dwMajorVersion, (unsigned)vi.dwMinorVersion, arch_name);
10351090
else if (vi.wServicePackMinor)
1036-
safe_sprintf(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, w64);
1091+
safe_sprintf(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch_name);
10371092
else if (vi.wServicePackMajor)
1038-
safe_sprintf(vptr, vlen, "%s SP%u %s", w, vi.wServicePackMajor, w64);
1093+
safe_sprintf(vptr, vlen, "%s SP%u %s", w, vi.wServicePackMajor, arch_name);
10391094
else
10401095
safe_sprintf(vptr, vlen, "%s%s%s, %s",
1041-
w, (dwProductType != PRODUCT_UNDEFINED) ? " " : "", get_edition(dwProductType), w64);
1096+
w, (dwProductType != PRODUCT_UNDEFINED) ? " " : "", get_edition(dwProductType), arch_name);
10421097

10431098
// Add the build number (including UBR if available) for Windows 8.0 and later
10441099
nWindowsBuildNumber = vi.dwBuildNumber;

examples/zadig.h

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
#define FIELD_ORANGE RGB(255,240,200)
6161
#define ARROW_GREEN RGB(92,228,65)
6262
#define ARROW_ORANGE RGB(253,143,56)
63-
#define APP_VERSION "Zadig 2.8.782"
63+
#define APP_VERSION "Zadig 2.8.783"
6464

6565
// These are used to flag end users about the driver they are going to replace
6666
enum driver_type {
@@ -134,22 +134,28 @@ typedef struct ext_t {
134134
EXT_D(var, descriptions); \
135135
ext_t var = { ARRAYSIZE(_##var##_x), filename, _##var##_x, _##var##_d }
136136

137-
#define safe_free(p) do {if ((void*)p != NULL) {free((void*)p); p = NULL;}} while(0)
137+
#define safe_free(p) do {free((void*)p); p = NULL;} while(0)
138138
#define safe_min(a, b) min((size_t)(a), (size_t)(b))
139-
#define safe_strcp(dst, dst_max, src, count) do {memcpy(dst, src, safe_min(count, dst_max)); \
140-
((char*)dst)[safe_min(count, dst_max)-1] = 0;} while(0)
141-
#define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, src, safe_strlen(src)+1)
139+
static __inline void safe_strcp(char* dst, const size_t dst_max, const char* src, const size_t count) {
140+
memmove(dst, src, min(count, dst_max));
141+
dst[min(count, dst_max) - 1] = 0;
142+
}
143+
#define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, src, safe_strlen(src) + 1)
142144
#define static_strcpy(dst, src) safe_strcpy(dst, sizeof(dst), src)
143-
#define safe_strncat(dst, dst_max, src, count) strncat(dst, src, safe_min(count, dst_max - safe_strlen(dst) - 1))
144-
#define safe_strcat(dst, dst_max, src) safe_strncat(dst, dst_max, src, safe_strlen(src)+1)
145+
#define safe_strcat(dst, dst_max, src) strncat_s(dst, dst_max, src, _TRUNCATE)
146+
#define static_strcat(dst, src) safe_strcat(dst, sizeof(dst), (src))
145147
#define safe_strcmp(str1, str2) strcmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
146148
#define safe_stricmp(str1, str2) _stricmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
147149
#define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2), count)
148-
#define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
149-
#define safe_sprintf(dst, count, ...) do {_snprintf(dst, count, __VA_ARGS__); (dst)[(count)-1] = 0; } while(0)
150+
#define safe_closehandle(h) do {if ((h != INVALID_HANDLE_VALUE) && (h != NULL)) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
151+
#define safe_sprintf(dst, count, ...) do { size_t _count = count; char* _dst = dst; _snprintf_s(_dst, _count, _TRUNCATE, __VA_ARGS__); \
152+
_dst[(_count) - 1] = 0; } while(0)
150153
#define static_sprintf(dst, ...) safe_sprintf(dst, sizeof(dst), __VA_ARGS__)
151154
#define safe_strlen(str) ((((char*)str)==NULL)?0:strlen(str))
152-
#define safe_strdup _strdup
155+
#define static_sprintf(dst, ...) safe_sprintf(dst, sizeof(dst), __VA_ARGS__)
156+
#define safe_swprintf(dst, count, ...) do { size_t _count = count; wchar_t* _dst = dst; _snwprintf_s(_dst, _count, _TRUNCATE, __VA_ARGS__); \
157+
_dst[(_count) - 1] = 0; } while(0)
158+
#define safe_strdup(str) ((((char*)(str))==NULL) ? NULL : _strdup(str))
153159
#define MF_CHECK(cond) ((cond)?MF_CHECKED:MF_UNCHECKED)
154160
#define IGNORE_RETVAL(expr) do { (void)(expr); } while(0)
155161

examples/zadig.rc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,8 @@ END
246246
//
247247

248248
VS_VERSION_INFO VERSIONINFO
249-
FILEVERSION 2,8,782,0
250-
PRODUCTVERSION 2,8,782,0
249+
FILEVERSION 2,8,783,0
250+
PRODUCTVERSION 2,8,783,0
251251
FILEFLAGSMASK 0x17L
252252
#ifdef _DEBUG
253253
FILEFLAGS 0x1L
@@ -264,13 +264,13 @@ BEGIN
264264
BEGIN
265265
VALUE "CompanyName", "akeo.ie"
266266
VALUE "FileDescription", "Zadig"
267-
VALUE "FileVersion", "2.8.782"
267+
VALUE "FileVersion", "2.8.783"
268268
VALUE "InternalName", "Zadig"
269269
VALUE "LegalCopyright", "� 2010-2023 Pete Batard (GPL v3)"
270270
VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/gpl.html"
271271
VALUE "OriginalFilename", "zadig.exe"
272272
VALUE "ProductName", "Zadig"
273-
VALUE "ProductVersion", "2.8.782"
273+
VALUE "ProductVersion", "2.8.783"
274274
VALUE "Comments", "https://zadig.akeo.ie"
275275
END
276276
END

examples/zadig_net.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,20 @@ static BOOL force_update = FALSE;
5353
static BOOL force_update_check = FALSE;
5454
static BOOL update_check_in_progress = FALSE;
5555

56+
static const char* GetAppArchName(void) {
57+
#if defined(_M_AMD64)
58+
return "x64";
59+
#elif defined(_M_IX86)
60+
return "x86";
61+
#elif defined(_M_ARM64)
62+
return "arm64";
63+
#elif defined(_M_ARM)
64+
return "arm";
65+
#else
66+
return "unknown";
67+
#endif
68+
}
69+
5670
/* MinGW is missing some of those */
5771
#if !defined(ERROR_INTERNET_DISCONNECTED)
5872
#define ERROR_INTERNET_DISCONNECTED (INTERNET_ERROR_BASE + 163)
@@ -248,6 +262,13 @@ const char* WinInetErrorString(void)
248262
}
249263
}
250264

265+
static __inline BOOL is_WOW64(void)
266+
{
267+
BOOL ret = FALSE;
268+
IsWow64Process(GetCurrentProcess(), &ret);
269+
return ret;
270+
}
271+
251272
/*
252273
* Open an Internet session
253274
*/
@@ -289,7 +310,7 @@ static HINTERNET GetInternetSession(int num_retries)
289310
}
290311
static_sprintf(agent, APPLICATION_NAME "/%d.%d.%d (Windows NT %d.%d%s)",
291312
application_version[0], application_version[1], application_version[2],
292-
windows_version >> 4, windows_version & 0x0F, is_x64() ? "; WOW64" : "");
313+
windows_version >> 4, windows_version & 0x0F, is_WOW64() ? "; WOW64" : "");
293314
hSession = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
294315
// Set the timeouts
295316
InternetSetOptionA(hSession, INTERNET_OPTION_CONNECT_TIMEOUT, (LPVOID)&dwTimeout, sizeof(dwTimeout));
@@ -574,8 +595,8 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
574595
// and then remove each each of the <os_> components until we find our match. For instance, we may first
575596
// look for <app_name>_win_x64_6.2.ver (Win8 x64) but only get a match for <app_name>_win_x64_6.ver (Vista x64 or later)
576597
// This allows sunsetting OS versions (eg XP) or providing different downloads for different archs/groups.
577-
static_sprintf(urlpath, "%s%s%s_%s_%ld.%ld.ver", APPLICATION_NAME, (k == 0) ? "" : "_",
578-
(k == 0) ? "" : channel[k], archname[is_x64() ? 1 : 0], os_version.dwMajorVersion, os_version.dwMinorVersion);
598+
static_sprintf(urlpath, "%s%s%s_win_%s_%lu.%lu.ver", APPLICATION_NAME, (k == 0) ? "" : "_",
599+
(k == 0) ? "" : channel[k], GetAppArchName(), os_version.dwMajorVersion, os_version.dwMinorVersion);
579600
vuprintf("Base update check: %s\n", urlpath);
580601
for (i = 0, j = (int)safe_strlen(urlpath) - 5; (j>0) && (i<ARRAYSIZE(verpos)); j--) {
581602
if ((urlpath[j] == '.') || (urlpath[j] == '_')) {

libwdi/installer.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,26 @@
4242

4343
#define safe_free(p) do {free((void*)p); p = NULL;} while(0)
4444
#define safe_min(a, b) min((size_t)(a), (size_t)(b))
45-
#define safe_strcp(dst, dst_max, src, count) do {memcpy(dst, (src), safe_min(count, dst_max)); \
46-
((char*)dst)[safe_min(count, dst_max)-1] = 0;} while(0)
47-
#define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, (src), safe_strlen(src)+1)
48-
#define static_strcpy(dst, src) safe_strcpy(dst, sizeof(dst), (src))
49-
#define safe_strncat(dst, dst_max, src, count) strncat(dst, (src), safe_min(count, dst_max - safe_strlen(dst) - 1))
50-
#define safe_strcat(dst, dst_max, src) safe_strncat(dst, dst_max, src, safe_strlen(src)+1)
45+
static __inline void safe_strcp(char* dst, const size_t dst_max, const char* src, const size_t count) {
46+
memmove(dst, src, min(count, dst_max));
47+
dst[min(count, dst_max) - 1] = 0;
48+
}
49+
#define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, src, safe_strlen(src) + 1)
50+
#define static_strcpy(dst, src) safe_strcpy(dst, sizeof(dst), src)
51+
#define safe_strcat(dst, dst_max, src) strncat_s(dst, dst_max, src, _TRUNCATE)
5152
#define static_strcat(dst, src) safe_strcat(dst, sizeof(dst), (src))
5253
#define safe_strcmp(str1, str2) strcmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
5354
#define safe_stricmp(str1, str2) _stricmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
5455
#define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2), count)
5556
#define safe_closehandle(h) do {if ((h != INVALID_HANDLE_VALUE) && (h != NULL)) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
56-
#define safe_sprintf(dst, count, ...) do {_snprintf(dst, count, __VA_ARGS__); (dst)[(count)-1] = 0; } while(0)
57+
#define safe_sprintf(dst, count, ...) do { size_t _count = count; char* _dst = dst; _snprintf_s(_dst, _count, _TRUNCATE, __VA_ARGS__); \
58+
_dst[(_count) - 1] = 0; } while(0)
59+
#define static_sprintf(dst, ...) safe_sprintf(dst, sizeof(dst), __VA_ARGS__)
5760
#define safe_strlen(str) ((((char*)str)==NULL)?0:strlen(str))
5861
#define static_sprintf(dst, ...) safe_sprintf(dst, sizeof(dst), __VA_ARGS__)
59-
#define safe_swprintf _snwprintf
60-
#define safe_strdup _strdup
62+
#define safe_swprintf(dst, count, ...) do { size_t _count = count; wchar_t* _dst = dst; _snwprintf_s(_dst, _count, _TRUNCATE, __VA_ARGS__); \
63+
_dst[(_count) - 1] = 0; } while(0)
64+
#define safe_strdup(str) ((((char*)(str))==NULL) ? NULL : _strdup(str))
6165
#ifndef ARRAYSIZE
6266
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
6367
#endif

0 commit comments

Comments
 (0)