From 21f3875c4f1458e859093d3c10eceed4f68dda4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 5 Jan 2024 22:44:40 +0800 Subject: [PATCH] Host (Windows): detect serial number and UUID --- CMakeLists.txt | 2 +- doc/json_schema.json | 31 ++++++++++++++--- src/data/help.json | 14 ++++++-- src/detection/host/host.h | 2 +- src/detection/host/host_android.c | 2 +- src/detection/host/host_apple.c | 2 +- src/detection/host/host_bsd.c | 2 +- src/detection/host/host_linux.c | 2 +- .../host/{host_windows.c => host_windows.cpp} | 27 ++++++++++++++- src/modules/host/host.c | 33 ++++++++++++++++--- src/modules/host/option.h | 4 +++ 11 files changed, 104 insertions(+), 17 deletions(-) rename src/detection/host/{host_windows.c => host_windows.cpp} (52%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e0624a4..2a0babff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -631,7 +631,7 @@ elseif(WIN32) src/detection/displayserver/displayserver_windows.c src/detection/font/font_windows.c src/detection/gpu/gpu_windows.c - src/detection/host/host_windows.c + src/detection/host/host_windows.cpp src/detection/icons/icons_windows.c src/detection/libc/libc_windows.cpp src/detection/lm/lm_nosupport.c diff --git a/doc/json_schema.json b/doc/json_schema.json index 78a4116b..e86fbc74 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -676,10 +676,6 @@ "const": "gamepad", "description": "List connected gamepads" }, - { - "const": "host", - "description": "Print product name of your computer" - }, { "const": "icons", "description": "Print icon style name" @@ -1221,6 +1217,33 @@ }, "additionalProperties": false }, + { + "title": "Host", + "properties": { + "type": { + "const": "host", + "description": "Print product name of your computer", + }, + "useWmi": { + "description": "Set if WMI query should be used on Windows, which detects more information but slower", + "type": "boolean", + "default": false + }, + "key": { + "$ref": "#/$defs/key" + }, + "keyColor": { + "$ref": "#/$defs/keyColor" + }, + "keyWidth": { + "$ref": "#/$defs/keyWidth" + }, + "format": { + "$ref": "#/$defs/format" + } + }, + "additionalProperties": false + }, { "title": "Local IP", "properties": { diff --git a/src/data/help.json b/src/data/help.json index 3af8895c..2302f6c1 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -842,10 +842,20 @@ "default": "default" } }, + { + "long": "host-use-wmi", + "desc": "Set if WMI query should be used on Windows when detecting host", + "remark": "WMI query detects more information (UUID and serial number) but is slower. Windows only", + "arg": { + "type": "bool", + "optional": true, + "default": false + } + }, { "long": "chassis-use-wmi", - "desc": "Set if WMI query should be used on Windows", - "remark": "WMI query detects more information but is slower. Windows only", + "desc": "Set if WMI query should be used on Windows when detecting chassis", + "remark": "WMI query detects more information (vendor and version) but is slower. Windows only", "arg": { "type": "bool", "optional": true, diff --git a/src/detection/host/host.h b/src/detection/host/host.h index 1b0c6118..eb236ccf 100644 --- a/src/detection/host/host.h +++ b/src/detection/host/host.h @@ -13,4 +13,4 @@ typedef struct FFHostResult FFstrbuf vendor; } FFHostResult; -const char* ffDetectHost(FFHostResult* host); +const char* ffDetectHost(FFHostResult* host, FFHostOptions* options); diff --git a/src/detection/host/host_android.c b/src/detection/host/host_android.c index b496029a..e37202cb 100644 --- a/src/detection/host/host_android.c +++ b/src/detection/host/host_android.c @@ -2,7 +2,7 @@ #include "common/settings.h" #include -const char* ffDetectHost(FFHostResult* host) +const char* ffDetectHost(FFHostResult* host, FF_MAYBE_UNUSED FFHostOptions* options) { // http://newandroidbook.com/ddb/ ffSettingsGetAndroidProperty("ro.product.device", &host->family); diff --git a/src/detection/host/host_apple.c b/src/detection/host/host_apple.c index 98910e5e..89f47f62 100644 --- a/src/detection/host/host_apple.c +++ b/src/detection/host/host_apple.c @@ -201,7 +201,7 @@ const char* getOthersByIokit(FFHostResult* host) return NULL; } -const char* ffDetectHost(FFHostResult* host) +const char* ffDetectHost(FFHostResult* host, FF_MAYBE_UNUSED FFHostOptions* options) { const char* error = ffSysctlGetString("hw.model", &host->family); if (error) return error; diff --git a/src/detection/host/host_bsd.c b/src/detection/host/host_bsd.c index 334b04ca..f662a9f2 100644 --- a/src/detection/host/host_bsd.c +++ b/src/detection/host/host_bsd.c @@ -2,7 +2,7 @@ #include "common/settings.h" #include "util/smbiosHelper.h" -const char* ffDetectHost(FFHostResult* host) +const char* ffDetectHost(FFHostResult* host, FF_MAYBE_UNUSED FFHostOptions* options) { ffSettingsGetFreeBSDKenv("smbios.system.product", &host->name); ffCleanUpSmbiosValue(&host->name); diff --git a/src/detection/host/host_linux.c b/src/detection/host/host_linux.c index 372557a8..4c542f6b 100644 --- a/src/detection/host/host_linux.c +++ b/src/detection/host/host_linux.c @@ -27,7 +27,7 @@ static void getHostProductName(FFstrbuf* name) ffStrbufClear(name); } -const char* ffDetectHost(FFHostResult* host) +const char* ffDetectHost(FFHostResult* host, FF_MAYBE_UNUSED FFHostOptions* options) { ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &host->family); getHostProductName(&host->name); diff --git a/src/detection/host/host_windows.c b/src/detection/host/host_windows.cpp similarity index 52% rename from src/detection/host/host_windows.c rename to src/detection/host/host_windows.cpp index 8ff2c70a..2d3ab204 100644 --- a/src/detection/host/host_windows.c +++ b/src/detection/host/host_windows.cpp @@ -1,8 +1,30 @@ +extern "C" +{ #include "host.h" #include "util/windows/registry.h" #include "util/smbiosHelper.h" +} +#include "util/windows/wmi.hpp" +#include "util/windows/unicode.hpp" -const char* ffDetectHost(FFHostResult* host) +const char* detectWithWmi(FFHostResult* host) +{ + FFWmiQuery query(L"SELECT IdentifyingNumber, UUID FROM Win32_ComputerSystemProduct", nullptr, FFWmiNamespace::CIMV2); + if(!query) + return "Query WMI service failed"; + + if (FFWmiRecord record = query.next()) + { + if (auto identifyingNumber = record.get(L"IdentifyingNumber")) + ffStrbufSetWSV(&host->serial, identifyingNumber.get()); + if (auto uuid = record.get(L"UUID")) + ffStrbufSetWSV(&host->uuid, uuid.get()); + return NULL; + } + return "No WMI result returned"; +} + +const char* ffDetectHost(FFHostResult* host, FFHostOptions* options) { FF_HKEY_AUTO_DESTROY hKey = NULL; @@ -20,5 +42,8 @@ const char* ffDetectHost(FFHostResult* host) ffRegReadStrbuf(hKey, L"SystemManufacturer", &host->vendor, NULL); ffCleanUpSmbiosValue(&host->vendor); + if (options->useWmi) + detectWithWmi(host); + return NULL; } diff --git a/src/modules/host/host.c b/src/modules/host/host.c index 5c80baef..18a14637 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -16,8 +16,8 @@ void ffPrintHost(FFHostOptions* options) ffStrbufInit(&host.serial); ffStrbufInit(&host.uuid); ffStrbufInit(&host.vendor); - const char* error = ffDetectHost(&host); + const char* error = ffDetectHost(&host, options); if(error) { ffPrintError(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, "%s", error); @@ -76,6 +76,14 @@ bool ffParseHostCommandOptions(FFHostOptions* options, const char* key, const ch if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) return true; + #ifdef _WIN32 + if (ffStrEqualsIgnCase(subKey, "use-wmi")) + { + options->useWmi = ffOptionParseBoolean(value); + return true; + } + #endif + return false; } @@ -92,6 +100,14 @@ void ffParseHostJsonObject(FFHostOptions* options, yyjson_val* module) if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; + #ifdef _WIN32 + if (ffStrEqualsIgnCase(key, "useWmi")) + { + options->useWmi = yyjson_get_bool(val); + continue; + } + #endif + ffPrintError(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } @@ -102,6 +118,11 @@ void ffGenerateHostJsonConfig(FFHostOptions* options, yyjson_mut_doc* doc, yyjso ffInitHostOptions(&defaultOptions); ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + + #ifdef _WIN32 + if (options->useWmi != defaultOptions.useWmi) + yyjson_mut_obj_add_bool(doc, module, "useWmi", options->useWmi); + #endif } void ffGenerateHostJsonResult(FF_MAYBE_UNUSED FFHostOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -114,8 +135,8 @@ void ffGenerateHostJsonResult(FF_MAYBE_UNUSED FFHostOptions* options, yyjson_mut ffStrbufInit(&host.serial); ffStrbufInit(&host.uuid); ffStrbufInit(&host.vendor); - const char* error = ffDetectHost(&host); + const char* error = ffDetectHost(&host, options); if (error) { yyjson_mut_obj_add_str(doc, module, "error", error); @@ -133,9 +154,9 @@ void ffGenerateHostJsonResult(FF_MAYBE_UNUSED FFHostOptions* options, yyjson_mut yyjson_mut_obj_add_strbuf(doc, obj, "name", &host.name); yyjson_mut_obj_add_strbuf(doc, obj, "version", &host.version); yyjson_mut_obj_add_strbuf(doc, obj, "sku", &host.sku); + yyjson_mut_obj_add_strbuf(doc, obj, "vender", &host.vendor); yyjson_mut_obj_add_strbuf(doc, obj, "serial", &host.serial); yyjson_mut_obj_add_strbuf(doc, obj, "uuid", &host.uuid); - yyjson_mut_obj_add_strbuf(doc, obj, "sysVender", &host.vendor); exit: ffStrbufDestroy(&host.family); @@ -154,9 +175,9 @@ void ffPrintHostHelpFormat(void) "product name", "product version", "product sku", + "product vendor", "product serial number", "product uuid", - "sys vendor" }); } @@ -174,6 +195,10 @@ void ffInitHostOptions(FFHostOptions* options) ffGenerateHostJsonConfig ); ffOptionInitModuleArg(&options->moduleArgs); + + #ifdef _WIN32 + options->useWmi = false; + #endif } void ffDestroyHostOptions(FFHostOptions* options) diff --git a/src/modules/host/option.h b/src/modules/host/option.h index 1c6bf26f..b305f2a9 100644 --- a/src/modules/host/option.h +++ b/src/modules/host/option.h @@ -8,4 +8,8 @@ typedef struct FFHostOptions { FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; + + #ifdef _WIN32 + bool useWmi; + #endif } FFHostOptions;