diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d0cf1b4d..ce3a3a99b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -374,7 +374,7 @@ if(WIN32) src/util/windows/wmi.cpp src/util/windows/getline.c src/util/windows/pwd.c - src/util/windows/utsname.c + src/util/windows/utsname.cpp src/detection/poweradapter/poweradapter_nosupport.c src/detection/media/media_nosupport.c diff --git a/src/detection/battery/battery_windows.cpp b/src/detection/battery/battery_windows.cpp index fce0b5657..a3c2accf0 100644 --- a/src/detection/battery/battery_windows.cpp +++ b/src/detection/battery/battery_windows.cpp @@ -8,26 +8,23 @@ const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results) FF_UNUSED(instance); //https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-battery - IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT SystemName, Name, Chemistry, EstimatedChargeRemaining, BatteryStatus FROM Win32_Battery", nullptr); + FFWmiQuery query(L"SELECT SystemName, Name, Chemistry, EstimatedChargeRemaining, BatteryStatus FROM Win32_Battery"); - if(!pEnumerator) + if(!query) return "Query WMI service failed"; - IWbemClassObject *pclsObj = NULL; - ULONG uReturn = 0; - - while(SUCCEEDED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) && uReturn != 0) + while(FFWmiRecord record = query.next()) { BatteryResult* battery = (BatteryResult*)ffListAdd(results); ffStrbufInit(&battery->manufacturer); - ffGetWmiObjString(pclsObj, L"SystemName", &battery->manufacturer); + record.getString(L"SystemName", &battery->manufacturer); ffStrbufInit(&battery->modelName); - ffGetWmiObjString(pclsObj, L"Name", &battery->modelName); + record.getString(L"Name", &battery->modelName); uint64_t chemistry = 0; - ffGetWmiObjUnsigned(pclsObj, L"Chemistry", &chemistry); + record.getUnsigned(L"Chemistry", &chemistry); switch(chemistry) { case 1: ffStrbufInitS(&battery->technology, "Other"); break; @@ -42,11 +39,11 @@ const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results) } uint64_t capacity; - ffGetWmiObjUnsigned(pclsObj, L"EstimatedChargeRemaining", &capacity); + record.getUnsigned(L"EstimatedChargeRemaining", &capacity); ffStrbufInitF(&battery->capacity, "%d", (int)capacity); uint64_t batteryStatus; - ffGetWmiObjUnsigned(pclsObj, L"BatteryStatus", &batteryStatus); + record.getUnsigned(L"BatteryStatus", &batteryStatus); switch(batteryStatus) { case 1: ffStrbufInitS(&battery->status, "Discharging"); break; @@ -66,7 +63,5 @@ const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results) battery->temperature = FF_BATTERY_TEMP_UNSET; } - if(pclsObj) pclsObj->Release(); - pEnumerator->Release(); return nullptr; } diff --git a/src/detection/bios/bios_windows.cpp b/src/detection/bios/bios_windows.cpp index d04726ebb..a48d5d538 100644 --- a/src/detection/bios/bios_windows.cpp +++ b/src/detection/bios/bios_windows.cpp @@ -12,27 +12,17 @@ extern "C" void ffDetectBios(FFBiosResult* bios) ffStrbufInit(&bios->biosVendor); ffStrbufInit(&bios->biosVersion); - IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Name, ReleaseDate, Version, Manufacturer FROM Win32_BIOS", &bios->error); - if(!pEnumerator) + FFWmiQuery query(L"SELECT Name, ReleaseDate, Version, Manufacturer FROM Win32_BIOS", &bios->error); + if(!query) return; - IWbemClassObject *pclsObj = NULL; - ULONG uReturn = 0; - - pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); - - if(uReturn == 0) + if(FFWmiRecord record = query.next()) { - ffStrbufInitS(&bios->error, "No Wmi result returned"); - pEnumerator->Release(); - return; + record.getString(L"Name", &bios->biosRelease); + record.getString(L"ReleaseDate", &bios->biosDate); + record.getString(L"Version", &bios->biosVersion); + record.getString(L"Manufacturer", &bios->biosVendor); } - - ffGetWmiObjString(pclsObj, L"Name", &bios->biosRelease); - ffGetWmiObjString(pclsObj, L"ReleaseDate", &bios->biosDate); - ffGetWmiObjString(pclsObj, L"Version", &bios->biosVersion); - ffGetWmiObjString(pclsObj, L"Manufacturer", &bios->biosVendor); - - pclsObj->Release(); - pEnumerator->Release(); + else + ffStrbufInitS(&bios->error, "No Wmi result returned"); } diff --git a/src/detection/board/board_windows.cpp b/src/detection/board/board_windows.cpp index 895d6f8ed..e0f92bcf5 100644 --- a/src/detection/board/board_windows.cpp +++ b/src/detection/board/board_windows.cpp @@ -11,26 +11,16 @@ extern "C" void ffDetectBoard(FFBoardResult* board) ffStrbufInit(&board->boardVendor); ffStrbufInit(&board->boardVersion); - IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Product, Version, Manufacturer FROM Win32_BaseBoard", &board->error); - if(!pEnumerator) + FFWmiQuery query(L"SELECT Product, Version, Manufacturer FROM Win32_BaseBoard", &board->error); + if(!query) return; - IWbemClassObject *pclsObj = NULL; - ULONG uReturn = 0; - - pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); - - if(uReturn == 0) + if(FFWmiRecord record = query.next()) { - ffStrbufInitS(&board->error, "No Wmi result returned"); - pEnumerator->Release(); - return; + record.getString(L"Product", &board->boardName); + record.getString(L"Manufacturer", &board->boardVendor); + record.getString(L"Version", &board->boardVersion); } - - ffGetWmiObjString(pclsObj, L"Product", &board->boardName); - ffGetWmiObjString(pclsObj, L"Manufacturer", &board->boardVendor); - ffGetWmiObjString(pclsObj, L"Version", &board->boardVersion); - - pclsObj->Release(); - pEnumerator->Release(); + else + ffStrbufInitS(&board->error, "No Wmi result returned"); } diff --git a/src/detection/cpu/cpu_windows.cpp b/src/detection/cpu/cpu_windows.cpp index 250212cfc..8740fa4b9 100644 --- a/src/detection/cpu/cpu_windows.cpp +++ b/src/detection/cpu/cpu_windows.cpp @@ -17,35 +17,26 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu, bool cached) ffStrbufInit(&cpu->name); ffStrbufInit(&cpu->vendor); - IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Name, Manufacturer, NumberOfCores, NumberOfLogicalProcessors, ThreadCount, CurrentClockSpeed, MaxClockSpeed FROM Win32_Processor WHERE ProcessorType = 3", nullptr); - if(!pEnumerator) + FFWmiQuery query(L"SELECT Name, Manufacturer, NumberOfCores, NumberOfLogicalProcessors, ThreadCount, CurrentClockSpeed, MaxClockSpeed FROM Win32_Processor WHERE ProcessorType = 3"); + if(!query) return; - IWbemClassObject *pclsObj = NULL; - ULONG uReturn = 0; - - if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0) + if(FFWmiRecord record = query.next()) { - pEnumerator->Release(); - return; + record.getString(L"Name", &cpu->name); + record.getString(L"Manufacturer", &cpu->vendor); + + uint64_t value; + + record.getUnsigned(L"NumberOfCores", &value); + cpu->coresPhysical = (uint16_t)value; + record.getUnsigned(L"NumberOfLogicalProcessors", &value); + cpu->coresLogical = (uint16_t)value; + record.getUnsigned(L"ThreadCount", &value); + cpu->coresOnline = (uint16_t)value; + record.getUnsigned(L"CurrentClockSpeed", &value); //There's no MinClockSpeed in Win32_Processor + cpu->frequencyMin = (double)value / 1000.0; + record.getUnsigned(L"MaxClockSpeed", &value); + cpu->frequencyMax = (double)value / 1000.0; } - - ffGetWmiObjString(pclsObj, L"Name", &cpu->name); - ffGetWmiObjString(pclsObj, L"Manufacturer", &cpu->vendor); - - uint64_t value; - - ffGetWmiObjUnsigned(pclsObj, L"NumberOfCores", &value); - cpu->coresPhysical = (uint16_t)value; - ffGetWmiObjUnsigned(pclsObj, L"NumberOfLogicalProcessors", &value); - cpu->coresLogical = (uint16_t)value; - ffGetWmiObjUnsigned(pclsObj, L"ThreadCount", &value); - cpu->coresOnline = (uint16_t)value; - ffGetWmiObjUnsigned(pclsObj, L"CurrentClockSpeed", &value); //There's no MinClockSpeed in Win32_Processor - cpu->frequencyMin = (double)value / 1000.0; - ffGetWmiObjUnsigned(pclsObj, L"MaxClockSpeed", &value); - cpu->frequencyMax = (double)value / 1000.0; - - pclsObj->Release(); - pEnumerator->Release(); } diff --git a/src/detection/cpuUsage/cpuUsage_nowait_windows.cpp b/src/detection/cpuUsage/cpuUsage_nowait_windows.cpp index 19af6ffbe..7ef1aa855 100644 --- a/src/detection/cpuUsage/cpuUsage_nowait_windows.cpp +++ b/src/detection/cpuUsage/cpuUsage_nowait_windows.cpp @@ -5,22 +5,14 @@ extern "C" { extern "C" const char* ffGetCpuUsageResultNoWait(double* result) { - IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT LoadPercentage FROM Win32_Processor", nullptr); - if(!pEnumerator) + FFWmiQuery query(L"SELECT LoadPercentage FROM Win32_Processor"); + if(!query) return "Query WMI service failed"; - IWbemClassObject *pclsObj = NULL; - ULONG uReturn = 0; - - if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0) - { - pEnumerator->Release(); + if(FFWmiRecord record = query.next()) + record.getReal(L"LoadPercentage", result); + else return "No WMI result returned"; - } - ffGetWmiObjReal(pclsObj, L"LoadPercentage", result); - - pclsObj->Release(); - pEnumerator->Release(); - return NULL; + return nullptr; } diff --git a/src/detection/font/font_windows.cpp b/src/detection/font/font_windows.cpp index 0ade9812e..3d883bd58 100644 --- a/src/detection/font/font_windows.cpp +++ b/src/detection/font/font_windows.cpp @@ -9,34 +9,26 @@ extern "C" { extern "C" void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result) { - wchar_t query[256] = {}; - swprintf(query, 256, L"SELECT IconTitleFaceName, IconTitleSize FROM Win32_Desktop WHERE Name LIKE '%%\\\\%s'", instance->state.passwd->pw_name); + wchar_t sql[256] = {}; + swprintf(sql, 256, L"SELECT IconTitleFaceName, IconTitleSize FROM Win32_Desktop WHERE Name LIKE '%%\\\\%s'", instance->state.passwd->pw_name); - IEnumWbemClassObject* pEnumerator = ffQueryWmi(query, &result->error); - if(!pEnumerator) + FFWmiQuery query(sql, &result->error); + if(!query) return; - IWbemClassObject *pclsObj = NULL; - ULONG uReturn = 0; - - if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0) + if(FFWmiRecord record = query.next()) { - ffStrbufInitS(&result->error, "No WMI result returned"); - pEnumerator->Release(); - return; + FFstrbuf fontName; + ffStrbufInit(&fontName); + record.getString(L"IconTitleFaceName", &fontName); + + uint64_t fontSize; + record.getUnsigned(L"IconTitleSize", &fontSize); + + ffStrbufAppendF(&result->fonts[0], "%*s (%upt)", fontName.length, fontName.chars, (unsigned)fontSize); + + ffStrbufDestroy(&fontName); } - - FFstrbuf fontName; - ffStrbufInit(&fontName); - ffGetWmiObjString(pclsObj, L"IconTitleFaceName", &fontName); - - uint64_t fontSize; - ffGetWmiObjUnsigned(pclsObj, L"IconTitleSize", &fontSize); - - ffStrbufAppendF(&result->fonts[0], "%*s (%upt)", fontName.length, fontName.chars, (unsigned)fontSize); - - ffStrbufDestroy(&fontName); - - pclsObj->Release(); - pEnumerator->Release(); + else + ffStrbufInitS(&result->error, "No WMI result returned"); } diff --git a/src/detection/gpu/gpu_windows.cpp b/src/detection/gpu/gpu_windows.cpp index d99885633..374c8e035 100644 --- a/src/detection/gpu/gpu_windows.cpp +++ b/src/detection/gpu/gpu_windows.cpp @@ -8,20 +8,16 @@ const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance) { FF_UNUSED(instance); - IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Name, AdapterCompatibility, DriverVersion FROM Win32_VideoController", nullptr); - - if(!pEnumerator) + FFWmiQuery query(L"SELECT Name, AdapterCompatibility, DriverVersion FROM Win32_VideoController", nullptr); + if(!query) return "Query WMI service failed"; - IWbemClassObject *pclsObj = NULL; - ULONG uReturn = 0; - - while(SUCCEEDED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) && uReturn != 0) + while(FFWmiRecord record = query.next()) { FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); ffStrbufInit(&gpu->vendor); - ffGetWmiObjString(pclsObj, L"AdapterCompatibility", &gpu->vendor); + record.getString(L"AdapterCompatibility", &gpu->vendor); if(ffStrbufStartsWithS(&gpu->vendor, "Intel ")) { //Intel returns "Intel Corporation", not sure about AMD @@ -29,16 +25,14 @@ const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance) } ffStrbufInit(&gpu->name); - ffGetWmiObjString(pclsObj, L"Name", &gpu->name); + record.getString(L"Name", &gpu->name); ffStrbufInit(&gpu->driver); - ffGetWmiObjString(pclsObj, L"DriverVersion", &gpu->driver); + record.getString(L"DriverVersion", &gpu->driver); gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; } - if(pclsObj) pclsObj->Release(); - pEnumerator->Release(); return nullptr; } diff --git a/src/detection/host/host_windows.cpp b/src/detection/host/host_windows.cpp index 60f3fcedf..5d0333db8 100644 --- a/src/detection/host/host_windows.cpp +++ b/src/detection/host/host_windows.cpp @@ -16,25 +16,17 @@ extern "C" void ffDetectHostImpl(FFHostResult* host) ffStrbufInit(&host->chassisVendor); ffStrbufInit(&host->chassisVersion); - IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Name, Version, SKUNumber, Vendor FROM Win32_ComputerSystemProduct", &host->error); - if(!pEnumerator) + FFWmiQuery query(L"SELECT Name, Version, SKUNumber, Vendor FROM Win32_ComputerSystemProduct", &host->error); + if(!query) return; - IWbemClassObject *pclsObj = NULL; - ULONG uReturn = 0; - - if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0) + if(FFWmiRecord record = query.next()) { - ffStrbufInitS(&host->error, "No Wmi result returned"); - pEnumerator->Release(); - return; + record.getString(L"Name", &host->productName); + record.getString(L"Version", &host->productVersion); + record.getString(L"SKUNumber", &host->productSku); + record.getString(L"Vendor", &host->sysVendor); } - - ffGetWmiObjString(pclsObj, L"Name", &host->productName); - ffGetWmiObjString(pclsObj, L"Version", &host->productVersion); - ffGetWmiObjString(pclsObj, L"SKUNumber", &host->productSku); - ffGetWmiObjString(pclsObj, L"Vendor", &host->sysVendor); - - pclsObj->Release(); - pEnumerator->Release(); + else + ffStrbufInitS(&host->error, "No Wmi result returned"); } diff --git a/src/detection/memory/memory_windows.cpp b/src/detection/memory/memory_windows.cpp index 91a42ef3c..a11308e0d 100644 --- a/src/detection/memory/memory_windows.cpp +++ b/src/detection/memory/memory_windows.cpp @@ -5,58 +5,40 @@ extern "C" { void detectRam(FFMemoryStorage* ram) { - IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT TotalVisibleMemorySize, FreePhysicalMemory FROM Win32_OperatingSystem", &ram->error); - if(!pEnumerator) + FFWmiQuery query(L"SELECT TotalVisibleMemorySize, FreePhysicalMemory FROM Win32_OperatingSystem", &ram->error); + if(!query) return; - IWbemClassObject *pclsObj = NULL; - ULONG uReturn = 0; - - if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0) + if(FFWmiRecord record = query.next()) { - ffStrbufInitS(&ram->error, "No WMI result returned"); - pEnumerator->Release(); - return; + //KB + record.getUnsigned(L"TotalVisibleMemorySize", &ram->bytesTotal); + uint64_t bytesFree; + record.getUnsigned(L"FreePhysicalMemory", &bytesFree); + ram->bytesUsed = ram->bytesTotal - bytesFree; + ram->bytesTotal *= 1024; + ram->bytesUsed *= 1024; } - - //KB - ffGetWmiObjUnsigned(pclsObj, L"TotalVisibleMemorySize", &ram->bytesTotal); - uint64_t bytesFree; - ffGetWmiObjUnsigned(pclsObj, L"FreePhysicalMemory", &bytesFree); - ram->bytesUsed = ram->bytesTotal - bytesFree; - - pclsObj->Release(); - pEnumerator->Release(); - - ram->bytesTotal *= 1024; - ram->bytesUsed *= 1024; + else + ffStrbufInitS(&ram->error, "No Wmi result returned"); } void detectSwap(FFMemoryStorage* swap) { - IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT AllocatedBaseSize, CurrentUsage FROM Win32_PageFileUsage", &swap->error); - if(!pEnumerator) + FFWmiQuery query(L"SELECT AllocatedBaseSize, CurrentUsage FROM Win32_PageFileUsage", &swap->error); + if(!query) return; - IWbemClassObject *pclsObj = NULL; - ULONG uReturn = 0; - - if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0) + if(FFWmiRecord record = query.next()) { - ffStrbufInitS(&swap->error, "No WMI result returned"); - pEnumerator->Release(); - return; + //MB + record.getUnsigned(L"AllocatedBaseSize", &swap->bytesTotal); + record.getUnsigned(L"CurrentUsage", &swap->bytesUsed); + swap->bytesTotal *= 1024 * 1024; + swap->bytesUsed *= 1024 * 1024; } - - //MB - ffGetWmiObjUnsigned(pclsObj, L"AllocatedBaseSize", &swap->bytesTotal); - ffGetWmiObjUnsigned(pclsObj, L"CurrentUsage", &swap->bytesUsed); - - pclsObj->Release(); - pEnumerator->Release(); - - swap->bytesTotal *= 1024 * 1024; - swap->bytesUsed *= 1024 * 1024; + else + ffStrbufInitS(&swap->error, "No Wmi result returned"); } extern "C" diff --git a/src/detection/os/os_windows.cpp b/src/detection/os/os_windows.cpp index c6dd9977e..e28607c9c 100644 --- a/src/detection/os/os_windows.cpp +++ b/src/detection/os/os_windows.cpp @@ -19,65 +19,55 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance) ffStrbufInit(&os->systemName); ffStrbufInit(&os->architecture); - IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Caption, Version, BuildNumber, OSArchitecture FROM Win32_OperatingSystem", nullptr); - - if(!pEnumerator) + FFWmiQuery query(L"SELECT Caption, Version, BuildNumber, OSArchitecture FROM Win32_OperatingSystem"); + if(!query) return; - IWbemClassObject *pclsObj = NULL; - ULONG uReturn = 0; - - if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0) + if(FFWmiRecord record = query.next()) { - pEnumerator->Release(); - return; - } - - ffGetWmiObjString(pclsObj, L"Caption", &os->variant); - if(ffStrbufStartsWithS(&os->variant, "Microsoft Windows ")) - { - ffStrbufAppendS(&os->name, "Microsoft Windows"); - ffStrbufAppendS(&os->prettyName, "Windows"); - - ffStrbufSubstrAfter(&os->variant, strlen("Microsoft Windows ") - 1); - - if(ffStrbufStartsWithS(&os->variant, "Server ")) + record.getString(L"Caption", &os->variant); + if(ffStrbufStartsWithS(&os->variant, "Microsoft Windows ")) { - ffStrbufAppendS(&os->name, " Server"); - ffStrbufAppendS(&os->prettyName, " Server"); - ffStrbufSubstrAfter(&os->variant, strlen(" Server") - 1); - } + ffStrbufAppendS(&os->name, "Microsoft Windows"); + ffStrbufAppendS(&os->prettyName, "Windows"); - uint32_t index = ffStrbufFirstIndexC(&os->variant, ' '); - ffStrbufAppendNS(&os->version, index, os->variant.chars); - ffStrbufSubstrAfter(&os->variant, index); + ffStrbufSubstrAfter(&os->variant, strlen("Microsoft Windows ") - 1); - // Windows Server 20xx Rx - if(ffStrbufEndsWithC(&os->prettyName, 'r')) - { - if(os->variant.chars[0] == 'R' && - isdigit(os->variant.chars[1]) && - (os->variant.chars[2] == '\0' || os->variant.chars[2] == ' ')) + if(ffStrbufStartsWithS(&os->variant, "Server ")) { - ffStrbufAppendF(&os->version, " R%c", os->variant.chars[1]); - ffStrbufSubstrAfter(&os->variant, strlen("Rx ") - 1); + ffStrbufAppendS(&os->name, " Server"); + ffStrbufAppendS(&os->prettyName, " Server"); + ffStrbufSubstrAfter(&os->variant, strlen(" Server") - 1); + } + + uint32_t index = ffStrbufFirstIndexC(&os->variant, ' '); + ffStrbufAppendNS(&os->version, index, os->variant.chars); + ffStrbufSubstrAfter(&os->variant, index); + + // Windows Server 20xx Rx + if(ffStrbufEndsWithC(&os->prettyName, 'r')) + { + if(os->variant.chars[0] == 'R' && + isdigit(os->variant.chars[1]) && + (os->variant.chars[2] == '\0' || os->variant.chars[2] == ' ')) + { + ffStrbufAppendF(&os->version, " R%c", os->variant.chars[1]); + ffStrbufSubstrAfter(&os->variant, strlen("Rx ") - 1); + } } } + else + { + // Unknown Windows name, please report this + ffStrbufAppend(&os->name, &os->variant); + ffStrbufClear(&os->variant); + } + + ffStrbufAppendF(&os->id, "%*s %*s", os->prettyName.length, os->prettyName.chars, os->version.length, os->version.chars); + + record.getString(L"BuildNumber", &os->buildID); + record.getString(L"OSArchitecture", &os->architecture); + + ffStrbufSetS(&os->systemName, instance->state.utsname.sysname); } - else - { - // Unknown Windows name, please report this - ffStrbufAppend(&os->name, &os->variant); - ffStrbufClear(&os->variant); - } - - ffStrbufAppendF(&os->id, "%*s %*s", os->prettyName.length, os->prettyName.chars, os->version.length, os->version.chars); - - ffGetWmiObjString(pclsObj, L"BuildNumber", &os->buildID); - ffGetWmiObjString(pclsObj, L"OSArchitecture", &os->architecture); - - ffStrbufSetS(&os->systemName, instance->state.utsname.sysname); - - pclsObj->Release(); - pEnumerator->Release(); } diff --git a/src/detection/processes/processes_windows.cpp b/src/detection/processes/processes_windows.cpp index 5d491d16e..68de794a6 100644 --- a/src/detection/processes/processes_windows.cpp +++ b/src/detection/processes/processes_windows.cpp @@ -7,24 +7,19 @@ uint32_t ffDetectProcesses(FFinstance* instance, FFstrbuf* error) { FF_UNUSED(instance); - IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT NumberOfProcesses FROM Win32_OperatingSystem", error); - - if(!pEnumerator) + FFWmiQuery query(L"SELECT NumberOfProcesses FROM Win32_OperatingSystem", error); + if(!query) return 0; - IWbemClassObject *pclsObj = NULL; - ULONG uReturn = 0; - - if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0) + if(FFWmiRecord record = query.next()) + { + uint64_t result = 0; + record.getUnsigned(L"NumberOfProcesses", &result); + return (uint32_t)result; + } + else { ffStrbufAppendS(error, "No Wmi result returned"); - pEnumerator->Release(); return 0; } - - uint64_t result = 0; - ffGetWmiObjUnsigned(pclsObj, L"NumberOfProcesses", &result); - pclsObj->Release(); - pEnumerator->Release(); - return (uint32_t)result; } diff --git a/src/detection/terminalshell/terminalshell_windows.cpp b/src/detection/terminalshell/terminalshell_windows.cpp index 71a34c6ea..770e043eb 100644 --- a/src/detection/terminalshell/terminalshell_windows.cpp +++ b/src/detection/terminalshell/terminalshell_windows.cpp @@ -65,45 +65,34 @@ static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrb if(pid == 0) pid = GetCurrentProcessId(); - wchar_t query[256] = {}; - swprintf(query, 256, L"SELECT %ls %ls ParentProcessId FROM Win32_Process WHERE ProcessId = %" PRIu32, + wchar_t sql[256] = {}; + swprintf(sql, 256, L"SELECT %ls %ls ParentProcessId FROM Win32_Process WHERE ProcessId = %" PRIu32, pname ? L"Name," : L"", pname ? L"ExecutablePath," : L"", pid); - IEnumWbemClassObject* pEnumerator = ffQueryWmi(query, nullptr); - if(!pEnumerator) + FFWmiQuery query(sql); + if(!query) return false; - IWbemClassObject *pclsObj = nullptr; - ULONG uReturn = 0; - - if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0) + if(FFWmiRecord record = query.next()) { - pEnumerator->Release(); - return false; + if(ppid) + { + uint64_t value; + record.getUnsigned(L"ParentProcessId", &value); + *ppid = (uint32_t) value; + } + + if(pname) + record.getString(L"Name", pname); + + if(exe) + record.getString(L"ExecutablePath", exe); + + if(exeName) + *exeName = exe->chars + ffStrbufLastIndexC(exe, '\\') + 1; } - - if(ppid) - { - uint64_t value; - ffGetWmiObjUnsigned(pclsObj, L"ParentProcessId", &value); - *ppid = (uint32_t) value; - } - - if(pname) - ffGetWmiObjString(pclsObj, L"Name", pname); - - if(exe) - ffGetWmiObjString(pclsObj, L"ExecutablePath", exe); - - if(exeName) - { - *exeName = exe->chars + ffStrbufLastIndexC(exe, '\\') + 1; - } - - pclsObj->Release(); - pEnumerator->Release(); return true; } diff --git a/src/detection/users/users_windows.cpp b/src/detection/users/users_windows.cpp index 41dd9674b..9e50cd365 100644 --- a/src/detection/users/users_windows.cpp +++ b/src/detection/users/users_windows.cpp @@ -5,20 +5,16 @@ extern "C" { void ffDetectUsers(FFlist* users, FFstrbuf* error) { - IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Antecedent FROM Win32_LoggedOnUser", error); - - if(!pEnumerator) + FFWmiQuery query(L"SELECT Antecedent FROM Win32_LoggedOnUser", error); + if(!query) return; - IWbemClassObject *pclsObj = NULL; - ULONG uReturn = 0; - next: - while(SUCCEEDED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) && uReturn != 0) + while(FFWmiRecord record = query.next()) { FFstrbuf antecedent; ffStrbufInit(&antecedent); - ffGetWmiObjString(pclsObj, L"Antecedent", &antecedent); // \\.\root\cimv2:Win32_Account.Domain="DOMAIN",Name="NAME" + record.getString(L"Antecedent", &antecedent); // \\.\root\cimv2:Win32_Account.Domain="DOMAIN",Name="NAME" ffStrbufTrimRight(&antecedent, '"'); // \\.\root\cimv2:Win32_Account.Domain="DOMAIN",Name="NAME ffStrbufSubstrAfterFirstC(&antecedent, '"'); // DOMAIN",Name="NAME uint32_t index = ffStrbufFirstIndexC(&antecedent, '"'); @@ -36,7 +32,4 @@ next: if(users->length == 0) ffStrbufAppendS(error, "Unable to detect users"); - - if(pclsObj) pclsObj->Release(); - pEnumerator->Release(); } diff --git a/src/util/windows/utsname.c b/src/util/windows/utsname.c deleted file mode 100644 index 403f5e6fd..000000000 --- a/src/util/windows/utsname.c +++ /dev/null @@ -1,59 +0,0 @@ -// https://github.com/tniessen/iperf-windows/blob/master/win32-compat/sys/utsname.c - -#define WIN32_LEAN_AND_MEAN -#include - -#include - -#include "utsname.h" - -int uname(struct utsname *name) -{ - memset(name, 0, sizeof(*name)); - - // Get Windows version info - OSVERSIONINFOA versionInfo = { - .dwOSVersionInfoSize = sizeof(OSVERSIONINFO), - }; - GetVersionExA(&versionInfo); - - // Get hardware info - SYSTEM_INFO sysInfo = {0}; - GetSystemInfo(&sysInfo); - - // Set implementation name - strcpy(name->sysname, "Windows_NT"); - sprintf(name->release, "%u.%u.%u", (unsigned)versionInfo.dwMajorVersion, (unsigned)versionInfo.dwMinorVersion, (unsigned)versionInfo.dwBuildNumber); - name->version[0] = '\0'; - - // Set hostname - DWORD bufSize = UTSNAME_MAXLENGTH - 1; - if(GetComputerNameA(name->nodename, &bufSize)) - return 1; - name->nodename[bufSize] = '\0'; - - // Set processor architecture - switch (sysInfo.wProcessorArchitecture) - { - case PROCESSOR_ARCHITECTURE_AMD64: - strcpy(name->machine, "x86_64"); - break; - case PROCESSOR_ARCHITECTURE_IA64: - strcpy(name->machine, "ia64"); - break; - case PROCESSOR_ARCHITECTURE_INTEL: - strcpy(name->machine, "x86"); - break; - case PROCESSOR_ARCHITECTURE_ARM64: - strcpy(name->machine, "aarch64"); - break; - case PROCESSOR_ARCHITECTURE_ARM: - strcpy(name->machine, "arm"); - break; - case PROCESSOR_ARCHITECTURE_UNKNOWN: - default: - strcpy(name->machine, "unknown"); - } - - return 0; -} diff --git a/src/util/windows/utsname.cpp b/src/util/windows/utsname.cpp new file mode 100644 index 000000000..10c0f7b68 --- /dev/null +++ b/src/util/windows/utsname.cpp @@ -0,0 +1,35 @@ +#include "util/windows/wmi.hpp" +extern "C" { + #include "utsname.h" +} + +int uname(struct utsname *name) +{ + memset(name, 0, sizeof(*name)); + + strncpy(name->sysname, "Windows_NT", UTSNAME_MAXLENGTH); + + FFWmiQuery query(L"SELECT Version, CSName, OSArchitecture FROM Win32_OperatingSystem"); + if(!query) + return -1; + + if(FFWmiRecord record = query.next()) + { + FFstrbuf value; + ffStrbufInit(&value); + record.getString(L"Version", &value); + strncpy(name->release, value.chars, UTSNAME_MAXLENGTH); + + ffStrbufClear(&value); + record.getString(L"CSName", &value); + strncpy(name->nodename, value.chars, UTSNAME_MAXLENGTH); + + ffStrbufClear(&value); + record.getString(L"OSArchitecture", &value); + strncpy(name->machine, value.chars, UTSNAME_MAXLENGTH); + + ffStrbufDestroy(&value); + } + + return 0; +} diff --git a/src/util/windows/wmi.cpp b/src/util/windows/wmi.cpp index 9b1a120d0..6a273f86a 100644 --- a/src/util/windows/wmi.cpp +++ b/src/util/windows/wmi.cpp @@ -4,6 +4,21 @@ #include #include +namespace +{ + // Provide our bstr_t to avoid libstdc++ dependency + struct bstr_t + { + explicit bstr_t(const wchar_t* str) noexcept: _bstr(SysAllocString(str)) {} + ~bstr_t() noexcept { SysFreeString(_bstr); } + explicit operator const wchar_t*() const noexcept { return _bstr; } + operator BSTR() const noexcept { return _bstr; } + + private: + BSTR _bstr; + }; +} + //https://learn.microsoft.com/en-us/windows/win32/wmisdk/example--getting-wmi-data-from-the-local-computer //https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/computer-system-hardware-classes static void CoUninitializeWrap() @@ -105,8 +120,8 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID, PVOID *lpContext) return TRUE; } - -IEnumWbemClassObject* ffQueryWmi(const wchar_t* queryStr, FFstrbuf* error) +FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error) + : pEnumerator(nullptr) { static INIT_ONCE s_InitOnce = INIT_ONCE_STATIC_INIT; const char* context; @@ -114,11 +129,10 @@ IEnumWbemClassObject* ffQueryWmi(const wchar_t* queryStr, FFstrbuf* error) { if(error) ffStrbufInitS(error, context); - return nullptr; + return; } // Use the IWbemServices pointer to make requests of WMI - IEnumWbemClassObject* pEnumerator = nullptr; HRESULT hres; hres = ((IWbemServices*)context)->ExecQuery( @@ -132,13 +146,11 @@ IEnumWbemClassObject* ffQueryWmi(const wchar_t* queryStr, FFstrbuf* error) { if(error) ffStrbufAppendF(error, "Query for '%ls' failed. Error code = 0x%lX", queryStr, hres); - return nullptr; } - - return pEnumerator; } -void ffBstrToStrbuf(BSTR bstr, FFstrbuf* strbuf) { +static void ffBstrToStrbuf(BSTR bstr, FFstrbuf* strbuf) +{ int len = (int)SysStringLen(bstr); if(len <= 0) { @@ -152,7 +164,7 @@ void ffBstrToStrbuf(BSTR bstr, FFstrbuf* strbuf) { strbuf->chars[size_needed] = '\0'; } -bool ffGetWmiObjString(IWbemClassObject* obj, const wchar_t* key, FFstrbuf* strbuf) +bool FFWmiRecord::getString(const wchar_t* key, FFstrbuf* strbuf) { bool result = true; @@ -202,7 +214,7 @@ bool ffGetWmiObjString(IWbemClassObject* obj, const wchar_t* key, FFstrbuf* strb return result; } -bool ffGetWmiObjSigned(IWbemClassObject* obj, const wchar_t* key, int64_t* integer) +bool FFWmiRecord::getSigned(const wchar_t* key, int64_t* integer) { bool result = true; @@ -237,7 +249,7 @@ bool ffGetWmiObjSigned(IWbemClassObject* obj, const wchar_t* key, int64_t* integ return result; } -bool ffGetWmiObjUnsigned(IWbemClassObject* obj, const wchar_t* key, uint64_t* integer) +bool FFWmiRecord::getUnsigned(const wchar_t* key, uint64_t* integer) { bool result = true; @@ -271,7 +283,7 @@ bool ffGetWmiObjUnsigned(IWbemClassObject* obj, const wchar_t* key, uint64_t* in return result; } -bool ffGetWmiObjReal(IWbemClassObject* obj, const wchar_t* key, double* real) +bool FFWmiRecord::getReal(const wchar_t* key, double* real) { bool result = true; diff --git a/src/util/windows/wmi.hpp b/src/util/windows/wmi.hpp index 53122dfa2..0fec1ee64 100644 --- a/src/util/windows/wmi.hpp +++ b/src/util/windows/wmi.hpp @@ -11,32 +11,51 @@ extern "C" { #include -// is not usable in MSYS, so provide our simple bstr_t implementation -struct bstr_t +struct FFWmiRecord { - explicit bstr_t(const wchar_t* str) noexcept: _bstr(SysAllocString(str)) {} + IWbemClassObject* obj; - ~bstr_t() noexcept { SysFreeString(_bstr); } + explicit FFWmiRecord(IEnumWbemClassObject* pEnumerator): obj(nullptr) { + if(!pEnumerator) return; - explicit operator const wchar_t*() const noexcept { - return _bstr; + ULONG ret; + bool ok = SUCCEEDED(pEnumerator->Next(WBEM_INFINITE, 1, &obj, &ret)) && ret; + if(!ok) obj = nullptr; } - - operator BSTR() const noexcept { - return _bstr; + FFWmiRecord(const FFWmiRecord&) = delete; + FFWmiRecord(FFWmiRecord&& other) { + obj = other.obj; + other.obj = nullptr; } + ~FFWmiRecord() { if(obj) obj->Release(); } + explicit operator bool() { return !!obj; } -private: - BSTR _bstr; + bool getString(const wchar_t* key, FFstrbuf* strbuf); + bool getSigned(const wchar_t* key, int64_t* integer); + bool getUnsigned(const wchar_t* key, uint64_t* integer); + bool getReal(const wchar_t* key, double* real); }; -void ffBstrToStrbuf(BSTR bstr, FFstrbuf* strbuf); +struct FFWmiQuery +{ + IEnumWbemClassObject* pEnumerator = nullptr; -IEnumWbemClassObject* ffQueryWmi(const wchar_t* queryStr, FFstrbuf* error); -bool ffGetWmiObjString(IWbemClassObject* obj, const wchar_t* key, FFstrbuf* strbuf); -bool ffGetWmiObjSigned(IWbemClassObject* obj, const wchar_t* key, int64_t* integer); -bool ffGetWmiObjUnsigned(IWbemClassObject* obj, const wchar_t* key, uint64_t* integer); -bool ffGetWmiObjReal(IWbemClassObject* obj, const wchar_t* key, double* real); + FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error = nullptr); + explicit FFWmiQuery(IEnumWbemClassObject* pEnumerator): pEnumerator(pEnumerator) {} + FFWmiQuery(const FFWmiQuery& other) = delete; + FFWmiQuery(FFWmiQuery&& other) { + pEnumerator = other.pEnumerator; + other.pEnumerator = nullptr; + } + ~FFWmiQuery() { if(pEnumerator) pEnumerator->Release(); } + + explicit operator bool() { return !!pEnumerator; } + + FFWmiRecord next() { + FFWmiRecord result(pEnumerator); + return result; + } +}; #else // Win32 COM headers requires C++ compiler