From 246ff0bc88af9eb621e7fa37567b3928d817df4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 24 Mar 2026 16:09:25 +0800 Subject: [PATCH] Common (Windows): adds a unique type for querying registry binary data --- src/common/argType.h | 15 +++- src/common/impl/format.c | 7 ++ src/common/windows/registry.c | 77 ++++++++++--------- src/common/windows/registry.h | 6 +- .../displayserver/displayserver_windows.c | 14 +++- src/detection/font/font_windows.c | 28 +++---- 6 files changed, 87 insertions(+), 60 deletions(-) diff --git a/src/common/argType.h b/src/common/argType.h index c108e3e5c..481f9d225 100644 --- a/src/common/argType.h +++ b/src/common/argType.h @@ -2,6 +2,15 @@ #include "common/FFstrbuf.h" +// For ffRegReadValue(s) +// If length is 0, data will be allocated with malloc() and must be freed by the caller +// Otherwise, data must point to a buffer of at least length bytes, and the actual length of the data will be written to length. +typedef struct FFArgBuffer +{ + void* data; + uint32_t length; +} FFArgBuffer; + typedef enum __attribute__((__packed__)) FFArgType { FF_ARG_TYPE_NULL = 0, @@ -15,7 +24,8 @@ typedef enum __attribute__((__packed__)) FFArgType FF_ARG_TYPE_FLOAT, FF_ARG_TYPE_DOUBLE, FF_ARG_TYPE_LIST, - FF_ARG_TYPE_BOOL + FF_ARG_TYPE_BOOL, + FF_ARG_TYPE_BUFFER, } FFArgType; #define FF_ARG(variable, var_name) { _Generic((variable), \ @@ -30,5 +40,6 @@ typedef enum __attribute__((__packed__)) FFArgType float: FF_ARG_TYPE_FLOAT, \ double: FF_ARG_TYPE_DOUBLE, \ FFlist: FF_ARG_TYPE_LIST, \ - bool: FF_ARG_TYPE_BOOL \ + bool: FF_ARG_TYPE_BOOL, \ + FFArgBuffer: FF_ARG_TYPE_BUFFER \ ), _Generic((variable), char*: (variable), const char*: (variable), default: &(variable) ), (var_name) } diff --git a/src/common/impl/format.c b/src/common/impl/format.c index 0c3ea9757..16b21c479 100644 --- a/src/common/impl/format.c +++ b/src/common/impl/format.c @@ -51,6 +51,13 @@ void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg) } break; } + case FF_ARG_TYPE_BUFFER: + { + // Placeholder for binary data, just print the size for now + const FFArgBuffer* argBuffer = (const FFArgBuffer*) formatarg->value; + ffStrbufAppendF(buffer, "buffer(%u bytes)", argBuffer->length); + break; + } default: if(formatarg->type != FF_ARG_TYPE_NULL) fprintf(stderr, "Error: format string \"%s\": argument is not implemented: %i\n", buffer->chars, formatarg->type); diff --git a/src/common/windows/registry.c b/src/common/windows/registry.c index f57535c73..a8c020492 100644 --- a/src/common/windows/registry.c +++ b/src/common/windows/registry.c @@ -180,51 +180,56 @@ static bool processRegValue(const FFRegValueArg* arg, const ULONG regType, const case FF_ARG_TYPE_LIST: { - if (regType != REG_MULTI_SZ && regType != REG_BINARY) + if (regType != REG_MULTI_SZ) goto type_mismatch; FFlist* list = (FFlist*) arg->value; + if (list->elementSize != sizeof(FFstrbuf)) + { + if (error) + { + FF_STRBUF_AUTO_DESTROY nameA = arg->name ? ffStrbufCreateWS(arg->name) : ffStrbufCreateStatic("(default)"); + ffStrbufAppendF(error, "ffRegReadValues(%s) type mismatch: expected list of strbuf for REG_MULTI_SZ", nameA.chars); + } + return false; + } + ffListClear(list); - if (regType == REG_MULTI_SZ) + for ( + const wchar_t* ptr = (const wchar_t*) regData; + (const uint8_t*) ptr < (const uint8_t*) regData + regDataLen && *ptr; + ptr++ + ) { - if (list->elementSize != sizeof(FFstrbuf)) - { - if (error) - { - FF_STRBUF_AUTO_DESTROY nameA = arg->name ? ffStrbufCreateWS(arg->name) : ffStrbufCreateStatic("(default)"); - ffStrbufAppendF(error, "ffRegReadValues(%s) type mismatch: expected list of strbuf for REG_MULTI_SZ", nameA.chars); - } - return false; - } - - for ( - const wchar_t* ptr = (const wchar_t*) regData; - (const uint8_t*) ptr < (const uint8_t*) regData + regDataLen && *ptr; - ptr++ - ) - { - uint32_t strLen = (uint32_t) wcsnlen(ptr, regDataLen / sizeof(wchar_t) - (size_t) (ptr - (const wchar_t*) regData)); - ffStrbufInitNWS(FF_LIST_ADD(FFstrbuf, *list), strLen, ptr); - ptr += strLen; - } + uint32_t strLen = (uint32_t) wcsnlen(ptr, regDataLen / sizeof(wchar_t) - (size_t) (ptr - (const wchar_t*) regData)); + ffStrbufInitNWS(FF_LIST_ADD(FFstrbuf, *list), strLen, ptr); + ptr += strLen; } - else + break; + } + + case FF_ARG_TYPE_BUFFER: + { + if (regType != REG_BINARY) + goto type_mismatch; + + FFArgBuffer* buffer = (FFArgBuffer*) arg->value; + if (buffer->length == 0) { - if (list->elementSize != sizeof(uint8_t)) - { - if (error) - { - FF_STRBUF_AUTO_DESTROY nameA = arg->name ? ffStrbufCreateWS(arg->name) : ffStrbufCreateStatic("(default)"); - ffStrbufAppendF(error, "ffRegReadValues(%s) type mismatch: expected list of uint8_t for REG_BINARY", nameA.chars); - } - return false; - } - - ffListReserve(list, regDataLen); - memcpy(list->data, regData, regDataLen); - list->length = regDataLen; + buffer->data = malloc(regDataLen); } + else if (buffer->length < regDataLen) + { + if (error) + { + FF_STRBUF_AUTO_DESTROY nameA = arg->name ? ffStrbufCreateWS(arg->name) : ffStrbufCreateStatic("(default)"); + ffStrbufAppendF(error, "ffRegReadValues(%s) buffer too small (%u): expected %u", nameA.chars, (unsigned) buffer->length, (unsigned) regDataLen); + } + return false; + } + buffer->length = regDataLen; + memcpy(buffer->data, regData, regDataLen); break; } diff --git a/src/common/windows/registry.h b/src/common/windows/registry.h index 7c9b9a39a..b056dd3b6 100644 --- a/src/common/windows/registry.h +++ b/src/common/windows/registry.h @@ -58,11 +58,11 @@ static inline bool ffRegReadUint64(HANDLE hKey, const wchar_t* valueNameW, uint6 .name = valueNameW, }, error); } -static inline bool ffRegReadData(HANDLE hKey, const wchar_t* valueNameW, FFlist* result /*list of uint8_t*/, FFstrbuf* error) +static inline bool ffRegReadData(HANDLE hKey, const wchar_t* valueNameW, FFArgBuffer* buffer, FFstrbuf* error) { return ffRegReadValue(hKey, &(FFRegValueArg) { - .type = FF_ARG_TYPE_LIST, - .value = result, + .type = FF_ARG_TYPE_BUFFER, + .value = buffer, .name = valueNameW, }, error); } diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index c26fd596c..8dd1049c9 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -6,6 +6,15 @@ #include #include +static inline void freeArgBuffer(FFArgBuffer* buffer) +{ + if (buffer->data) + free(buffer->data); + buffer->data = NULL; + buffer->length = 0; +} +#define FF_AUTO_FREE_ARG_BUFFER __attribute__((__cleanup__(freeArgBuffer))) + // http://undoc.airesoft.co.uk/user32.dll/IsThreadDesktopComposited.php BOOL WINAPI IsThreadDesktopComposited(); BOOL WINAPI GetDpiForMonitorInternal(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT* dpiX, UINT* dpiY); @@ -41,8 +50,7 @@ static void detectDisplays(FFDisplayServerResult* ds) .id = path->targetInfo.id, }, }; - FF_LIST_AUTO_DESTROY edid = ffListCreate(sizeof(uint8_t)); - + FF_AUTO_FREE_ARG_BUFFER FFArgBuffer edid = {}; if(DisplayConfigGetDeviceInfo(&targetName.header) == ERROR_SUCCESS) { wchar_t regPath[256] = L"SYSTEM\\CurrentControlSet\\Enum"; @@ -70,7 +78,7 @@ static void detectDisplays(FFDisplayServerResult* ds) } else { - ffListClear(&edid); + edid.length = 0; if (targetName.flags.friendlyNameFromEdid) ffStrbufSetWS(&name, targetName.monitorFriendlyDeviceName); else diff --git a/src/detection/font/font_windows.c b/src/detection/font/font_windows.c index bd9ff9558..acd6c3063 100644 --- a/src/detection/font/font_windows.c +++ b/src/detection/font/font_windows.c @@ -24,35 +24,31 @@ static void generateString(FFFontResult* font) ffStrbufAppendC(&font->display, ']'); } -WINUSERAPI WINBOOL WINAPI ClassicSystemParametersInfoW(UINT uiAction,UINT uiParam,PVOID pvParam,UINT fWinIni); - const char* ffDetectFontImpl(FFFontResult* result) { FF_AUTO_CLOSE_FD HANDLE hKey = NULL; if (!ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"Control Panel\\Desktop\\WindowMetrics", &hKey, NULL)) return "ffRegOpenKeyForRead(HKEY_CURRENT_USER\\Control Panel\\Desktop\\WindowMetrics) failed"; - FF_LIST_AUTO_DESTROY CaptionFont = ffListCreate(sizeof(uint8_t)); - FF_LIST_AUTO_DESTROY MenuFont = ffListCreate(sizeof(uint8_t)); - FF_LIST_AUTO_DESTROY MessageFont = ffListCreate(sizeof(uint8_t)); - FF_LIST_AUTO_DESTROY StatusFont = ffListCreate(sizeof(uint8_t)); + LOGFONTW fonts[4]; + FFArgBuffer fontBuffers[4] = { + { .data = &fonts[0], .length = sizeof(fonts[0]) }, + { .data = &fonts[1], .length = sizeof(fonts[1]) }, + { .data = &fonts[2], .length = sizeof(fonts[2]) }, + { .data = &fonts[3], .length = sizeof(fonts[3]) }, + }; if (!ffRegReadValues(hKey, 4, (FFRegValueArg[]) { - FF_ARG(CaptionFont, L"CaptionFont"), - FF_ARG(MenuFont, L"MenuFont"), - FF_ARG(MessageFont, L"MessageFont"), - FF_ARG(StatusFont, L"StatusFont"), + FF_ARG(fontBuffers[0], L"CaptionFont"), + FF_ARG(fontBuffers[1], L"MenuFont"), + FF_ARG(fontBuffers[2], L"MessageFont"), + FF_ARG(fontBuffers[3], L"StatusFont"), }, NULL)) return "ffRegReadValues(HKEY_CURRENT_USER\\Control Panel\\Desktop\\WindowMetrics) failed"; - FFlist* fonts[4] = { &CaptionFont, &MenuFont, &MessageFont, &StatusFont }; - for (uint32_t i = 0; i < ARRAY_SIZE(fonts); ++i) { - if (fonts[i]->length < sizeof(LOGFONTW)) - continue; - - LOGFONTW* logFont = (LOGFONTW*) fonts[i]->data; + LOGFONTW* logFont = &fonts[i]; ffStrbufSetWS(&result->fonts[i], logFont->lfFaceName); if (logFont->lfHeight < 0)