diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index 851ef5e4b..34e116256 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -2,17 +2,12 @@ #include "detection/gpu/gpu_driver_specific.h" #include "util/windows/unicode.h" #include "util/windows/registry.h" +#include "util/mallocHelper.h" #define INITGUID -#include -#include -#include - -static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev) -{ - if(*hdev) - SetupDiDestroyDeviceInfoList(*hdev); -} +#include +#include +#include #define FF_EMPTY_GUID_STR L"{00000000-0000-0000-0000-000000000000}" enum { FF_GUID_STRLEN = sizeof(FF_EMPTY_GUID_STR) / sizeof(wchar_t) - 1 }; @@ -24,21 +19,38 @@ const uint32_t regDriverKeyPrefixLength = (uint32_t) __builtin_strlen("SYSTEM\\C const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) { - HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) = - SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, NULL, NULL, DIGCF_PRESENT); + ULONG devInfListSize = 0; + if (CM_Get_Device_Interface_List_SizeW(&devInfListSize, (LPGUID)&GUID_DEVINTERFACE_DISPLAY_ADAPTER, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS || devInfListSize <= 1) + return "No display devices found"; - if(hdev == INVALID_HANDLE_VALUE) - return "SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY) failed"; + FF_AUTO_FREE DEVINSTID_W devInfList = malloc(devInfListSize * sizeof(*devInfList)); - SP_DEVINFO_DATA did = { .cbSize = sizeof(did) }; - for (DWORD idev = 0; SetupDiEnumDeviceInfo(hdev, idev, &did); ++idev) + if (CM_Get_Device_Interface_ListW((LPGUID)&GUID_DEVINTERFACE_DISPLAY_ADAPTER, NULL, devInfList, devInfListSize, CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS) + return "CM_Get_Device_Interface_ListW failed"; + + for (wchar_t* devInf = devInfList; *devInf; devInf += wcslen(devInf) + 1) { + if (wcsncmp(devInf, L"\\\\?\\ROOT#BasicDisplay#", 22) == 0) + continue; // Skip Microsoft Basic Display Adapter + + DEVINST devInst = 0; + wchar_t buffer[256]; + ULONG bufferLen = 0; + + { + DEVPROPTYPE propertyType; + bufferLen = sizeof(buffer); + if (CM_Get_Device_Interface_PropertyW(devInf, &DEVPKEY_Device_InstanceId, &propertyType, (PBYTE) buffer, &bufferLen, 0) != CR_SUCCESS || + CM_Locate_DevNodeW(&devInst, buffer, CM_LOCATE_DEVNODE_NORMAL) != CR_SUCCESS) + continue; + } + FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); ffStrbufInit(&gpu->vendor); ffStrbufInit(&gpu->name); ffStrbufInit(&gpu->driver); ffStrbufInit(&gpu->memoryType); - ffStrbufInitStatic(&gpu->platformApi, "SetupAPI"); + ffStrbufInitStatic(&gpu->platformApi, "CM API"); gpu->index = FF_GPU_INDEX_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; @@ -49,71 +61,76 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpu->frequency = FF_GPU_FREQUENCY_UNSET; uint32_t pciBus = 0, pciAddr = 0, pciDev = 0, pciFunc = 0; - if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_BUSNUMBER, NULL, (PBYTE) &pciBus, sizeof(pciBus), NULL) && - SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_ADDRESS, NULL, (PBYTE) &pciAddr, sizeof(pciAddr), NULL)) - { - pciDev = (pciAddr >> 16) & 0xFFFF; - pciFunc = pciAddr & 0xFFFF; - gpu->deviceId = (pciBus * 1000ull) + (pciDev * 10ull) + pciFunc; - pciAddr = 1; // Set to 1 to indicate that the device is a PCI device - } - wchar_t buffer[256]; + ULONG pciBufLen = sizeof(pciBus); + if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_BUSNUMBER, NULL, &pciBus, &pciBufLen, 0) == CR_SUCCESS) + { + pciBufLen = sizeof(pciAddr); + if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_ADDRESS, NULL, &pciAddr, &pciBufLen, 0) == CR_SUCCESS) + { + pciDev = (pciAddr >> 16) & 0xFFFF; + pciFunc = pciAddr & 0xFFFF; + gpu->deviceId = (pciBus * 1000ull) + (pciDev * 10ull) + pciFunc; + pciAddr = 1; // Set to 1 to indicate that the device is a PCI device + } + } uint64_t adapterLuid = 0; - FF_HKEY_AUTO_DESTROY hVideoIdKey = SetupDiOpenDevRegKey(hdev, &did, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); - if (!hVideoIdKey) continue; - DWORD bufferLen = sizeof(buffer); - if (RegGetValueW(hVideoIdKey, NULL, L"VideoID", RRF_RT_REG_SZ, NULL, buffer, &bufferLen) == ERROR_SUCCESS && - bufferLen == (FF_GUID_STRLEN + 1) * sizeof(wchar_t)) + FF_HKEY_AUTO_DESTROY hVideoIdKey = NULL; + if (CM_Open_DevNode_Key(devInst, KEY_QUERY_VALUE, 0, RegDisposition_OpenExisting, &hVideoIdKey, CM_REGISTRY_HARDWARE) == CR_SUCCESS) { - wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, buffer, FF_GUID_STRLEN); - FF_HKEY_AUTO_DESTROY hDirectxKey = NULL; - if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL)) + bufferLen = sizeof(buffer); + if (RegGetValueW(hVideoIdKey, NULL, L"VideoID", RRF_RT_REG_SZ, NULL, buffer, &bufferLen) == ERROR_SUCCESS && + bufferLen == (FF_GUID_STRLEN + 1) * sizeof(wchar_t)) { - uint32_t vendorId = 0; - if(ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId) - ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId)); - - if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) - gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; - - uint64_t dedicatedVideoMemory = 0; - if(ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, NULL)) + wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, buffer, FF_GUID_STRLEN); + FF_HKEY_AUTO_DESTROY hDirectxKey = NULL; + if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL)) { - if (gpu->type == FF_GPU_TYPE_UNKNOWN) - gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; - } + uint32_t vendorId = 0; + if(ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId) + ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId)); - uint64_t dedicatedSystemMemory, sharedSystemMemory; - if(ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, NULL) && - ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL)) - { - gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory; - gpu->shared.total = sharedSystemMemory; - } + if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) + gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; - if (ffRegReadUint64(hDirectxKey, L"AdapterLuid", &adapterLuid, NULL)) - { - if (!gpu->deviceId) gpu->deviceId = adapterLuid; - } + uint64_t dedicatedVideoMemory = 0; + if(ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, NULL)) + { + if (gpu->type == FF_GPU_TYPE_UNKNOWN) + gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; + } - uint32_t featureLevel = 0; - if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel) - ffStrbufSetF(&gpu->platformApi, "Direct3D 12.%u", (featureLevel & 0x0F00) >> 8); - else if(ffRegReadUint(hDirectxKey, L"MaxD3D11FeatureLevel", &featureLevel, NULL) && featureLevel) - ffStrbufSetF(&gpu->platformApi, "Direct3D 11.%u", (featureLevel & 0x0F00) >> 8); + uint64_t dedicatedSystemMemory, sharedSystemMemory; + if(ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, NULL) && + ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL)) + { + gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory; + gpu->shared.total = sharedSystemMemory; + } - uint64_t driverVersion = 0; - if(ffRegReadUint64(hDirectxKey, L"DriverVersion", &driverVersion, NULL) && driverVersion) - { - ffStrbufSetF(&gpu->driver, "%u.%u.%u.%u", - (unsigned) (driverVersion >> 48) & 0xFFFF, - (unsigned) (driverVersion >> 32) & 0xFFFF, - (unsigned) (driverVersion >> 16) & 0xFFFF, - (unsigned) (driverVersion >> 0) & 0xFFFF - ); + if (ffRegReadUint64(hDirectxKey, L"AdapterLuid", &adapterLuid, NULL)) + { + if (!gpu->deviceId) gpu->deviceId = adapterLuid; + } + + uint32_t featureLevel = 0; + if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel) + ffStrbufSetF(&gpu->platformApi, "Direct3D 12.%u", (featureLevel & 0x0F00) >> 8); + else if(ffRegReadUint(hDirectxKey, L"MaxD3D11FeatureLevel", &featureLevel, NULL) && featureLevel) + ffStrbufSetF(&gpu->platformApi, "Direct3D 11.%u", (featureLevel & 0x0F00) >> 8); + + uint64_t driverVersion = 0; + if(ffRegReadUint64(hDirectxKey, L"DriverVersion", &driverVersion, NULL) && driverVersion) + { + ffStrbufSetF(&gpu->driver, "%u.%u.%u.%u", + (unsigned) (driverVersion >> 48) & 0xFFFF, + (unsigned) (driverVersion >> 32) & 0xFFFF, + (unsigned) (driverVersion >> 16) & 0xFFFF, + (unsigned) (driverVersion >> 0) & 0xFFFF + ); + } } } } @@ -121,7 +138,8 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (gpu->vendor.length == 0) { bufferLen = sizeof(buffer); - if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DRIVER, NULL, (PBYTE) buffer, sizeof(buffer), &bufferLen) && bufferLen == (FF_GUID_STRLEN + strlen("\\0000") + 1) * 2) + if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_DRIVER, NULL, buffer, &bufferLen, 0) == CR_SUCCESS && + bufferLen == (FF_GUID_STRLEN + strlen("\\0000") + 1) * 2) { wmemcpy(regDriverKey + regDriverKeyPrefixLength, buffer, FF_GUID_STRLEN + strlen("\\0000")); FF_HKEY_AUTO_DESTROY hRegDriverKey = NULL; @@ -146,7 +164,8 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &dllName) && (options->temp || options->driverSpecific)) { unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0; - if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_HARDWAREID, NULL, (PBYTE) buffer, sizeof(buffer), NULL)) + bufferLen = sizeof(buffer); + if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_HARDWAREID, NULL, buffer, &bufferLen, 0) == CR_SUCCESS) { swscanf(buffer, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId); ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId)); @@ -189,7 +208,8 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (!gpu->name.length) { - if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DEVICEDESC, NULL, (PBYTE) buffer, sizeof(buffer), NULL)) + bufferLen = sizeof(buffer); + if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_DEVICEDESC, NULL, buffer, &bufferLen, 0) == CR_SUCCESS) ffStrbufSetWS(&gpu->name, buffer); } }