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 introduced 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 ||
502 wcsncmp(service_config->lpBinaryPathName, L"\\??\\\\UNC\\", sizeof("\\??\\\\UNC\\")-1) == 0)
504 /* ImagePath is in NT UNC namespace, convert to Win32 UNC path via "\\\\" prefix. */
505 service_image_path = pci_malloc(a, sizeof(WCHAR) * (sizeof("\\\\") + wcslen(service_config->lpBinaryPathName) - (sizeof("\\??\\UNC\\")-1)));
506 /* Namespace separator may be single or double backslash. */
507 driver_path_len = sizeof("\\??\\")-1;
508 if (service_config->lpBinaryPathName[driver_path_len] == L'\\')
510 driver_path_len += sizeof("UNC\\")-1;
511 wcscpy(service_image_path, L"\\\\");
512 wcscpy(service_image_path + sizeof("\\\\")-1, service_config->lpBinaryPathName + driver_path_len);
514 else if (wcsncmp(service_config->lpBinaryPathName, L"\\??\\", sizeof("\\??\\")-1) == 0)
516 /* ImagePath is in NT Global?? namespace, root of the Win32 file namespace, so just remove "\\??\\" prefix to get Win32 path. */
517 service_image_path = pci_malloc(a, sizeof(WCHAR) * (wcslen(service_config->lpBinaryPathName) - (sizeof("\\??\\")-1)));
518 /* Namespace separator may be single or double backslash. */
519 driver_path_len = sizeof("\\??\\")-1;
520 if (service_config->lpBinaryPathName[driver_path_len] == L'\\')
522 wcscpy(service_image_path, service_config->lpBinaryPathName + driver_path_len);
524 else if (service_config->lpBinaryPathName[0] != L'\\')
526 /* ImagePath is relative to the NT SystemRoot namespace, convert to Win32 path via GetSystemWindowsDirectoryW()/GetWindowsDirectoryW(). */
527 service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + sizeof("\\") + wcslen(service_config->lpBinaryPathName)));
528 systemroot_len = get_system_root_path(service_image_path, systemroot_len+1);
529 if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
530 service_image_path[systemroot_len++] = L'\\';
531 wcscpy(service_image_path + systemroot_len, service_config->lpBinaryPathName);
535 /* 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. */
536 service_image_path = pci_malloc(a, sizeof(WCHAR) * wcslen(service_config->lpBinaryPathName));
537 wcscpy(service_image_path, service_config->lpBinaryPathName);
540 /* Calculate len of buffer needed for conversion from LPWSTR to char*. */
541 driver_path_len = WideCharToMultiByte(CP_ACP, 0, service_image_path, -1, NULL, 0, NULL, NULL);
542 if (driver_path_len <= 0)
544 error = GetLastError();
545 a->warning("Cannot convert kernel driver path from wide string to 8-bit string: %s.", win32_strerror(error));
549 driver_path = pci_malloc(a, driver_path_len);
550 driver_path_len = WideCharToMultiByte(CP_ACP, 0, service_image_path, -1, driver_path, driver_path_len, NULL, NULL);
551 if (driver_path_len <= 0)
553 error = GetLastError();
554 a->warning("Cannot convert kernel driver path from wide string to 8-bit string: %s.", win32_strerror(error));
555 pci_mfree(driver_path);
561 if (service_image_path)
562 pci_mfree(service_image_path);
564 pci_mfree(service_config);
566 CloseServiceHandle(service);
571 get_device_driver_devreg(struct pci_access *a, DEVINST devinst, DEVINSTID_A devinst_id)
576 cr = CM_Open_DevNode_Key(devinst, KEY_READ, 0, RegDisposition_OpenExisting, &key, CM_REGISTRY_SOFTWARE);
577 if (cr != CR_SUCCESS)
579 if (cr != CR_NO_SUCH_VALUE)
580 a->warning("Cannot retrieve driver key for device %s: %s.", devinst_id, cr_strerror(cr));
588 read_reg_key_string_value(struct pci_access *a, HKEY key, const char *name, DWORD *unkn_reg_type)
590 DWORD reg_type, reg_size, reg_len;
595 error = RegQueryValueExA(key, name, NULL, ®_type, NULL, ®_size);
596 if (error != ERROR_SUCCESS &&
597 error != ERROR_MORE_DATA)
602 else if (reg_type != REG_SZ)
605 *unkn_reg_type = reg_type;
610 value = pci_malloc(a, reg_size + 1);
612 error = RegQueryValueExA(key, name, NULL, ®_type, (PBYTE)value, ®_len);
613 if (error != ERROR_SUCCESS)
616 if (error == ERROR_MORE_DATA)
624 else if (reg_type != REG_SZ)
628 *unkn_reg_type = reg_type;
631 value[reg_len] = '\0';
637 driver_cmp(const char *driver, const char *match)
639 int len = strlen(driver);
640 if (driver[0] == '*')
642 if (len >= 4 && strcasecmp(driver + len - 4, ".vxd") == 0)
644 return strncasecmp(driver, match, len);
648 get_driver_path_for_regkey(struct pci_access *a, DEVINSTID_A devinst_id, HKEY key)
650 char *driver_list, *driver, *driver_next;
651 char *subdriver, *subname;
662 driver_list = read_reg_key_string_value(a, key, "DevLoader", &unkn_reg_type);
665 error = GetLastError();
667 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);
668 else if (error != ERROR_FILE_NOT_FOUND)
669 a->warning("Cannot read driver DevLoader key for PCI device %s: %s.", devinst_id, win32_strerror(error));
674 driver = driver_list;
677 driver_next = strchr(driver, ',');
679 *(driver_next++) = '\0';
681 if (driver_cmp(driver, "ios") == 0 ||
682 driver_cmp(driver, "vcomm") == 0)
683 subname = "PortDriver";
684 else if (driver_cmp(driver, "ntkern") == 0)
685 subname = "NTMPDriver";
686 else if (driver_cmp(driver, "ndis") == 0)
687 subname = "DeviceVxDs";
688 else if (driver_cmp(driver, "vdd") == 0)
694 if (subname && strcmp(subname, "minivdd") == 0)
696 error = RegOpenKeyA(key, "Default", &subkey);
697 if (error != ERROR_SUCCESS)
699 a->warning("Cannot open driver subkey Default for PCI device %s: %s.", devinst_id, win32_strerror(error));
710 subdriver = read_reg_key_string_value(a, subkey, subname, &unkn_reg_type);
713 error = GetLastError();
715 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);
716 else if (error != ERROR_FILE_NOT_FOUND)
717 a->warning("Cannot read driver %s key for PCI device %s: %s.", subname, devinst_id, win32_strerror(error));
718 else if (strcmp(subname, "minivdd") == 0)
723 else if (strcmp(subname, "drv") == 0)
735 char *endptr = strchr(subdriver, ',');
742 driver = driver_next;
745 if (subdriver && subdriver[0])
746 driver_ptr = subdriver;
752 if (driver_ptr && driver_ptr[0] == '*')
763 len = driver_ptr ? strlen(driver_ptr) : 0;
764 noext = driver_ptr && (len < 4 || driver_ptr[len-4] != '.');
770 if (tolower(driver_ptr[0]) >= 'a' && tolower(driver_ptr[0]) <= 'z' && driver_ptr[1] == ':')
772 /* Driver is already with absolute path. */
773 driver_path = pci_strdup(a, driver_ptr);
775 else if (driver_cmp(driver, "ntkern") == 0 && subdriver)
777 /* Driver is relative to system32\drivers\ directory which is relative to windows directory. */
778 systemdir_len = GetWindowsDirectoryA(NULL, 0);
779 driver_path = pci_malloc(a, systemdir_len + 1 + sizeof("system32\\drivers\\")-1 + strlen(driver_ptr) + 4 + 1);
780 systemdir_len = GetWindowsDirectoryA(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, "system32\\drivers\\%s%s", driver_ptr, noext ? ".sys" : "");
787 /* Driver is packed in vmm32.vxd which is stored in system directory. */
788 systemdir_len = GetSystemDirectoryA(NULL, 0);
789 driver_path = pci_malloc(a, systemdir_len + 1 + sizeof("vmm32.vxd ()")-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, "vmm32.vxd (%s%s)", driver_ptr, noext ? ".vxd" : "");
797 /* Otherwise driver is relative to system directory. */
798 systemdir_len = GetSystemDirectoryA(NULL, 0);
799 driver_path = pci_malloc(a, systemdir_len + 1 + strlen(driver_ptr) + 4 + 1);
800 systemdir_len = GetSystemDirectoryA(driver_path, systemdir_len + 1);
801 if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
802 driver_path[systemdir_len++] = '\\';
803 sprintf(driver_path + systemdir_len, "%s%s", driver_ptr, noext ? ".vxd" : "");
808 pci_mfree(subdriver);
809 pci_mfree(driver_list);
814 get_device_driver_path(struct pci_dev *d, SC_HANDLE manager, BOOL manager_supported)
816 struct pci_access *a = d->access;
817 BOOL service_supported = TRUE;
818 DEVINSTID_A devinst_id = NULL;
819 LPWSTR service_name = NULL;
820 ULONG devinst_id_len = 0;
821 char *driver_path = NULL;
822 DEVINST devinst = (DEVINST)d->aux;
827 if (CM_Get_DevNode_Status(&status, &problem, devinst, 0) != CR_SUCCESS || !(status & DN_DRIVER_LOADED))
830 if (CM_Get_Device_ID_Size(&devinst_id_len, devinst, 0) == CR_SUCCESS)
832 devinst_id = pci_malloc(a, devinst_id_len + 1);
833 if (CM_Get_Device_IDA(devinst, devinst_id, devinst_id_len + 1, 0) != CR_SUCCESS)
835 pci_mfree(devinst_id);
836 devinst_id = pci_strdup(a, "UNKNOWN");
840 devinst_id = pci_strdup(a, "UNKNOWN");
842 service_name = get_device_service_name(d->access, devinst, devinst_id, &service_supported);
843 if ((!service_name || !manager) && service_supported && manager_supported)
845 else if (service_name && manager)
847 driver_path = get_driver_path_for_service(d->access, service_name, manager);
851 key = get_device_driver_devreg(d->access, devinst, devinst_id);
854 driver_path = get_driver_path_for_regkey(d->access, devinst_id, key);
862 pci_mfree(service_name);
863 pci_mfree(devinst_id);
868 fill_drivers(struct pci_access *a)
870 BOOL manager_supported;
876 /* ERROR_CALL_NOT_IMPLEMENTED is returned on systems without Service Manager support. */
877 manager_supported = TRUE;
878 manager = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
881 error = GetLastError();
882 if (error != ERROR_CALL_NOT_IMPLEMENTED)
883 a->warning("Cannot open Service Manager with connect right: %s.", win32_strerror(error));
885 manager_supported = FALSE;
888 for (d = a->devices; d; d = d->next)
890 driver = get_device_driver_path(d, manager, manager_supported);
893 pci_set_property(d, PCI_FILL_DRIVER, driver);
896 d->known_fields |= PCI_FILL_DRIVER;
900 CloseServiceHandle(manager);
904 fill_resources(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
906 struct pci_access *a = d->access;
914 RES_DES prev_res_des;
923 int last_shared_irq = -1;
925 cr = CM_Get_DevNode_Status(&status, &problem, devinst, 0);
926 if (cr != CR_SUCCESS)
928 a->warning("Cannot retrieve status of PCI device %s: %s.", devinst_id, cr_strerror(cr));
932 cr = CR_NO_MORE_LOG_CONF;
935 * If the device is running then retrieve allocated configuration by PnP
936 * manager which is currently in use by a device.
938 if (!(status & DN_HAS_PROBLEM))
939 cr = CM_Get_First_Log_Conf(&config, devinst, ALLOC_LOG_CONF);
942 * If the device is not running or it does not have allocated configuration by
943 * PnP manager then retrieve forced configuration which prevents PnP manager
944 * from assigning resources.
946 if (cr == CR_NO_MORE_LOG_CONF)
947 cr = CM_Get_First_Log_Conf(&config, devinst, FORCED_LOG_CONF);
950 * If the device does not have neither allocated configuration by PnP manager
951 * nor forced configuration and it is not disabled in the BIOS then retrieve
952 * boot configuration supplied by the BIOS.
954 if (cr == CR_NO_MORE_LOG_CONF &&
955 (!(status & DN_HAS_PROBLEM) || problem != CM_PROB_HARDWARE_DISABLED))
956 cr = CM_Get_First_Log_Conf(&config, devinst, BOOT_LOG_CONF);
958 if (cr != CR_SUCCESS)
961 * Note: Starting with Windows 8, CM_Get_First_Log_Conf returns
962 * CR_CALL_NOT_IMPLEMENTED when used in a Wow64 scenario.
963 * To request information about the hardware resources on a local machine
964 * it is necessary implement an architecture-native version of the
965 * application using the hardware resource APIs. For example: An AMD64
966 * application for AMD64 systems.
968 if (cr == CR_CALL_NOT_IMPLEMENTED && is_32bit_on_win8_64bit_system())
970 static BOOL warn_once = FALSE;
974 a->warning("Cannot retrieve resources of PCI devices from 32-bit application on 64-bit system.");
977 else if (cr != CR_NO_MORE_LOG_CONF)
978 a->warning("Cannot retrieve resources of PCI device %s: %s.", devinst_id, cr_strerror(cr));
983 non_nt_system = is_non_nt_system();
990 ULONG child_name_len;
994 if (CM_Get_Child(&child, devinst, 0) != CR_SUCCESS)
996 else if (CM_Get_Device_ID_Size(&child_name_len, child, 0) != CR_SUCCESS)
1001 child_name = pci_malloc(a, child_name_len);
1002 if (CM_Get_Device_IDA(child, child_name, child_name_len, 0) != CR_SUCCESS)
1004 else if (strncmp(child_name, "PCI\\", 4) != 0)
1008 pci_mfree(child_name);
1011 if (has_child || d->device_class == PCI_CLASS_BRIDGE_PCI || d->device_class == PCI_CLASS_BRIDGE_CARDBUS)
1020 prev_res_des = (RES_DES)config;
1021 while ((cr = CM_Get_Next_Res_Des(&res_des, prev_res_des, ResType_All, &res_id, 0)) == CR_SUCCESS)
1023 pciaddr_t start, end, size, flags;
1024 ULONG res_des_data_size;
1027 if (prev_res_des != config)
1028 CM_Free_Res_Des_Handle(prev_res_des);
1030 prev_res_des = res_des;
1032 cr = CM_Get_Res_Des_Data_Size(&res_des_data_size, res_des, 0);
1033 if (cr != CR_SUCCESS)
1035 a->warning("Cannot retrieve resource data of PCI device %s: %s.", devinst_id, cr_strerror(cr));
1039 if (!res_des_data_size)
1041 a->warning("Cannot retrieve resource data of PCI device %s: %s.", devinst_id, "Empty data");
1045 res_des_data = pci_malloc(a, res_des_data_size);
1046 cr = CM_Get_Res_Des_Data(res_des, res_des_data, res_des_data_size, 0);
1047 if (cr != CR_SUCCESS)
1049 a->warning("Cannot retrieve resource data of PCI device %s: %s.", devinst_id, cr_strerror(cr));
1050 pci_mfree(res_des_data);
1055 * There can be more resources with the same id. In this case we are
1056 * interested in the last one in the list as at the beginning of the list
1057 * can be some virtual resources (which are not set in PCI config space).
1060 if (res_id == ResType_IO)
1062 PIO_RESOURCE io_data = (PIO_RESOURCE)res_des_data;
1064 start = io_data->IO_Header.IOD_Alloc_Base;
1065 end = io_data->IO_Header.IOD_Alloc_End;
1066 size = (end > start) ? (end - start + 1) : 0;
1067 flags = PCI_IORESOURCE_IO;
1070 * If neither 10-bit, 12-bit, nor 16-bit support is presented then
1071 * expects that this is 32-bit I/O resource. If resource does not fit
1072 * into 16-bit space then it must be 32-bit. If PCI I/O resource is
1073 * not 32-bit then it is 16-bit.
1075 if (end <= 0xffff && (io_data->IO_Header.IOD_DesFlags & (fIOD_10_BIT_DECODE|fIOD_12_BIT_DECODE|fIOD_16_BIT_DECODE)))
1076 flags |= PCI_IORESOURCE_IO_16BIT_ADDR;
1079 * 16/32-bit non-NT systems do not support these two flags.
1080 * Most NT-based Windows versions support only the fIOD_WINDOW_DECODE
1081 * flag and put all BAR resources before window resources in this
1082 * resource list. So use this fIOD_WINDOW_DECODE flag as separator
1083 * between IO/MEM windows and IO/MEM BARs of PCI Bridges.
1085 if (io_data->IO_Header.IOD_DesFlags & fIOD_WINDOW_DECODE)
1087 else if (io_data->IO_Header.IOD_DesFlags & fIOD_PORT_BAR)
1090 if (is_bar_res && bar_res_count < 6)
1092 d->flags[bar_res_count] = flags;
1093 d->base_addr[bar_res_count] = start;
1094 d->size[bar_res_count] = size;
1097 else if (!is_bar_res)
1099 d->bridge_flags[0] = flags;
1100 d->bridge_base_addr[0] = start;
1101 d->bridge_size[0] = size;
1102 d->known_fields |= PCI_FILL_BRIDGE_BASES;
1105 else if (res_id == ResType_Mem)
1107 PMEM_RESOURCE mem_data = (PMEM_RESOURCE)res_des_data;
1109 start = mem_data->MEM_Header.MD_Alloc_Base;
1110 end = mem_data->MEM_Header.MD_Alloc_End;
1111 size = (end > start) ? (end - start + 1) : 0;
1112 flags = PCI_IORESOURCE_MEM;
1115 * If fMD_PrefetchAllowed flag is set then this is
1116 * PCI Prefetchable Memory resource.
1118 if ((mem_data->MEM_Header.MD_Flags & mMD_Prefetchable) == fMD_PrefetchAllowed)
1119 flags |= PCI_IORESOURCE_PREFETCH;
1121 /* If resource does not fit into 32-bit space then it must be 64-bit. */
1122 if (is_bar_res && end > 0xffffffff)
1123 flags |= PCI_IORESOURCE_MEM_64;
1126 * These two flags (fMD_WINDOW_DECODE and fMD_MEMORY_BAR) are
1127 * unsupported on most Windows versions, so distinguish between
1128 * window and BAR based on previous resource type.
1130 if (mem_data->MEM_Header.MD_Flags & fMD_WINDOW_DECODE)
1132 else if (mem_data->MEM_Header.MD_Flags & fMD_MEMORY_BAR)
1135 /* 64-bit BAR resource must be at even position. */
1136 if (is_bar_res && (flags & PCI_IORESOURCE_MEM_64) && bar_res_count % 2)
1139 if (is_bar_res && bar_res_count < 6)
1141 d->flags[bar_res_count] = flags;
1142 d->base_addr[bar_res_count] = start;
1143 d->size[bar_res_count] = size;
1145 /* 64-bit BAR resource occupies two slots. */
1146 if (flags & PCI_IORESOURCE_MEM_64)
1149 else if (!is_bar_res && !(flags & PCI_IORESOURCE_PREFETCH))
1151 d->bridge_flags[1] = flags;
1152 d->bridge_base_addr[1] = start;
1153 d->bridge_size[1] = size;
1154 d->known_fields |= PCI_FILL_BRIDGE_BASES;
1156 else if (!is_bar_res && (flags & PCI_IORESOURCE_PREFETCH))
1158 d->bridge_flags[2] = flags;
1159 d->bridge_base_addr[2] = start;
1160 d->bridge_size[2] = size;
1161 d->known_fields |= PCI_FILL_BRIDGE_BASES;
1164 else if (res_id == ResType_IRQ)
1166 PIRQ_RESOURCE irq_data = (PIRQ_RESOURCE)res_des_data;
1169 * libpci's d->irq should be set to the non-MSI PCI IRQ and therefore
1170 * it should be level IRQ which may be shared with other PCI devices
1171 * and drivers in the system. As always we want to retrieve the last
1172 * IRQ number from the resource list.
1174 * On 16/32-bit non-NT systems is fIRQD_Level set to 2 but on NT
1175 * systems to 0. Moreover it looks like that different PCI drivers
1176 * on both NT and non-NT systems set bits 0 and 1 to wrong values
1177 * and so reported value in this list may be incorrect.
1179 * Therefore take the last level-shared IRQ number from the resource
1180 * list and if there is none of this type then take the last IRQ
1181 * number from the list.
1183 last_irq = irq_data->IRQ_Header.IRQD_Alloc_Num;
1184 if ((irq_data->IRQ_Header.IRQD_Flags & (mIRQD_Share|mIRQD_Edge_Level)) == (fIRQD_Share|fIRQD_Level))
1185 last_shared_irq = irq_data->IRQ_Header.IRQD_Alloc_Num;
1188 * IRQ resource on 16/32-bit non-NT systems is separator between
1189 * IO/MEM windows and IO/MEM BARs of PCI Bridges. After the IRQ
1190 * resource are IO/MEM BAR resources.
1192 if (!is_bar_res && non_nt_system)
1196 pci_mfree(res_des_data);
1198 if (cr != CR_NO_MORE_RES_DES)
1199 a->warning("Cannot retrieve resources of PCI device %s: %s.", devinst_id, cr_strerror(cr));
1201 if (prev_res_des != config)
1202 CM_Free_Res_Des_Handle(prev_res_des);
1204 CM_Free_Log_Conf_Handle(config);
1206 /* Set the last IRQ from the resource list to pci_dev. */
1207 if (last_shared_irq >= 0)
1208 d->irq = last_shared_irq;
1209 else if (last_irq >= 0)
1211 if (last_shared_irq >= 0 || last_irq >= 0)
1212 d->known_fields |= PCI_FILL_IRQ;
1214 if (bar_res_count > 0)
1215 d->known_fields |= PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS;
1219 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)
1221 ULONG reg_type, reg_len;
1223 BOOL have_bus, have_devfunc;
1224 DWORD drp_bus_num, drp_address;
1228 have_devfunc = FALSE;
1231 * DRP_BUSNUMBER consists of PCI domain number in high 24 bits
1232 * and PCI bus number in low 8 bits.
1234 reg_len = sizeof(drp_bus_num);
1235 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_BUSNUMBER, ®_type, &drp_bus_num, ®_len, 0);
1236 if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_bus_num))
1238 *domain = drp_bus_num >> 8;
1239 *bus = drp_bus_num & 0xff;
1244 * DRP_ADDRESS consists of PCI device number in high 16 bits
1245 * and PCI function number in low 16 bits.
1247 reg_len = sizeof(drp_address);
1248 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_ADDRESS, ®_type, &drp_address, ®_len, 0);
1249 if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_address))
1251 *dev = drp_address >> 16;
1252 *func = drp_address & 0xffff;
1253 have_devfunc = TRUE;
1257 * Device Instance Id for PCI devices is of format:
1258 * "<enumerator>\\<device_id>\\<instance_id>"
1260 * "<enumerator>" is "PCI"
1261 * "<device_id>" is "VEN_####&DEV_####&SUBSYS_########&REV_##"
1262 * and "<instance_id>" for PCI devices is at least in one of following format:
1263 * "BUS_##&DEV_##&FUNC_##"
1264 * "##.." (sequence of devfn hex bytes, where bytes represents tree path to the root)
1265 * "#..&#..&#..&#.." (four hex numbers separated by "&"; meaning is unknown yet)
1267 * First two formats are used only on systems without support for multiple
1268 * domains. The second format uses intel-conf encoding of device and function
1269 * number: Low 3 bits is function number and high 5 bits is device number.
1270 * Bus number is not really encoded in second format!
1272 * The third format is used on systems with support for multiple domains but
1273 * format is variable length and currently its meaning is unknown. Apparently
1274 * it looks like that DRP_BUSNUMBER and DRP_ADDRESS registry properties are
1275 * supported on these systems.
1277 * If DRP_BUSNUMBER or DRP_ADDRESS failed then try to parse PCI bus, device
1278 * and function numbers from Instance Id part.
1280 if (!have_bus || !have_devfunc)
1282 const char *device_id0 = strchr(devinst_id, '\\');
1283 const char *instance_id0 = device_id0 ? strchr(device_id0 + 1, '\\') : NULL;
1284 const char *instance_id = instance_id0 ? instance_id0 + 1 : NULL;
1289 if (fmt_validate(instance_id, strlen(instance_id), "BUS_##&DEV_##&FUNC_##") &&
1290 sscanf(instance_id, "BUS_%x&DEV_%x&FUNC_%x", bus, dev, func) == 3)
1293 have_devfunc = TRUE;
1295 else if (seq_xdigit_validate(instance_id, 2, 2) &&
1296 sscanf(instance_id, "%2x", &devfn) == 1)
1299 *func = devfn & 0x7;
1300 have_devfunc = TRUE;
1306 * Virtual IRQ holder devices do not have assigned any bus/dev/func number and
1307 * have "IRQHOLDER" in their Device Id part. So skip them.
1309 if (!have_bus && !have_devfunc && strncmp(devinst_id, "PCI\\IRQHOLDER\\", 14) == 0)
1313 * When some numbers cannot be retrieved via cfgmgr32 then set them to zeros
1314 * to have structure initialized. It makes sense to report via libpci also
1315 * such "incomplete" device as cfgmgr32 can provide additional information
1316 * like device/vendor ids or assigned resources.
1318 if (!have_bus && !have_devfunc)
1320 *bus = *dev = *func = 0;
1321 a->warning("Cannot retrieve bus, device and function numbers for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1326 a->warning("Cannot retrieve bus number for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1328 else if (!have_devfunc)
1331 a->warning("Cannot retrieve device and function numbers for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1338 fill_data_from_string(struct pci_dev *d, const char *str)
1340 BOOL have_device_id;
1341 BOOL have_vendor_id;
1344 const char *endptr, *endptr2;
1348 have_device_id = have_vendor_id = (d->known_fields & PCI_FILL_IDENT);
1349 have_prog_if = have_rev_id = (d->known_fields & PCI_FILL_CLASS_EXT);
1353 endptr = strchr(str, '&');
1354 endptr2 = strchr(str, '\\');
1355 if (endptr2 && (!endptr || endptr > endptr2))
1357 len = endptr ? endptr-str : (int)strlen(str);
1359 if (!have_vendor_id &&
1360 fmt_validate(str, len, "VEN_####") &&
1361 sscanf(str, "VEN_%x", &hex) == 1)
1364 have_vendor_id = TRUE;
1366 else if (!have_device_id &&
1367 fmt_validate(str, len, "DEV_####") &&
1368 sscanf(str, "DEV_%x", &hex) == 1)
1371 have_device_id = TRUE;
1373 else if (!(d->known_fields & PCI_FILL_SUBSYS) &&
1374 fmt_validate(str, len, "SUBSYS_########") &&
1375 sscanf(str, "SUBSYS_%x", &hex) == 1)
1377 d->subsys_vendor_id = hex & 0xffff;
1378 d->subsys_id = hex >> 16;
1379 d->known_fields |= PCI_FILL_SUBSYS;
1381 else if (!have_rev_id &&
1382 fmt_validate(str, len, "REV_##") &&
1383 sscanf(str, "REV_%x", &hex) == 1)
1388 else if (!((d->known_fields & PCI_FILL_CLASS) && have_prog_if) &&
1389 (fmt_validate(str, len, "CC_####") || fmt_validate(str, len, "CC_######")) &&
1390 sscanf(str, "CC_%x", &hex) == 1)
1396 d->prog_if = hex & 0xff;
1397 have_prog_if = TRUE;
1401 if (!(d->known_fields & PCI_FILL_CLASS))
1403 d->device_class = hex;
1404 d->known_fields |= PCI_FILL_CLASS;
1408 if (!endptr || endptr == endptr2)
1414 if ((have_device_id || d->device_id) && (have_vendor_id || d->vendor_id))
1415 d->known_fields |= PCI_FILL_IDENT;
1417 if ((have_prog_if || d->prog_if) && (have_rev_id || d->rev_id))
1418 d->known_fields |= PCI_FILL_CLASS_EXT;
1422 fill_data_from_devinst_id(struct pci_dev *d, DEVINSTID_A devinst_id)
1424 const char *device_id;
1426 device_id = strchr(devinst_id, '\\');
1432 * Device Id part of Device Instance Id is in format:
1433 * "VEN_####&DEV_####&SUBSYS_########&REV_##"
1435 fill_data_from_string(d, device_id);
1439 fill_data_from_hardware_ids(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
1441 ULONG reg_type, reg_size, reg_len;
1442 struct pci_access *a = d->access;
1443 char *hardware_ids = NULL;
1448 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, ®_type, NULL, ®_size, 0);
1449 if (cr != CR_SUCCESS && cr != CR_BUFFER_SMALL)
1451 a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1454 else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1456 a->warning("Cannot retrieve hardware ids for PCI device %s: Hardware ids are stored as unknown type 0x%lx.", devinst_id, reg_type);
1462 * Returned size is on older Windows versions without nul-term char.
1463 * So explicitly increase size and fill nul-term byte.
1466 hardware_ids = pci_malloc(a, reg_size);
1468 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, ®_type, hardware_ids, ®_len, 0);
1469 hardware_ids[reg_size - 1] = 0;
1470 if (reg_len > reg_size)
1472 pci_mfree(hardware_ids);
1476 else if (cr != CR_SUCCESS)
1478 a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1479 pci_mfree(hardware_ids);
1482 else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1484 a->warning("Cannot retrieve hardware ids for PCI device %s: Hardware ids are stored as unknown type 0x%lx.", devinst_id, reg_type);
1485 pci_mfree(hardware_ids);
1490 * Hardware ids is nul-separated nul-term string list where each string has
1491 * one of the following format:
1492 * "PCI\\VEN_####&DEV_####&SUBSYS_########&REV_##"
1493 * "PCI\\VEN_####&DEV_####&SUBSYS_########"
1494 * "PCI\\VEN_####&DEV_####&REV_##&CC_####"
1495 * "PCI\\VEN_####&DEV_####&CC_######"
1496 * "PCI\\VEN_####&DEV_####&CC_####"
1497 * "PCI\\VEN_####&DEV_####&REV_##"
1498 * "PCI\\VEN_####&DEV_####"
1500 for (str = hardware_ids; *str != '\0'; str += strlen(str) + 1)
1502 if (strncmp(str, "PCI\\", 4) != 0)
1505 fill_data_from_string(d, str);
1508 pci_mfree(hardware_ids);
1512 scan_devinst_id(struct pci_access *a, DEVINSTID_A devinst_id)
1514 unsigned int domain, bus, dev, func;
1519 cr = CM_Locate_DevNodeA(&devinst, devinst_id, CM_LOCATE_DEVNODE_NORMAL);
1520 if (cr != CR_SUCCESS)
1522 /* Do not show warning when device is not present (= does not match NORMAL flag). */
1523 if (cr != CR_NO_SUCH_DEVNODE)
1524 a->warning("Cannot retrieve handle for device %s: %s.", devinst_id, cr_strerror(cr));
1528 /* get_device_location() returns FALSE if devinst is not real PCI device. */
1529 if (!get_device_location(a, devinst, devinst_id, &domain, &bus, &dev, &func))
1532 d = pci_get_dev(a, domain, bus, dev, func);
1534 if (!d->access->aux)
1535 d->no_config_access = 1;
1536 d->aux = (void *)devinst;
1538 /* Parse device id part of devinst id and fill details into pci_dev. */
1540 fill_data_from_devinst_id(d, devinst_id);
1542 /* Retrieve hardware ids of devinst, parse them and fill details into pci_dev. */
1544 fill_data_from_hardware_ids(d, devinst, devinst_id);
1547 fill_resources(d, devinst, devinst_id);
1550 * Set parent field to cfgmgr32 parent devinst handle and aux field to current
1551 * devinst handle. At later stage in win32_cfgmgr32_scan() when all pci_dev
1552 * devices are linked, change every devinst handle by pci_dev.
1556 DEVINST parent_devinst;
1557 if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS)
1560 a->warning("Cannot retrieve parent handle for device %s: %s.", devinst_id, cr_strerror(cr));
1562 d->parent = (void *)parent_devinst;
1567 win32_cfgmgr32_scan(struct pci_access *a)
1569 ULONG devinst_id_list_size;
1570 PCHAR devinst_id_list;
1571 DEVINSTID_A devinst_id;
1575 if (!resolve_cfgmgr32_functions())
1577 a->warning("Required cfgmgr32.dll functions are unavailable.");
1582 * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1583 * support this API but returns CR_SUCCESS without touching size argument.
1585 devinst_id_list_size = 0;
1586 cr = CM_Get_Device_ID_List_SizeA(&devinst_id_list_size, "PCI", CM_GETIDLIST_FILTER_ENUMERATOR);
1587 if (cr != CR_SUCCESS)
1589 a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1592 else if (devinst_id_list_size <= 1)
1594 a->warning("Cannot retrieve list of PCI devices: No device was found.");
1598 devinst_id_list = pci_malloc(a, devinst_id_list_size);
1599 cr = CM_Get_Device_ID_ListA("PCI", devinst_id_list, devinst_id_list_size, CM_GETIDLIST_FILTER_ENUMERATOR);
1600 if (cr != CR_SUCCESS)
1602 a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1603 pci_mfree(devinst_id_list);
1607 /* Register pci_dev for each cfgmgr32 devinst handle. */
1608 for (devinst_id = devinst_id_list; *devinst_id; devinst_id += strlen(devinst_id) + 1)
1609 scan_devinst_id(a, devinst_id);
1611 /* Fill all drivers. */
1615 /* Switch parent fields from cfgmgr32 devinst handle to pci_dev. */
1618 struct pci_dev *d1, *d2;
1619 for (d1 = a->devices; d1; d1 = d1->next)
1621 for (d2 = a->devices; d2; d2 = d2->next)
1622 if ((DEVINST)d1->parent == (DEVINST)d2->aux)
1626 d1->known_fields |= PCI_FILL_PARENT;
1630 /* devinst stored in ->aux is not needed anymore, clear it. */
1631 for (d = a->devices; d; d = d->next)
1634 pci_mfree(devinst_id_list);
1638 win32_cfgmgr32_config(struct pci_access *a)
1640 pci_define_param(a, "win32.cfgmethod", "auto", "PCI config space access method");
1644 win32_cfgmgr32_detect(struct pci_access *a)
1646 ULONG devinst_id_list_size;
1649 if (!resolve_cfgmgr32_functions())
1651 a->debug("Required cfgmgr32.dll functions are unavailable.");
1656 * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1657 * support this API but returns CR_SUCCESS without touching size argument.
1659 devinst_id_list_size = 0;
1660 cr = CM_Get_Device_ID_List_SizeA(&devinst_id_list_size, "PCI", CM_GETIDLIST_FILTER_ENUMERATOR);
1661 if (cr != CR_SUCCESS)
1663 a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): %s.", cr_strerror(cr));
1666 else if (devinst_id_list_size <= 1)
1668 a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): No device was found.");
1676 win32_cfgmgr32_fill_info(struct pci_dev *d, unsigned int flags)
1679 * All available flags were filled by win32_cfgmgr32_scan().
1680 * Filling more flags is possible only from config space.
1682 if (!d->access->aux)
1685 pci_generic_fill_info(d, flags);
1689 win32_cfgmgr32_read(struct pci_dev *d, int pos, byte *buf, int len)
1691 struct pci_access *a = d->access;
1692 struct pci_access *acfg = a->aux;
1693 struct pci_dev *dcfg = d->aux;
1696 return pci_emulated_read(d, pos, buf, len);
1699 d->aux = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
1701 return pci_read_block(dcfg, pos, buf, len);
1705 win32_cfgmgr32_write(struct pci_dev *d, int pos, byte *buf, int len)
1707 struct pci_access *a = d->access;
1708 struct pci_access *acfg = a->aux;
1709 struct pci_dev *dcfg = d->aux;
1715 d->aux = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
1717 return pci_write_block(dcfg, pos, buf, len);
1721 win32_cfgmgr32_cleanup_dev(struct pci_dev *d)
1723 struct pci_dev *dcfg = d->aux;
1730 win32_cfgmgr32_init(struct pci_access *a)
1732 char *cfgmethod = pci_get_param(a, "win32.cfgmethod");
1733 struct pci_access *acfg;
1735 if (strcmp(cfgmethod, "") == 0 ||
1736 strcmp(cfgmethod, "auto") == 0)
1738 acfg = pci_clone_access(a);
1739 acfg->method = PCI_ACCESS_AUTO;
1741 else if (strcmp(cfgmethod, "none") == 0 ||
1742 strcmp(cfgmethod, "win32-cfgmgr32") == 0)
1745 a->error("Write access requested but option win32.cfgmethod was not set.");
1750 int m = pci_lookup_method(cfgmethod);
1752 a->error("Option win32.cfgmethod is set to an unknown access method \"%s\".", cfgmethod);
1753 acfg = pci_clone_access(a);
1757 a->debug("Loading config space access method...\n");
1758 if (!pci_init_internal(acfg, PCI_ACCESS_WIN32_CFGMGR32))
1761 a->debug("Cannot find any working config space access method.\n");
1763 a->error("Write access requested but no usable access method found.");
1771 win32_cfgmgr32_cleanup(struct pci_access *a)
1773 struct pci_access *acfg = a->aux;
1779 struct pci_methods pm_win32_cfgmgr32 = {
1781 "Win32 device listing via Configuration Manager",
1782 win32_cfgmgr32_config,
1783 win32_cfgmgr32_detect,
1784 win32_cfgmgr32_init,
1785 win32_cfgmgr32_cleanup,
1786 win32_cfgmgr32_scan,
1787 win32_cfgmgr32_fill_info,
1788 win32_cfgmgr32_read,
1789 win32_cfgmgr32_write,
1790 NULL, /* read_vpd */
1791 NULL, /* init_dev */
1792 win32_cfgmgr32_cleanup_dev,