2 * The PCI Library -- List PCI devices on Win32 via Configuration Manager
4 * Copyright (c) 2021 Pali Rohár <pali@kernel.org>
6 * Can be freely distributed and used under the terms of the GNU GPL.
12 #include <ctype.h> /* for isxdigit() */
13 #include <stdio.h> /* for sprintf() */
14 #include <string.h> /* for strlen(), strchr(), strncmp() */
15 #include <wchar.h> /* for wcslen(), wcscpy() */
19 /* Unfortunately MinGW32 toolchain does not provide these cfgmgr32 constants. */
21 #ifndef RegDisposition_OpenExisting
22 #define RegDisposition_OpenExisting 0x00000001
25 #ifndef CM_REGISTRY_SOFTWARE
26 #define CM_REGISTRY_SOFTWARE 0x00000001
29 #ifndef CM_DRP_HARDWAREID
30 #define CM_DRP_HARDWAREID 0x00000002
32 #ifndef CM_DRP_SERVICE
33 #define CM_DRP_SERVICE 0x00000005
35 #ifndef CM_DRP_BUSNUMBER
36 #define CM_DRP_BUSNUMBER 0x00000016
38 #ifndef CM_DRP_ADDRESS
39 #define CM_DRP_ADDRESS 0x0000001D
42 #ifndef CR_INVALID_CONFLICT_LIST
43 #define CR_INVALID_CONFLICT_LIST 0x00000039
45 #ifndef CR_INVALID_INDEX
46 #define CR_INVALID_INDEX 0x0000003A
48 #ifndef CR_INVALID_STRUCTURE_SIZE
49 #define CR_INVALID_STRUCTURE_SIZE 0x0000003B
52 #ifndef fIOD_10_BIT_DECODE
53 #define fIOD_10_BIT_DECODE 0x0004
55 #ifndef fIOD_12_BIT_DECODE
56 #define fIOD_12_BIT_DECODE 0x0008
58 #ifndef fIOD_16_BIT_DECODE
59 #define fIOD_16_BIT_DECODE 0x0010
61 #ifndef fIOD_POSITIVE_DECODE
62 #define fIOD_POSITIVE_DECODE 0x0020
64 #ifndef fIOD_PASSIVE_DECODE
65 #define fIOD_PASSIVE_DECODE 0x0040
67 #ifndef fIOD_WINDOW_DECODE
68 #define fIOD_WINDOW_DECODE 0x0080
71 #define fIOD_PORT_BAR 0x0100
74 #ifndef fMD_WINDOW_DECODE
75 #define fMD_WINDOW_DECODE 0x0040
77 #ifndef fMD_MEMORY_BAR
78 #define fMD_MEMORY_BAR 0x0080
82 * Unfortunately MinGW32 toolchain does not provide import library for these
83 * cfgmgr32.dll functions. So resolve pointers to these functions at runtime.
86 #ifdef CM_Get_DevNode_Registry_PropertyA
87 #undef CM_Get_DevNode_Registry_PropertyA
89 static CONFIGRET (WINAPI *MyCM_Get_DevNode_Registry_PropertyA)(DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType, PVOID Buffer, PULONG pulLength, ULONG ulFlags);
90 #define CM_Get_DevNode_Registry_PropertyA MyCM_Get_DevNode_Registry_PropertyA
92 #ifdef CM_Get_DevNode_Registry_PropertyW
93 #undef CM_Get_DevNode_Registry_PropertyW
95 static CONFIGRET (WINAPI *MyCM_Get_DevNode_Registry_PropertyW)(DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType, PVOID Buffer, PULONG pulLength, ULONG ulFlags);
96 #define CM_Get_DevNode_Registry_PropertyW MyCM_Get_DevNode_Registry_PropertyW
98 #ifndef CM_Open_DevNode_Key
99 #undef CM_Open_DevNode_Key
101 static CONFIGRET (WINAPI *MyCM_Open_DevNode_Key)(DEVINST dnDevNode, REGSAM samDesired, ULONG ulHardwareProfile, REGDISPOSITION Disposition, PHKEY phkDevice, ULONG ulFlags);
102 #define CM_Open_DevNode_Key MyCM_Open_DevNode_Key
105 resolve_cfgmgr32_functions(void)
109 if (CM_Get_DevNode_Registry_PropertyA && CM_Get_DevNode_Registry_PropertyW && CM_Open_DevNode_Key)
112 cfgmgr32 = GetModuleHandleA("cfgmgr32.dll");
116 CM_Get_DevNode_Registry_PropertyA = (void *)GetProcAddress(cfgmgr32, "CM_Get_DevNode_Registry_PropertyA");
117 CM_Get_DevNode_Registry_PropertyW = (void *)GetProcAddress(cfgmgr32, "CM_Get_DevNode_Registry_PropertyW");
118 CM_Open_DevNode_Key = (void *)GetProcAddress(cfgmgr32, "CM_Open_DevNode_Key");
119 if (!CM_Get_DevNode_Registry_PropertyA || !CM_Get_DevNode_Registry_PropertyW || !CM_Open_DevNode_Key)
126 * cfgmgr32.dll uses custom non-Win32 error numbers which are unsupported by
127 * Win32 APIs like GetLastError() and FormatMessage() functions.
129 * Windows 7 instroduced new cfgmgr32.dll function CM_MapCrToWin32Err() for
130 * translating mapping CR_* errors to Win32 errors but most error codes are
131 * not mapped. So this function is unusable.
133 * Error strings for CR_* errors are defined in cmapi.rc file which is
134 * statically linked into some system libraries (e.g. filemgmt.dll,
135 * acledit.dll, netui0.dll or netui2.dll) but due to static linking it is
136 * not possible to access these error strings easily at runtime.
138 * So define own function for translating CR_* errors directly to strings.
141 cr_strerror(CONFIGRET cr_error_id)
143 static char unknown_error[sizeof("Unknown CR error XXXXXXXXXX")];
144 static const char *cr_errors[] = {
145 "The operation completed successfully",
147 "Not enough memory is available to process this command",
148 "A required pointer parameter is invalid",
149 "The ulFlags parameter specified is invalid for this operation",
150 "The device instance handle parameter is not valid",
151 "The supplied resource descriptor parameter is invalid",
152 "The supplied logical configuration parameter is invalid",
153 "CR_INVALID_ARBITRATOR",
154 "CR_INVALID_NODELIST",
155 "CR_DEVNODE_HAS_REQS/CR_DEVINST_HAS_REQS",
156 "The RESOURCEID parameter does not contain a valid RESOURCEID",
157 "CR_DLVXD_NOT_FOUND",
158 "The specified device instance handle does not correspond to a present device",
159 "There are no more logical configurations available",
160 "There are no more resource descriptions available",
161 "This device instance already exists",
162 "The supplied range list parameter is invalid",
164 "A general internal error occurred",
165 "CR_NO_SUCH_LOGICAL_DEV",
166 "The device is disabled for this configuration",
168 "A service or application refused to allow removal of this device",
170 "CR_INVALID_LOAD_TYPE",
171 "An output parameter was too small to hold all the data available",
173 "CR_NO_REGISTRY_HANDLE",
174 "A required entry in the registry is missing or an attempt to write to the registry failed",
175 "The specified Device ID is not a valid Device ID",
176 "One or more parameters were invalid",
178 "CR_DEVLOADER_NOT_READY",
180 "There are no more hardware profiles available",
181 "CR_DEVICE_NOT_THERE",
182 "The specified value does not exist in the registry",
184 "The specified priority is invalid for this operation",
185 "This device cannot be disabled",
191 "The specified key does not exist in the registry",
192 "The specified machine name does not meet the UNC naming conventions",
193 "A general remote communication error occurred",
194 "The machine selected for remote communication is not available at this time",
195 "The Plug and Play service or another required service is not available",
197 "This routine is not implemented in this version of the operating system",
198 "The specified property type is invalid for this operation",
199 "Device interface is active",
200 "No such device interface",
201 "Invalid reference string",
202 "Invalid conflict list",
204 "Invalid structure size"
206 if (cr_error_id <= 0 || cr_error_id >= sizeof(cr_errors)/sizeof(*cr_errors))
208 sprintf(unknown_error, "Unknown CR error %lu", cr_error_id);
209 return unknown_error;
211 return cr_errors[cr_error_id];
215 win32_strerror(DWORD win32_error_id)
218 * Use static buffer which is large enough.
219 * Hopefully no Win32 API error message string is longer than 4 kB.
221 static char buffer[4096];
224 len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, win32_error_id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, sizeof(buffer), NULL);
226 /* FormatMessage() automatically appends ".\r\n" to the error message. */
227 if (len && buffer[len-1] == '\n')
228 buffer[--len] = '\0';
229 if (len && buffer[len-1] == '\r')
230 buffer[--len] = '\0';
231 if (len && buffer[len-1] == '.')
232 buffer[--len] = '\0';
235 sprintf(buffer, "Unknown Win32 error %lu", win32_error_id);
241 fmt_validate(const char *s, int len, const char *fmt)
245 for (i = 0; i < len; i++)
246 if (!fmt[i] || (fmt[i] == '#' ? !isxdigit(s[i]) : fmt[i] != s[i]))
253 seq_xdigit_validate(const char *s, int mult, int min)
258 if (len < min*mult || len % mult)
261 for (i = 0; i < len; i++)
269 is_non_nt_system(void)
271 OSVERSIONINFOA version;
272 version.dwOSVersionInfoSize = sizeof(version);
273 return GetVersionExA(&version) && version.dwPlatformId < VER_PLATFORM_WIN32_NT;
277 is_32bit_on_win8_64bit_system(void)
282 BOOL (WINAPI *MyIsWow64Process)(HANDLE, PBOOL);
283 OSVERSIONINFOA version;
287 /* Check for Windows 8 (NT 6.2). */
288 version.dwOSVersionInfoSize = sizeof(version);
289 if (!GetVersionExA(&version) ||
290 version.dwPlatformId != VER_PLATFORM_WIN32_NT ||
291 version.dwMajorVersion < 6 ||
292 (version.dwMajorVersion == 6 && version.dwMinorVersion < 2))
296 * Check for 64-bit system via IsWow64Process() function exported
297 * from 32-bit kernel32.dll library available on the 64-bit systems.
298 * Resolve pointer to this function at runtime as this code path is
299 * primary running on 32-bit systems where are not available 64-bit
303 kernel32 = GetModuleHandleA("kernel32.dll");
307 MyIsWow64Process = (void *)GetProcAddress(kernel32, "IsWow64Process");
308 if (!MyIsWow64Process)
311 if (!MyIsWow64Process(GetCurrentProcess(), &is_wow64))
319 get_device_service_name(struct pci_access *a, DEVINST devinst, DEVINSTID_A devinst_id, BOOL *supported)
321 ULONG reg_type, reg_size, reg_len;
326 * All data are stored as 7-bit ASCII strings in system but service name is
327 * exception. It can contain UNICODE. Moreover it is passed to other Win32 API
328 * functions and therefore it cannot be converted to 8-bit ANSI string without
329 * data loss. So use wide function CM_Get_DevNode_Registry_PropertyW() in this
330 * case and deal with all wchar_t problems...
334 cr = CM_Get_DevNode_Registry_PropertyW(devinst, CM_DRP_SERVICE, ®_type, NULL, ®_size, 0);
335 if (cr == CR_CALL_NOT_IMPLEMENTED)
340 else if (cr == CR_NO_SUCH_VALUE)
345 else if (cr != CR_SUCCESS &&
346 cr != CR_BUFFER_SMALL)
348 a->warning("Cannot retrieve service name for PCI device %s: %s.", devinst_id, cr_strerror(cr));
352 else if (reg_type != REG_SZ)
354 a->warning("Cannot retrieve service name for PCI device %s: Service name is stored as unknown type 0x%lx.", devinst_id, reg_type);
361 * Returned size is on older Windows versions without nul-term char.
362 * So explicitly increase size and fill nul-term byte.
364 reg_size += sizeof(service_name[0]);
365 service_name = pci_malloc(a, reg_size);
367 cr = CM_Get_DevNode_Registry_PropertyW(devinst, CM_DRP_SERVICE, ®_type, service_name, ®_len, 0);
368 service_name[reg_size/sizeof(service_name[0]) - 1] = 0;
369 if (reg_len > reg_size)
371 pci_mfree(service_name);
375 else if (cr != CR_SUCCESS)
377 a->warning("Cannot retrieve service name for PCI device %s: %s.", devinst_id, cr_strerror(cr));
378 pci_mfree(service_name);
382 else if (reg_type != REG_SZ)
384 a->warning("Cannot retrieve service name for PCI device %s: Service name is stored as unknown type 0x%lx.", devinst_id, reg_type);
385 pci_mfree(service_name);
395 get_driver_path_for_service(struct pci_access *a, LPCWSTR service_name, SC_HANDLE manager)
397 UINT (WINAPI *get_system_root_path)(LPWSTR buffer, UINT size) = NULL;
398 DWORD service_config_size, service_config_len;
399 LPQUERY_SERVICE_CONFIGW service_config = NULL;
400 LPWSTR service_image_path = NULL;
401 SERVICE_STATUS service_status;
402 SC_HANDLE service = NULL;
403 char *driver_path = NULL;
409 service = OpenServiceW(manager, service_name, SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS);
412 error = GetLastError();
413 if (error != ERROR_SERVICE_DOES_NOT_EXIST)
414 a->warning("Cannot open service %ls with query rights: %s.", service_name, win32_strerror(error));
418 if (!QueryServiceStatus(service, &service_status))
420 error = GetLastError();
421 a->warning("Cannot query status of service %ls: %s.", service_name, win32_strerror(error));
425 if (service_status.dwCurrentState == SERVICE_STOPPED)
428 if (service_status.dwServiceType != SERVICE_KERNEL_DRIVER)
431 if (!QueryServiceConfigW(service, NULL, 0, &service_config_size))
433 error = GetLastError();
434 if (error != ERROR_INSUFFICIENT_BUFFER)
436 a->warning("Cannot query config of service %ls: %s.", service_name, win32_strerror(error));
441 retry_service_config:
442 service_config = pci_malloc(a, service_config_size);
443 if (!QueryServiceConfigW(service, service_config, service_config_size, &service_config_len))
445 error = GetLastError();
446 if (error == ERROR_INSUFFICIENT_BUFFER)
448 pci_mfree(service_config);
449 service_config_size = service_config_len;
450 goto retry_service_config;
452 a->warning("Cannot query config of service %ls: %s.", service_name, win32_strerror(error));
456 if (service_config->dwServiceType != SERVICE_KERNEL_DRIVER)
460 * Despite QueryServiceConfig() is Win32 API, it returns lpBinaryPathName
461 * (ImagePath registry) in NT format. Unfortunately there is no Win32
462 * function for converting NT paths to Win32 paths. So do it manually and
463 * convert this NT format to human-readable Win32 path format.
467 * Old Windows versions return path to NT SystemRoot namespace via
468 * GetWindowsDirectoryW() function. New Windows versions via
469 * GetSystemWindowsDirectoryW(). GetSystemWindowsDirectoryW() is not
470 * provided in old Windows versions, so use GetProcAddress() for
471 * compatibility with all Windows versions.
473 kernel32 = GetModuleHandleW(L"kernel32.dll");
475 get_system_root_path = (void *)GetProcAddress(kernel32, "GetSystemWindowsDirectoryW");
476 if (!get_system_root_path)
477 get_system_root_path = &GetWindowsDirectoryW;
479 systemroot_len = get_system_root_path(NULL, 0);
481 if (!service_config->lpBinaryPathName || !service_config->lpBinaryPathName[0])
483 /* No ImagePath is specified, NT kernel assumes implicit kernel driver path by service name. */
484 service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + sizeof("\\System32\\drivers\\")-1 + wcslen(service_name) + sizeof(".sys")-1 + 1));
485 systemroot_len = get_system_root_path(service_image_path, systemroot_len+1);
486 if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
487 service_image_path[systemroot_len++] = L'\\';
488 wcscpy(service_image_path + systemroot_len, L"System32\\drivers\\");
489 wcscpy(service_image_path + systemroot_len + sizeof("System32\\drivers\\")-1, service_name);
490 wcscpy(service_image_path + systemroot_len + sizeof("System32\\drivers\\")-1 + wcslen(service_name), L".sys");
492 else if (wcsncmp(service_config->lpBinaryPathName, L"\\SystemRoot\\", sizeof("\\SystemRoot\\")-1) == 0)
494 /* ImagePath is in NT SystemRoot namespace, convert to Win32 path via GetSystemWindowsDirectoryW()/GetWindowsDirectoryW(). */
495 service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + wcslen(service_config->lpBinaryPathName) - (sizeof("\\SystemRoot")-1)));
496 systemroot_len = get_system_root_path(service_image_path, systemroot_len+1);
497 if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
498 service_image_path[systemroot_len++] = L'\\';
499 wcscpy(service_image_path + systemroot_len, service_config->lpBinaryPathName + sizeof("\\SystemRoot\\")-1);
501 else if (wcsncmp(service_config->lpBinaryPathName, L"\\??\\UNC\\", sizeof("\\??\\UNC\\")-1) == 0)
503 /* ImagePath is in NT UNC namespace, convert to Win32 UNC path via "\\\\" prefix. */
504 service_image_path = pci_malloc(a, sizeof(WCHAR) * (sizeof("\\\\") + wcslen(service_config->lpBinaryPathName) - (sizeof("\\??\\UNC\\")-1)));
505 wcscpy(service_image_path, L"\\\\");
506 wcscpy(service_image_path + sizeof("\\\\")-1, service_config->lpBinaryPathName + sizeof("\\??\\UNC\\")-1);
508 else if (wcsncmp(service_config->lpBinaryPathName, L"\\??\\", sizeof("\\??\\")-1) == 0)
510 /* ImagePath is in NT Global?? namespace, root of the Win32 file namespace, so just remove "\\??\\" prefix to get Win32 path. */
511 service_image_path = pci_malloc(a, sizeof(WCHAR) * (wcslen(service_config->lpBinaryPathName) - (sizeof("\\??\\")-1)));
512 wcscpy(service_image_path, service_config->lpBinaryPathName + sizeof("\\??\\")-1);
514 else if (service_config->lpBinaryPathName[0] != L'\\')
516 /* ImagePath is relative to the NT SystemRoot namespace, convert to Win32 path via GetSystemWindowsDirectoryW()/GetWindowsDirectoryW(). */
517 service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + sizeof("\\") + wcslen(service_config->lpBinaryPathName)));
518 systemroot_len = get_system_root_path(service_image_path, systemroot_len+1);
519 if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
520 service_image_path[systemroot_len++] = L'\\';
521 wcscpy(service_image_path + systemroot_len, service_config->lpBinaryPathName);
525 /* ImagePath is in some unhandled NT namespace, copy it as is. It cannot be used in Win32 API but libpci user can be still interested in it. */
526 service_image_path = pci_malloc(a, sizeof(WCHAR) * wcslen(service_config->lpBinaryPathName));
527 wcscpy(service_image_path, service_config->lpBinaryPathName);
530 /* Calculate len of buffer needed for conversion from LPWSTR to char*. */
531 driver_path_len = WideCharToMultiByte(CP_ACP, 0, service_image_path, -1, NULL, 0, NULL, NULL);
532 if (driver_path_len <= 0)
534 error = GetLastError();
535 a->warning("Cannot convert kernel driver path from wide string to 8-bit string: %s.", win32_strerror(error));
539 driver_path = pci_malloc(a, driver_path_len);
540 driver_path_len = WideCharToMultiByte(CP_ACP, 0, service_image_path, -1, driver_path, driver_path_len, NULL, NULL);
541 if (driver_path_len <= 0)
543 error = GetLastError();
544 a->warning("Cannot convert kernel driver path from wide string to 8-bit string: %s.", win32_strerror(error));
545 pci_mfree(driver_path);
551 if (service_image_path)
552 pci_mfree(service_image_path);
554 pci_mfree(service_config);
556 CloseServiceHandle(service);
561 get_device_driver_devreg(struct pci_access *a, DEVINST devinst, DEVINSTID_A devinst_id)
566 cr = CM_Open_DevNode_Key(devinst, KEY_READ, 0, RegDisposition_OpenExisting, &key, CM_REGISTRY_SOFTWARE);
567 if (cr != CR_SUCCESS)
569 if (cr != CR_NO_SUCH_VALUE)
570 a->warning("Cannot retrieve driver key for device %s: %s.", devinst_id, cr_strerror(cr));
578 read_reg_key_string_value(struct pci_access *a, HKEY key, const char *name, DWORD *unkn_reg_type)
580 DWORD reg_type, reg_size, reg_len;
585 error = RegQueryValueExA(key, name, NULL, ®_type, NULL, ®_size);
586 if (error != ERROR_SUCCESS &&
587 error != ERROR_MORE_DATA)
592 else if (reg_type != REG_SZ)
595 *unkn_reg_type = reg_type;
600 value = pci_malloc(a, reg_size + 1);
602 error = RegQueryValueExA(key, name, NULL, ®_type, (PBYTE)value, ®_len);
603 if (error != ERROR_SUCCESS)
606 if (error == ERROR_MORE_DATA)
614 else if (reg_type != REG_SZ)
618 *unkn_reg_type = reg_type;
621 value[reg_len] = '\0';
627 driver_cmp(const char *driver, const char *match)
629 int len = strlen(driver);
630 if (driver[0] == '*')
632 if (len >= 4 && strcasecmp(driver + len - 4, ".vxd") == 0)
634 return strncasecmp(driver, match, len);
638 get_driver_path_for_regkey(struct pci_access *a, DEVINSTID_A devinst_id, HKEY key)
640 char *driver_list, *driver, *driver_next;
641 char *subdriver, *subname;
652 driver_list = read_reg_key_string_value(a, key, "DevLoader", &unkn_reg_type);
655 error = GetLastError();
657 a->warning("Cannot read driver DevLoader key for PCI device %s: DevLoader key is stored as unknown type 0x%lx.", devinst_id, unkn_reg_type);
658 else if (error != ERROR_FILE_NOT_FOUND)
659 a->warning("Cannot read driver DevLoader key for PCI device %s: %s.", devinst_id, win32_strerror(error));
664 driver = driver_list;
667 driver_next = strchr(driver, ',');
669 *(driver_next++) = '\0';
671 if (driver_cmp(driver, "ios") == 0 ||
672 driver_cmp(driver, "vcomm") == 0)
673 subname = "PortDriver";
674 else if (driver_cmp(driver, "ntkern") == 0)
675 subname = "NTMPDriver";
676 else if (driver_cmp(driver, "ndis") == 0)
677 subname = "DeviceVxDs";
678 else if (driver_cmp(driver, "vdd") == 0)
684 if (subname && strcmp(subname, "minivdd") == 0)
686 error = RegOpenKeyA(key, "Default", &subkey);
687 if (error != ERROR_SUCCESS)
689 a->warning("Cannot open driver subkey Default for PCI device %s: %s.", devinst_id, win32_strerror(error));
700 subdriver = read_reg_key_string_value(a, subkey, subname, &unkn_reg_type);
703 error = GetLastError();
705 a->warning("Cannot read driver %s key for PCI device %s: DevLoader key is stored as unknown type 0x%lx.", subname, devinst_id, unkn_reg_type);
706 else if (error != ERROR_FILE_NOT_FOUND)
707 a->warning("Cannot read driver %s key for PCI device %s: %s.", subname, devinst_id, win32_strerror(error));
708 else if (strcmp(subname, "minivdd") == 0)
713 else if (strcmp(subname, "drv") == 0)
725 char *endptr = strchr(subdriver, ',');
732 driver = driver_next;
735 if (subdriver && subdriver[0])
736 driver_ptr = subdriver;
742 if (driver_ptr && driver_ptr[0] == '*')
753 len = driver_ptr ? strlen(driver_ptr) : 0;
754 noext = driver_ptr && (len < 4 || driver_ptr[len-4] != '.');
760 if (tolower(driver_ptr[0]) >= 'a' && tolower(driver_ptr[0]) <= 'z' && driver_ptr[1] == ':')
762 /* Driver is already with absolute path. */
763 driver_path = pci_strdup(a, driver_ptr);
765 else if (driver_cmp(driver, "ntkern") == 0 && subdriver)
767 /* Driver is relative to system32\drivers\ directory which is relative to windows directory. */
768 systemdir_len = GetWindowsDirectoryA(NULL, 0);
769 driver_path = pci_malloc(a, systemdir_len + 1 + sizeof("system32\\drivers\\")-1 + strlen(driver_ptr) + 4 + 1);
770 systemdir_len = GetWindowsDirectoryA(driver_path, systemdir_len + 1);
771 if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
772 driver_path[systemdir_len++] = '\\';
773 sprintf(driver_path + systemdir_len, "system32\\drivers\\%s%s", driver_ptr, noext ? ".sys" : "");
777 /* Driver is packed in vmm32.vxd which is stored in system directory. */
778 systemdir_len = GetSystemDirectoryA(NULL, 0);
779 driver_path = pci_malloc(a, systemdir_len + 1 + sizeof("vmm32.vxd ()")-1 + strlen(driver_ptr) + 4 + 1);
780 systemdir_len = GetSystemDirectoryA(driver_path, systemdir_len + 1);
781 if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
782 driver_path[systemdir_len++] = '\\';
783 sprintf(driver_path + systemdir_len, "vmm32.vxd (%s%s)", driver_ptr, noext ? ".vxd" : "");
787 /* Otherwise driver is relative to system directory. */
788 systemdir_len = GetSystemDirectoryA(NULL, 0);
789 driver_path = pci_malloc(a, systemdir_len + 1 + strlen(driver_ptr) + 4 + 1);
790 systemdir_len = GetSystemDirectoryA(driver_path, systemdir_len + 1);
791 if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
792 driver_path[systemdir_len++] = '\\';
793 sprintf(driver_path + systemdir_len, "%s%s", driver_ptr, noext ? ".vxd" : "");
798 pci_mfree(subdriver);
799 pci_mfree(driver_list);
804 get_device_driver_path(struct pci_dev *d, SC_HANDLE manager, BOOL manager_supported)
806 struct pci_access *a = d->access;
807 BOOL service_supported = TRUE;
808 DEVINSTID_A devinst_id = NULL;
809 LPWSTR service_name = NULL;
810 ULONG devinst_id_len = 0;
811 char *driver_path = NULL;
812 DEVINST devinst = (DEVINST)d->aux;
817 if (CM_Get_DevNode_Status(&status, &problem, devinst, 0) != CR_SUCCESS || !(status & DN_DRIVER_LOADED))
820 if (CM_Get_Device_ID_Size(&devinst_id_len, devinst, 0) == CR_SUCCESS)
822 devinst_id = pci_malloc(a, devinst_id_len + 1);
823 if (CM_Get_Device_IDA(devinst, devinst_id, devinst_id_len + 1, 0) != CR_SUCCESS)
825 pci_mfree(devinst_id);
826 devinst_id = pci_strdup(a, "UNKNOWN");
830 devinst_id = pci_strdup(a, "UNKNOWN");
832 service_name = get_device_service_name(d->access, devinst, devinst_id, &service_supported);
833 if ((!service_name || !manager) && service_supported && manager_supported)
835 else if (service_name && manager)
837 driver_path = get_driver_path_for_service(d->access, service_name, manager);
841 key = get_device_driver_devreg(d->access, devinst, devinst_id);
844 driver_path = get_driver_path_for_regkey(d->access, devinst_id, key);
852 pci_mfree(service_name);
853 pci_mfree(devinst_id);
858 fill_drivers(struct pci_access *a)
860 BOOL manager_supported;
866 /* ERROR_CALL_NOT_IMPLEMENTED is returned on systems without Service Manager support. */
867 manager_supported = TRUE;
868 manager = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
871 error = GetLastError();
872 if (error != ERROR_CALL_NOT_IMPLEMENTED)
873 a->warning("Cannot open Service Manager with connect right: %s.", win32_strerror(error));
875 manager_supported = FALSE;
878 for (d = a->devices; d; d = d->next)
880 driver = get_device_driver_path(d, manager, manager_supported);
883 pci_set_property(d, PCI_FILL_DRIVER, driver);
886 d->known_fields |= PCI_FILL_DRIVER;
890 CloseServiceHandle(manager);
894 fill_resources(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
896 struct pci_access *a = d->access;
904 RES_DES prev_res_des;
913 int last_shared_irq = -1;
915 cr = CM_Get_DevNode_Status(&status, &problem, devinst, 0);
916 if (cr != CR_SUCCESS)
918 a->warning("Cannot retrieve status of PCI device %s: %s.", devinst_id, cr_strerror(cr));
922 cr = CR_NO_MORE_LOG_CONF;
925 * If the device is running then retrieve allocated configuration by PnP
926 * manager which is currently in use by a device.
928 if (!(status & DN_HAS_PROBLEM))
929 cr = CM_Get_First_Log_Conf(&config, devinst, ALLOC_LOG_CONF);
932 * If the device is not running or it does not have allocated configuration by
933 * PnP manager then retrieve forced configuration which prevents PnP manager
934 * from assigning resources.
936 if (cr == CR_NO_MORE_LOG_CONF)
937 cr = CM_Get_First_Log_Conf(&config, devinst, FORCED_LOG_CONF);
940 * If the device does not have neither allocated configuration by PnP manager
941 * nor forced configuration and it is not disabled in the BIOS then retrieve
942 * boot configuration supplied by the BIOS.
944 if (cr == CR_NO_MORE_LOG_CONF &&
945 (!(status & DN_HAS_PROBLEM) || problem != CM_PROB_HARDWARE_DISABLED))
946 cr = CM_Get_First_Log_Conf(&config, devinst, BOOT_LOG_CONF);
948 if (cr != CR_SUCCESS)
951 * Note: Starting with Windows 8, CM_Get_First_Log_Conf returns
952 * CR_CALL_NOT_IMPLEMENTED when used in a Wow64 scenario.
953 * To request information about the hardware resources on a local machine
954 * it is necessary implement an architecture-native version of the
955 * application using the hardware resource APIs. For example: An AMD64
956 * application for AMD64 systems.
958 if (cr == CR_CALL_NOT_IMPLEMENTED && is_32bit_on_win8_64bit_system())
960 static BOOL warn_once = FALSE;
964 a->warning("Cannot retrieve resources of PCI devices from 32-bit application on 64-bit system.");
967 else if (cr != CR_NO_MORE_LOG_CONF)
968 a->warning("Cannot retrieve resources of PCI device %s: %s.", devinst_id, cr_strerror(cr));
973 non_nt_system = is_non_nt_system();
980 ULONG child_name_len;
984 if (CM_Get_Child(&child, devinst, 0) != CR_SUCCESS)
986 else if (CM_Get_Device_ID_Size(&child_name_len, child, 0) != CR_SUCCESS)
991 child_name = pci_malloc(a, child_name_len);
992 if (CM_Get_Device_IDA(child, child_name, child_name_len, 0) != CR_SUCCESS)
994 else if (strncmp(child_name, "PCI\\", 4) != 0)
998 pci_mfree(child_name);
1001 if (has_child || d->device_class == PCI_CLASS_BRIDGE_PCI || d->device_class == PCI_CLASS_BRIDGE_CARDBUS)
1010 prev_res_des = (RES_DES)config;
1011 while ((cr = CM_Get_Next_Res_Des(&res_des, prev_res_des, ResType_All, &res_id, 0)) == CR_SUCCESS)
1013 pciaddr_t start, end, size, flags;
1014 ULONG res_des_data_size;
1017 if (prev_res_des != config)
1018 CM_Free_Res_Des_Handle(prev_res_des);
1020 prev_res_des = res_des;
1022 cr = CM_Get_Res_Des_Data_Size(&res_des_data_size, res_des, 0);
1023 if (cr != CR_SUCCESS)
1025 a->warning("Cannot retrieve resource data of PCI device %s: %s.", devinst_id, cr_strerror(cr));
1029 if (!res_des_data_size)
1031 a->warning("Cannot retrieve resource data of PCI device %s: %s.", devinst_id, "Empty data");
1035 res_des_data = pci_malloc(a, res_des_data_size);
1036 cr = CM_Get_Res_Des_Data(res_des, res_des_data, res_des_data_size, 0);
1037 if (cr != CR_SUCCESS)
1039 a->warning("Cannot retrieve resource data of PCI device %s: %s.", devinst_id, cr_strerror(cr));
1040 pci_mfree(res_des_data);
1045 * There can be more resources with the same id. In this case we are
1046 * interested in the last one in the list as at the beginning of the list
1047 * can be some virtual resources (which are not set in PCI config space).
1050 if (res_id == ResType_IO)
1052 PIO_RESOURCE io_data = (PIO_RESOURCE)res_des_data;
1054 start = io_data->IO_Header.IOD_Alloc_Base;
1055 end = io_data->IO_Header.IOD_Alloc_End;
1056 size = (end > start) ? (end - start + 1) : 0;
1057 flags = PCI_IORESOURCE_IO;
1060 * If neither 10-bit, 12-bit, nor 16-bit support is presented then
1061 * expects that this is 32-bit I/O resource. If resource does not fit
1062 * into 16-bit space then it must be 32-bit. If PCI I/O resource is
1063 * not 32-bit then it is 16-bit.
1065 if (end <= 0xffff && (io_data->IO_Header.IOD_DesFlags & (fIOD_10_BIT_DECODE|fIOD_12_BIT_DECODE|fIOD_16_BIT_DECODE)))
1066 flags |= PCI_IORESOURCE_IO_16BIT_ADDR;
1069 * 16/32-bit non-NT systems do not support these two flags.
1070 * Most NT-based Windows versions support only the fIOD_WINDOW_DECODE
1071 * flag and put all BAR resources before window resources in this
1072 * resource list. So use this fIOD_WINDOW_DECODE flag as separator
1073 * between IO/MEM windows and IO/MEM BARs of PCI Bridges.
1075 if (io_data->IO_Header.IOD_DesFlags & fIOD_WINDOW_DECODE)
1077 else if (io_data->IO_Header.IOD_DesFlags & fIOD_PORT_BAR)
1080 if (is_bar_res && bar_res_count < 6)
1082 d->flags[bar_res_count] = flags;
1083 d->base_addr[bar_res_count] = start;
1084 d->size[bar_res_count] = size;
1087 else if (!is_bar_res)
1089 d->bridge_flags[0] = flags;
1090 d->bridge_base_addr[0] = start;
1091 d->bridge_size[0] = size;
1092 d->known_fields |= PCI_FILL_BRIDGE_BASES;
1095 else if (res_id == ResType_Mem)
1097 PMEM_RESOURCE mem_data = (PMEM_RESOURCE)res_des_data;
1099 start = mem_data->MEM_Header.MD_Alloc_Base;
1100 end = mem_data->MEM_Header.MD_Alloc_End;
1101 size = (end > start) ? (end - start + 1) : 0;
1102 flags = PCI_IORESOURCE_MEM;
1105 * If fMD_PrefetchAllowed flag is set then this is
1106 * PCI Prefetchable Memory resource.
1108 if ((mem_data->MEM_Header.MD_Flags & mMD_Prefetchable) == fMD_PrefetchAllowed)
1109 flags |= PCI_IORESOURCE_PREFETCH;
1111 /* If resource does not fit into 32-bit space then it must be 64-bit. */
1112 if (is_bar_res && end > 0xffffffff)
1113 flags |= PCI_IORESOURCE_MEM_64;
1116 * These two flags (fMD_WINDOW_DECODE and fMD_MEMORY_BAR) are
1117 * unsupported on most Windows versions, so distinguish between
1118 * window and BAR based on previous resource type.
1120 if (mem_data->MEM_Header.MD_Flags & fMD_WINDOW_DECODE)
1122 else if (mem_data->MEM_Header.MD_Flags & fMD_MEMORY_BAR)
1125 /* 64-bit BAR resource must be at even position. */
1126 if (is_bar_res && (flags & PCI_IORESOURCE_MEM_64) && bar_res_count % 2)
1129 if (is_bar_res && bar_res_count < 6)
1131 d->flags[bar_res_count] = flags;
1132 d->base_addr[bar_res_count] = start;
1133 d->size[bar_res_count] = size;
1135 /* 64-bit BAR resource occupies two slots. */
1136 if (flags & PCI_IORESOURCE_MEM_64)
1139 else if (!is_bar_res && !(flags & PCI_IORESOURCE_PREFETCH))
1141 d->bridge_flags[1] = flags;
1142 d->bridge_base_addr[1] = start;
1143 d->bridge_size[1] = size;
1144 d->known_fields |= PCI_FILL_BRIDGE_BASES;
1146 else if (!is_bar_res && (flags & PCI_IORESOURCE_PREFETCH))
1148 d->bridge_flags[2] = flags;
1149 d->bridge_base_addr[2] = start;
1150 d->bridge_size[2] = size;
1151 d->known_fields |= PCI_FILL_BRIDGE_BASES;
1154 else if (res_id == ResType_IRQ)
1156 PIRQ_RESOURCE irq_data = (PIRQ_RESOURCE)res_des_data;
1159 * libpci's d->irq should be set to the non-MSI PCI IRQ and therefore
1160 * it should be level IRQ which may be shared with other PCI devices
1161 * and drivers in the system. As always we want to retrieve the last
1162 * IRQ number from the resource list.
1164 * On 16/32-bit non-NT systems is fIRQD_Level set to 2 but on NT
1165 * systems to 0. Moreover it looks like that different PCI drivers
1166 * on both NT and non-NT systems set bits 0 and 1 to wrong values
1167 * and so reported value in this list may be incorrect.
1169 * Therefore take the last level-shared IRQ number from the resource
1170 * list and if there is none of this type then take the last IRQ
1171 * number from the list.
1173 last_irq = irq_data->IRQ_Header.IRQD_Alloc_Num;
1174 if ((irq_data->IRQ_Header.IRQD_Flags & (mIRQD_Share|mIRQD_Edge_Level)) == (fIRQD_Share|fIRQD_Level))
1175 last_shared_irq = irq_data->IRQ_Header.IRQD_Alloc_Num;
1178 * IRQ resource on 16/32-bit non-NT systems is separator between
1179 * IO/MEM windows and IO/MEM BARs of PCI Bridges. After the IRQ
1180 * resource are IO/MEM BAR resources.
1182 if (!is_bar_res && non_nt_system)
1186 pci_mfree(res_des_data);
1188 if (cr != CR_NO_MORE_RES_DES)
1189 a->warning("Cannot retrieve resources of PCI device %s: %s.", devinst_id, cr_strerror(cr));
1191 if (prev_res_des != config)
1192 CM_Free_Res_Des_Handle(prev_res_des);
1194 CM_Free_Log_Conf_Handle(config);
1196 /* Set the last IRQ from the resource list to pci_dev. */
1197 if (last_shared_irq >= 0)
1198 d->irq = last_shared_irq;
1199 else if (last_irq >= 0)
1201 if (last_shared_irq >= 0 || last_irq >= 0)
1202 d->known_fields |= PCI_FILL_IRQ;
1204 if (bar_res_count > 0)
1205 d->known_fields |= PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS;
1209 get_device_location(struct pci_access *a, DEVINST devinst, DEVINSTID_A devinst_id, unsigned int *domain, unsigned int *bus, unsigned int *dev, unsigned int *func)
1211 ULONG reg_type, reg_len;
1213 BOOL have_bus, have_devfunc;
1214 DWORD drp_bus_num, drp_address;
1218 have_devfunc = FALSE;
1221 * DRP_BUSNUMBER consists of PCI domain number in high 24 bits
1222 * and PCI bus number in low 8 bits.
1224 reg_len = sizeof(drp_bus_num);
1225 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_BUSNUMBER, ®_type, &drp_bus_num, ®_len, 0);
1226 if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_bus_num))
1228 *domain = drp_bus_num >> 8;
1229 *bus = drp_bus_num & 0xff;
1234 * DRP_ADDRESS consists of PCI device number in high 16 bits
1235 * and PCI function number in low 16 bits.
1237 reg_len = sizeof(drp_address);
1238 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_ADDRESS, ®_type, &drp_address, ®_len, 0);
1239 if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_address))
1241 *dev = drp_address >> 16;
1242 *func = drp_address & 0xffff;
1243 have_devfunc = TRUE;
1247 * Device Instance Id for PCI devices is of format:
1248 * "<enumerator>\\<device_id>\\<instance_id>"
1250 * "<enumerator>" is "PCI"
1251 * "<device_id>" is "VEN_####&DEV_####&SUBSYS_########&REV_##"
1252 * and "<instance_id>" for PCI devices is at least in one of following format:
1253 * "BUS_##&DEV_##&FUNC_##"
1254 * "##.." (sequence of devfn hex bytes, where bytes represents tree path to the root)
1255 * "#..&#..&#..&#.." (four hex numbers separated by "&"; meaning is unknown yet)
1257 * First two formats are used only on systems without support for multiple
1258 * domains. The second format uses intel-conf encoding of device and function
1259 * number: Low 3 bits is function number and high 5 bits is device number.
1260 * Bus number is not really encoded in second format!
1262 * The third format is used on systems with support for multiple domains but
1263 * format is variable length and currently its meaning is unknown. Apparently
1264 * it looks like that DRP_BUSNUMBER and DRP_ADDRESS registry properties are
1265 * supported on these systems.
1267 * If DRP_BUSNUMBER or DRP_ADDRESS failed then try to parse PCI bus, device
1268 * and function numbers from Instance Id part.
1270 if (!have_bus || !have_devfunc)
1272 const char *device_id0 = strchr(devinst_id, '\\');
1273 const char *instance_id0 = device_id0 ? strchr(device_id0 + 1, '\\') : NULL;
1274 const char *instance_id = instance_id0 ? instance_id0 + 1 : NULL;
1279 if (fmt_validate(instance_id, strlen(instance_id), "BUS_##&DEV_##&FUNC_##") &&
1280 sscanf(instance_id, "BUS_%x&DEV_%x&FUNC_%x", bus, dev, func) == 3)
1283 have_devfunc = TRUE;
1285 else if (seq_xdigit_validate(instance_id, 2, 2) &&
1286 sscanf(instance_id, "%2x", &devfn) == 1)
1289 *func = devfn & 0x7;
1290 have_devfunc = TRUE;
1296 * Virtual IRQ holder devices do not have assigned any bus/dev/func number and
1297 * have "IRQHOLDER" in their Device Id part. So skip them.
1299 if (!have_bus && !have_devfunc && strncmp(devinst_id, "PCI\\IRQHOLDER\\", 14) == 0)
1303 * When some numbers cannot be retrieved via cfgmgr32 then set them to zeros
1304 * to have structure initialized. It makes sense to report via libpci also
1305 * such "incomplete" device as cfgmgr32 can provide additional information
1306 * like device/vendor ids or assigned resources.
1308 if (!have_bus && !have_devfunc)
1310 *bus = *dev = *func = 0;
1311 a->warning("Cannot retrieve bus, device and function numbers for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1316 a->warning("Cannot retrieve bus number for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1318 else if (!have_devfunc)
1321 a->warning("Cannot retrieve device and function numbers for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1328 fill_data_from_string(struct pci_dev *d, const char *str)
1330 BOOL have_device_id;
1331 BOOL have_vendor_id;
1334 const char *endptr, *endptr2;
1338 have_device_id = have_vendor_id = (d->known_fields & PCI_FILL_IDENT);
1339 have_prog_if = have_rev_id = (d->known_fields & PCI_FILL_CLASS_EXT);
1343 endptr = strchr(str, '&');
1344 endptr2 = strchr(str, '\\');
1345 if (endptr2 && (!endptr || endptr > endptr2))
1347 len = endptr ? endptr-str : (int)strlen(str);
1349 if (!have_vendor_id &&
1350 fmt_validate(str, len, "VEN_####") &&
1351 sscanf(str, "VEN_%x", &hex) == 1)
1354 have_vendor_id = TRUE;
1356 else if (!have_device_id &&
1357 fmt_validate(str, len, "DEV_####") &&
1358 sscanf(str, "DEV_%x", &hex) == 1)
1361 have_device_id = TRUE;
1363 else if (!(d->known_fields & PCI_FILL_SUBSYS) &&
1364 fmt_validate(str, len, "SUBSYS_########") &&
1365 sscanf(str, "SUBSYS_%x", &hex) == 1)
1367 d->subsys_vendor_id = hex & 0xffff;
1368 d->subsys_id = hex >> 16;
1369 d->known_fields |= PCI_FILL_SUBSYS;
1371 else if (!have_rev_id &&
1372 fmt_validate(str, len, "REV_##") &&
1373 sscanf(str, "REV_%x", &hex) == 1)
1378 else if (!((d->known_fields & PCI_FILL_CLASS) && have_prog_if) &&
1379 (fmt_validate(str, len, "CC_####") || fmt_validate(str, len, "CC_######")) &&
1380 sscanf(str, "CC_%x", &hex) == 1)
1386 d->prog_if = hex & 0xff;
1387 have_prog_if = TRUE;
1391 if (!(d->known_fields & PCI_FILL_CLASS))
1393 d->device_class = hex;
1394 d->known_fields |= PCI_FILL_CLASS;
1398 if (!endptr || endptr == endptr2)
1404 if ((have_device_id || d->device_id) && (have_vendor_id || d->vendor_id))
1405 d->known_fields |= PCI_FILL_IDENT;
1407 if ((have_prog_if || d->prog_if) && (have_rev_id || d->rev_id))
1408 d->known_fields |= PCI_FILL_CLASS_EXT;
1412 fill_data_from_devinst_id(struct pci_dev *d, DEVINSTID_A devinst_id)
1414 const char *device_id;
1416 device_id = strchr(devinst_id, '\\');
1422 * Device Id part of Device Instance Id is in format:
1423 * "VEN_####&DEV_####&SUBSYS_########&REV_##"
1425 fill_data_from_string(d, device_id);
1429 fill_data_from_hardware_ids(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
1431 ULONG reg_type, reg_size, reg_len;
1432 struct pci_access *a = d->access;
1433 char *hardware_ids = NULL;
1438 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, ®_type, NULL, ®_size, 0);
1439 if (cr != CR_SUCCESS && cr != CR_BUFFER_SMALL)
1441 a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1444 else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1446 a->warning("Cannot retrieve hardware ids for PCI device %s: Hardware ids are stored as unknown type 0x%lx.", devinst_id, reg_type);
1452 * Returned size is on older Windows versions without nul-term char.
1453 * So explicitly increase size and fill nul-term byte.
1456 hardware_ids = pci_malloc(a, reg_size);
1458 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, ®_type, hardware_ids, ®_len, 0);
1459 hardware_ids[reg_size - 1] = 0;
1460 if (reg_len > reg_size)
1462 pci_mfree(hardware_ids);
1466 else if (cr != CR_SUCCESS)
1468 a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1469 pci_mfree(hardware_ids);
1472 else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1474 a->warning("Cannot retrieve hardware ids for PCI device %s: Hardware ids are stored as unknown type 0x%lx.", devinst_id, reg_type);
1475 pci_mfree(hardware_ids);
1480 * Hardware ids is nul-separated nul-term string list where each string has
1481 * one of the following format:
1482 * "PCI\\VEN_####&DEV_####&SUBSYS_########&REV_##"
1483 * "PCI\\VEN_####&DEV_####&SUBSYS_########"
1484 * "PCI\\VEN_####&DEV_####&REV_##&CC_####"
1485 * "PCI\\VEN_####&DEV_####&CC_######"
1486 * "PCI\\VEN_####&DEV_####&CC_####"
1487 * "PCI\\VEN_####&DEV_####&REV_##"
1488 * "PCI\\VEN_####&DEV_####"
1490 for (str = hardware_ids; *str != '\0'; str += strlen(str) + 1)
1492 if (strncmp(str, "PCI\\", 4) != 0)
1495 fill_data_from_string(d, str);
1498 pci_mfree(hardware_ids);
1502 scan_devinst_id(struct pci_access *a, DEVINSTID_A devinst_id)
1504 unsigned int domain, bus, dev, func;
1509 cr = CM_Locate_DevNodeA(&devinst, devinst_id, CM_LOCATE_DEVNODE_NORMAL);
1510 if (cr != CR_SUCCESS)
1512 /* Do not show warning when device is not present (= does not match NORMAL flag). */
1513 if (cr != CR_NO_SUCH_DEVNODE)
1514 a->warning("Cannot retrieve handle for device %s: %s.", devinst_id, cr_strerror(cr));
1518 /* get_device_location() returns FALSE if devinst is not real PCI device. */
1519 if (!get_device_location(a, devinst, devinst_id, &domain, &bus, &dev, &func))
1522 d = pci_get_dev(a, domain, bus, dev, func);
1524 d->no_config_access = 1;
1525 d->aux = (void *)devinst;
1527 /* Parse device id part of devinst id and fill details into pci_dev. */
1529 fill_data_from_devinst_id(d, devinst_id);
1531 /* Retrieve hardware ids of devinst, parse them and fill details into pci_dev. */
1533 fill_data_from_hardware_ids(d, devinst, devinst_id);
1536 fill_resources(d, devinst, devinst_id);
1539 * Set parent field to cfgmgr32 parent devinst handle and aux field to current
1540 * devinst handle. At later stage in win32_cfgmgr32_scan() when all pci_dev
1541 * devices are linked, change every devinst handle by pci_dev.
1545 DEVINST parent_devinst;
1546 if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS)
1549 a->warning("Cannot retrieve parent handle for device %s: %s.", devinst_id, cr_strerror(cr));
1551 d->parent = (void *)parent_devinst;
1556 win32_cfgmgr32_scan(struct pci_access *a)
1558 ULONG devinst_id_list_size;
1559 PCHAR devinst_id_list;
1560 DEVINSTID_A devinst_id;
1564 if (!resolve_cfgmgr32_functions())
1566 a->warning("Required cfgmgr32.dll functions are unavailable.");
1571 * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1572 * support this API but returns CR_SUCCESS without touching size argument.
1574 devinst_id_list_size = 0;
1575 cr = CM_Get_Device_ID_List_SizeA(&devinst_id_list_size, "PCI", CM_GETIDLIST_FILTER_ENUMERATOR);
1576 if (cr != CR_SUCCESS)
1578 a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1581 else if (devinst_id_list_size <= 1)
1583 a->warning("Cannot retrieve list of PCI devices: No device was found.");
1587 devinst_id_list = pci_malloc(a, devinst_id_list_size);
1588 cr = CM_Get_Device_ID_ListA("PCI", devinst_id_list, devinst_id_list_size, CM_GETIDLIST_FILTER_ENUMERATOR);
1589 if (cr != CR_SUCCESS)
1591 a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1592 pci_mfree(devinst_id_list);
1596 /* Register pci_dev for each cfgmgr32 devinst handle. */
1597 for (devinst_id = devinst_id_list; *devinst_id; devinst_id += strlen(devinst_id) + 1)
1598 scan_devinst_id(a, devinst_id);
1600 /* Fill all drivers. */
1604 /* Switch parent fields from cfgmgr32 devinst handle to pci_dev. */
1607 struct pci_dev *d1, *d2;
1608 for (d1 = a->devices; d1; d1 = d1->next)
1610 for (d2 = a->devices; d2; d2 = d2->next)
1611 if ((DEVINST)d1->parent == (DEVINST)d2->aux)
1615 d1->known_fields |= PCI_FILL_PARENT;
1619 /* devinst stored in ->aux is not needed anymore, clear it. */
1620 for (d = a->devices; d; d = d->next)
1623 pci_mfree(devinst_id_list);
1627 win32_cfgmgr32_detect(struct pci_access *a)
1629 ULONG devinst_id_list_size;
1632 if (!resolve_cfgmgr32_functions())
1634 a->debug("Required cfgmgr32.dll functions are unavailable.");
1639 * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1640 * support this API but returns CR_SUCCESS without touching size argument.
1642 devinst_id_list_size = 0;
1643 cr = CM_Get_Device_ID_List_SizeA(&devinst_id_list_size, "PCI", CM_GETIDLIST_FILTER_ENUMERATOR);
1644 if (cr != CR_SUCCESS)
1646 a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): %s.", cr_strerror(cr));
1649 else if (devinst_id_list_size <= 1)
1651 a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): No device was found.");
1659 win32_cfgmgr32_fill_info(struct pci_dev *d UNUSED, unsigned int flags UNUSED)
1662 * All available flags were filled by win32_cfgmgr32_scan()
1663 * and reading config space is not supported via cfgmgr32.
1668 win32_cfgmgr32_write(struct pci_dev *d UNUSED, int pos UNUSED, byte *buf UNUSED, int len UNUSED)
1670 /* Writing to config space is not supported via cfgmgr32. */
1675 win32_cfgmgr32_init(struct pci_access *a UNUSED)
1680 win32_cfgmgr32_cleanup(struct pci_access *a UNUSED)
1684 struct pci_methods pm_win32_cfgmgr32 = {
1686 "Win32 device listing via Configuration Manager",
1688 win32_cfgmgr32_detect,
1689 win32_cfgmgr32_init,
1690 win32_cfgmgr32_cleanup,
1691 win32_cfgmgr32_scan,
1692 win32_cfgmgr32_fill_info,
1693 pci_emulated_read, /* Reading of config space is not supported via cfgmgr32. */
1694 win32_cfgmgr32_write,
1695 NULL, /* read_vpd */
1696 NULL, /* init_dev */
1697 NULL, /* cleanup_dev */