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 v2+.
8 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <ctype.h> /* for isxdigit() */
15 #include <stdio.h> /* for sprintf() */
16 #include <string.h> /* for strlen(), strchr(), strncmp() */
17 #include <wchar.h> /* for wcslen(), wcscpy() */
20 #include "win32-helpers.h"
22 /* Unfortunately MinGW32 toolchain does not provide these cfgmgr32 constants. */
24 #ifndef RegDisposition_OpenExisting
25 #define RegDisposition_OpenExisting 0x00000001
28 #ifndef CM_REGISTRY_SOFTWARE
29 #define CM_REGISTRY_SOFTWARE 0x00000001
32 #ifndef CM_DRP_HARDWAREID
33 #define CM_DRP_HARDWAREID 0x00000002
35 #ifndef CM_DRP_SERVICE
36 #define CM_DRP_SERVICE 0x00000005
38 #ifndef CM_DRP_BUSNUMBER
39 #define CM_DRP_BUSNUMBER 0x00000016
41 #ifndef CM_DRP_ADDRESS
42 #define CM_DRP_ADDRESS 0x0000001D
45 #ifndef CR_INVALID_CONFLICT_LIST
46 #define CR_INVALID_CONFLICT_LIST 0x00000039
48 #ifndef CR_INVALID_INDEX
49 #define CR_INVALID_INDEX 0x0000003A
51 #ifndef CR_INVALID_STRUCTURE_SIZE
52 #define CR_INVALID_STRUCTURE_SIZE 0x0000003B
55 #ifndef fIOD_10_BIT_DECODE
56 #define fIOD_10_BIT_DECODE 0x0004
58 #ifndef fIOD_12_BIT_DECODE
59 #define fIOD_12_BIT_DECODE 0x0008
61 #ifndef fIOD_16_BIT_DECODE
62 #define fIOD_16_BIT_DECODE 0x0010
64 #ifndef fIOD_POSITIVE_DECODE
65 #define fIOD_POSITIVE_DECODE 0x0020
67 #ifndef fIOD_PASSIVE_DECODE
68 #define fIOD_PASSIVE_DECODE 0x0040
70 #ifndef fIOD_WINDOW_DECODE
71 #define fIOD_WINDOW_DECODE 0x0080
74 #define fIOD_PORT_BAR 0x0100
77 #ifndef fMD_WINDOW_DECODE
78 #define fMD_WINDOW_DECODE 0x0040
80 #ifndef fMD_MEMORY_BAR
81 #define fMD_MEMORY_BAR 0x0080
84 #ifndef mMD_Prefetchable
85 #define mMD_Prefetchable fMD_Prefetchable
89 * Unfortunately MinGW32 toolchain does not provide import library for these
90 * cfgmgr32.dll functions. So resolve pointers to these functions at runtime.
93 #ifdef CM_Get_DevNode_Registry_PropertyA
94 #undef CM_Get_DevNode_Registry_PropertyA
96 static CONFIGRET (WINAPI *MyCM_Get_DevNode_Registry_PropertyA)(DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType, PVOID Buffer, PULONG pulLength, ULONG ulFlags);
97 #define CM_Get_DevNode_Registry_PropertyA MyCM_Get_DevNode_Registry_PropertyA
99 #ifdef CM_Get_DevNode_Registry_PropertyW
100 #undef CM_Get_DevNode_Registry_PropertyW
102 static CONFIGRET (WINAPI *MyCM_Get_DevNode_Registry_PropertyW)(DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType, PVOID Buffer, PULONG pulLength, ULONG ulFlags);
103 #define CM_Get_DevNode_Registry_PropertyW MyCM_Get_DevNode_Registry_PropertyW
105 #ifndef CM_Open_DevNode_Key
106 #undef CM_Open_DevNode_Key
108 static CONFIGRET (WINAPI *MyCM_Open_DevNode_Key)(DEVINST dnDevNode, REGSAM samDesired, ULONG ulHardwareProfile, REGDISPOSITION Disposition, PHKEY phkDevice, ULONG ulFlags);
109 #define CM_Open_DevNode_Key MyCM_Open_DevNode_Key
112 resolve_cfgmgr32_functions(void)
116 if (CM_Get_DevNode_Registry_PropertyA && CM_Get_DevNode_Registry_PropertyW && CM_Open_DevNode_Key)
119 cfgmgr32 = GetModuleHandleA("cfgmgr32.dll");
123 CM_Get_DevNode_Registry_PropertyA = (void *)GetProcAddress(cfgmgr32, "CM_Get_DevNode_Registry_PropertyA");
124 CM_Get_DevNode_Registry_PropertyW = (void *)GetProcAddress(cfgmgr32, "CM_Get_DevNode_Registry_PropertyW");
125 CM_Open_DevNode_Key = (void *)GetProcAddress(cfgmgr32, "CM_Open_DevNode_Key");
126 if (!CM_Get_DevNode_Registry_PropertyA || !CM_Get_DevNode_Registry_PropertyW || !CM_Open_DevNode_Key)
133 * cfgmgr32.dll uses custom non-Win32 error numbers which are unsupported by
134 * Win32 APIs like GetLastError() and FormatMessage() functions.
136 * Windows 7 introduced new cfgmgr32.dll function CM_MapCrToWin32Err() for
137 * translating mapping CR_* errors to Win32 errors but most error codes are
138 * not mapped. So this function is unusable.
140 * Error strings for CR_* errors are defined in cmapi.rc file which is
141 * statically linked into some system libraries (e.g. filemgmt.dll,
142 * acledit.dll, netui0.dll or netui2.dll) but due to static linking it is
143 * not possible to access these error strings easily at runtime.
145 * So define own function for translating CR_* errors directly to strings.
148 cr_strerror(CONFIGRET cr_error_id)
150 static char unknown_error[sizeof("Unknown CR error XXXXXXXXXX")];
151 static const char *cr_errors[] = {
152 "The operation completed successfully",
154 "Not enough memory is available to process this command",
155 "A required pointer parameter is invalid",
156 "The ulFlags parameter specified is invalid for this operation",
157 "The device instance handle parameter is not valid",
158 "The supplied resource descriptor parameter is invalid",
159 "The supplied logical configuration parameter is invalid",
160 "CR_INVALID_ARBITRATOR",
161 "CR_INVALID_NODELIST",
162 "CR_DEVNODE_HAS_REQS/CR_DEVINST_HAS_REQS",
163 "The RESOURCEID parameter does not contain a valid RESOURCEID",
164 "CR_DLVXD_NOT_FOUND",
165 "The specified device instance handle does not correspond to a present device",
166 "There are no more logical configurations available",
167 "There are no more resource descriptions available",
168 "This device instance already exists",
169 "The supplied range list parameter is invalid",
171 "A general internal error occurred",
172 "CR_NO_SUCH_LOGICAL_DEV",
173 "The device is disabled for this configuration",
175 "A service or application refused to allow removal of this device",
177 "CR_INVALID_LOAD_TYPE",
178 "An output parameter was too small to hold all the data available",
180 "CR_NO_REGISTRY_HANDLE",
181 "A required entry in the registry is missing or an attempt to write to the registry failed",
182 "The specified Device ID is not a valid Device ID",
183 "One or more parameters were invalid",
185 "CR_DEVLOADER_NOT_READY",
187 "There are no more hardware profiles available",
188 "CR_DEVICE_NOT_THERE",
189 "The specified value does not exist in the registry",
191 "The specified priority is invalid for this operation",
192 "This device cannot be disabled",
198 "The specified key does not exist in the registry",
199 "The specified machine name does not meet the UNC naming conventions",
200 "A general remote communication error occurred",
201 "The machine selected for remote communication is not available at this time",
202 "The Plug and Play service or another required service is not available",
204 "This routine is not implemented in this version of the operating system",
205 "The specified property type is invalid for this operation",
206 "Device interface is active",
207 "No such device interface",
208 "Invalid reference string",
209 "Invalid conflict list",
211 "Invalid structure size"
213 if (cr_error_id <= 0 || cr_error_id >= sizeof(cr_errors)/sizeof(*cr_errors))
215 sprintf(unknown_error, "Unknown CR error %lu", cr_error_id);
216 return unknown_error;
218 return cr_errors[cr_error_id];
222 fmt_validate(const char *s, int len, const char *fmt)
226 for (i = 0; i < len; i++)
227 if (!fmt[i] || (fmt[i] == '#' ? !isxdigit(s[i]) : fmt[i] != s[i]))
234 seq_xdigit_validate(const char *s, int mult, int min)
239 if (len < min*mult || len % mult)
242 for (i = 0; i < len; i++)
250 get_device_service_name(struct pci_access *a, DEVINST devinst, DEVINSTID_A devinst_id, BOOL *supported)
252 ULONG reg_type, reg_size, reg_len;
257 * All data are stored as 7-bit ASCII strings in system but service name is
258 * exception. It can contain UNICODE. Moreover it is passed to other Win32 API
259 * functions and therefore it cannot be converted to 8-bit ANSI string without
260 * data loss. So use wide function CM_Get_DevNode_Registry_PropertyW() in this
261 * case and deal with all wchar_t problems...
265 cr = CM_Get_DevNode_Registry_PropertyW(devinst, CM_DRP_SERVICE, ®_type, NULL, ®_size, 0);
266 if (cr == CR_CALL_NOT_IMPLEMENTED)
271 else if (cr == CR_NO_SUCH_VALUE)
276 else if (cr != CR_SUCCESS &&
277 cr != CR_BUFFER_SMALL)
279 a->warning("Cannot retrieve service name for PCI device %s: %s.", devinst_id, cr_strerror(cr));
283 else if (reg_type != REG_SZ)
285 a->warning("Cannot retrieve service name for PCI device %s: Service name is stored as unknown type 0x%lx.", devinst_id, reg_type);
292 * Returned size is on older Windows versions without nul-term char.
293 * So explicitly increase size and fill nul-term byte.
295 reg_size += sizeof(service_name[0]);
296 service_name = pci_malloc(a, reg_size);
298 cr = CM_Get_DevNode_Registry_PropertyW(devinst, CM_DRP_SERVICE, ®_type, service_name, ®_len, 0);
299 service_name[reg_size/sizeof(service_name[0]) - 1] = 0;
300 if (reg_len > reg_size)
302 pci_mfree(service_name);
306 else if (cr != CR_SUCCESS)
308 a->warning("Cannot retrieve service name for PCI device %s: %s.", devinst_id, cr_strerror(cr));
309 pci_mfree(service_name);
313 else if (reg_type != REG_SZ)
315 a->warning("Cannot retrieve service name for PCI device %s: Service name is stored as unknown type 0x%lx.", devinst_id, reg_type);
316 pci_mfree(service_name);
326 get_driver_path_for_service(struct pci_access *a, LPCWSTR service_name, SC_HANDLE manager)
328 UINT (WINAPI *get_system_root_path)(LPWSTR buffer, UINT size) = NULL;
329 DWORD service_config_size, service_config_len;
330 LPQUERY_SERVICE_CONFIGW service_config = NULL;
331 LPWSTR service_image_path = NULL;
332 SERVICE_STATUS service_status;
333 SC_HANDLE service = NULL;
334 char *driver_path = NULL;
335 int trim_system32 = 0;
343 service = OpenServiceW(manager, service_name, SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS);
346 error = GetLastError();
347 if (error != ERROR_SERVICE_DOES_NOT_EXIST)
348 a->warning("Cannot open service %ls with query rights: %s.", service_name, win32_strerror(error));
352 if (!QueryServiceStatus(service, &service_status))
354 error = GetLastError();
355 a->warning("Cannot query status of service %ls: %s.", service_name, win32_strerror(error));
359 if (service_status.dwCurrentState == SERVICE_STOPPED)
362 if (service_status.dwServiceType != SERVICE_KERNEL_DRIVER)
365 if (!QueryServiceConfigW(service, NULL, 0, &service_config_size))
367 error = GetLastError();
368 if (error != ERROR_INSUFFICIENT_BUFFER)
370 a->warning("Cannot query config of service %ls: %s.", service_name, win32_strerror(error));
375 retry_service_config:
376 service_config = pci_malloc(a, service_config_size);
377 if (!QueryServiceConfigW(service, service_config, service_config_size, &service_config_len))
379 error = GetLastError();
380 if (error == ERROR_INSUFFICIENT_BUFFER)
382 pci_mfree(service_config);
383 service_config_size = service_config_len;
384 goto retry_service_config;
386 a->warning("Cannot query config of service %ls: %s.", service_name, win32_strerror(error));
390 if (service_config->dwServiceType != SERVICE_KERNEL_DRIVER)
394 * Despite QueryServiceConfig() is Win32 API, it returns lpBinaryPathName
395 * (ImagePath registry) in NT format. Unfortunately there is no Win32
396 * function for converting NT paths to Win32 paths. So do it manually and
397 * convert this NT format to human-readable Win32 path format.
401 * GetSystemWindowsDirectoryW() returns path to NT SystemRoot namespace.
402 * Alternativelly path to NT SystemRoot namespace can be constructed by
403 * GetSystemDirectoryW() by trimming "\\system32" from the end of path.
404 * GetSystemWindowsDirectoryW() is not provided in old Windows versions,
405 * so use GetProcAddress() for compatibility with all Windows versions.
407 kernel32 = GetModuleHandleW(L"kernel32.dll");
409 get_system_root_path = (void *)GetProcAddress(kernel32, "GetSystemWindowsDirectoryW");
412 get_system_root_path = &GetSystemDirectoryW;
416 if (!service_config->lpBinaryPathName || !service_config->lpBinaryPathName[0])
418 /* No ImagePath is specified, NT kernel assumes implicit kernel driver path by service name, which is relative to "\\system32\\drivers". */
419 /* GetSystemDirectoryW() returns path to "\\system32" directory on all Windows versions. */
420 system32_len = GetSystemDirectoryW(NULL, 0); /* Returns number of WCHARs plus 1 for nul-term. */
421 service_image_path = pci_malloc(a, sizeof(WCHAR) * (system32_len + sizeof("\\drivers\\")-1 + wcslen(service_name) + sizeof(".sys")-1));
422 system32_len = GetSystemDirectoryW(service_image_path, system32_len); /* Now it returns number of WCHARs without nul-term. */
423 if (system32_len && service_image_path[system32_len-1] != L'\\')
424 service_image_path[system32_len++] = L'\\';
425 wcscpy(service_image_path + system32_len, L"drivers\\");
426 wcscpy(service_image_path + system32_len + sizeof("drivers\\")-1, service_name);
427 wcscpy(service_image_path + system32_len + sizeof("drivers\\")-1 + wcslen(service_name), L".sys");
429 else if (wcsncmp(service_config->lpBinaryPathName, L"\\SystemRoot\\", sizeof("\\SystemRoot\\")-1) == 0)
431 /* ImagePath is in NT SystemRoot namespace, convert to Win32 path via GetSystemWindowsDirectoryW()/GetSystemDirectoryW(). */
432 systemroot_len = get_system_root_path(NULL, 0); /* Returns number of WCHARs plus 1 for nul-term. */
433 service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + wcslen(service_config->lpBinaryPathName) - (sizeof("\\SystemRoot")-1)));
434 systemroot_len = get_system_root_path(service_image_path, systemroot_len); /* Now it returns number of WCHARs without nul-term. */
435 if (trim_system32 && systemroot_len && (trim_ptr = wcsrchr(service_image_path, L'\\')) != NULL)
436 systemroot_len = trim_ptr - service_image_path;
437 if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
438 service_image_path[systemroot_len++] = L'\\';
439 wcscpy(service_image_path + systemroot_len, service_config->lpBinaryPathName + sizeof("\\SystemRoot\\")-1);
441 else if (wcsncmp(service_config->lpBinaryPathName, L"\\??\\UNC\\", sizeof("\\??\\UNC\\")-1) == 0 ||
442 wcsncmp(service_config->lpBinaryPathName, L"\\??\\\\UNC\\", sizeof("\\??\\\\UNC\\")-1) == 0)
444 /* ImagePath is in NT UNC namespace, convert to Win32 UNC path via "\\\\" prefix. */
445 service_image_path = pci_malloc(a, sizeof(WCHAR) * (sizeof("\\\\") + wcslen(service_config->lpBinaryPathName) - (sizeof("\\??\\UNC\\")-1)));
446 /* Namespace separator may be single or double backslash. */
447 driver_path_len = sizeof("\\??\\")-1;
448 if (service_config->lpBinaryPathName[driver_path_len] == L'\\')
450 driver_path_len += sizeof("UNC\\")-1;
451 wcscpy(service_image_path, L"\\\\");
452 wcscpy(service_image_path + sizeof("\\\\")-1, service_config->lpBinaryPathName + driver_path_len);
454 else if (wcsncmp(service_config->lpBinaryPathName, L"\\??\\", sizeof("\\??\\")-1) == 0)
456 /* ImagePath is in NT Global?? namespace, root of the Win32 file namespace, so just remove "\\??\\" prefix to get Win32 path. */
457 service_image_path = pci_malloc(a, sizeof(WCHAR) * (wcslen(service_config->lpBinaryPathName) - (sizeof("\\??\\")-1)));
458 /* Namespace separator may be single or double backslash. */
459 driver_path_len = sizeof("\\??\\")-1;
460 if (service_config->lpBinaryPathName[driver_path_len] == L'\\')
462 wcscpy(service_image_path, service_config->lpBinaryPathName + driver_path_len);
464 else if (service_config->lpBinaryPathName[0] != L'\\')
466 /* ImagePath is relative to the NT SystemRoot namespace, convert to Win32 path via GetSystemWindowsDirectoryW()/GetSystemDirectoryW(). */
467 systemroot_len = get_system_root_path(NULL, 0); /* Returns number of WCHARs plus 1 for nul-term. */
468 service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + sizeof("\\")-1 + wcslen(service_config->lpBinaryPathName)));
469 systemroot_len = get_system_root_path(service_image_path, systemroot_len); /* Now it returns number of WCHARs without nul-term. */
470 if (trim_system32 && systemroot_len && (trim_ptr = wcsrchr(service_image_path, L'\\')) != NULL)
471 systemroot_len = trim_ptr - service_image_path;
472 if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
473 service_image_path[systemroot_len++] = L'\\';
474 wcscpy(service_image_path + systemroot_len, service_config->lpBinaryPathName);
478 /* 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. */
479 service_image_path = pci_malloc(a, sizeof(WCHAR) * wcslen(service_config->lpBinaryPathName));
480 wcscpy(service_image_path, service_config->lpBinaryPathName);
483 /* Calculate len of buffer needed for conversion from LPWSTR to char*. */
484 driver_path_len = WideCharToMultiByte(CP_ACP, 0, service_image_path, -1, NULL, 0, NULL, NULL);
485 if (driver_path_len <= 0)
487 error = GetLastError();
488 a->warning("Cannot convert kernel driver path from wide string to 8-bit string: %s.", win32_strerror(error));
492 driver_path = pci_malloc(a, driver_path_len);
493 driver_path_len = WideCharToMultiByte(CP_ACP, 0, service_image_path, -1, driver_path, driver_path_len, NULL, NULL);
494 if (driver_path_len <= 0)
496 error = GetLastError();
497 a->warning("Cannot convert kernel driver path from wide string to 8-bit string: %s.", win32_strerror(error));
498 pci_mfree(driver_path);
504 if (service_image_path)
505 pci_mfree(service_image_path);
507 pci_mfree(service_config);
509 CloseServiceHandle(service);
514 get_device_driver_devreg(struct pci_access *a, DEVINST devinst, DEVINSTID_A devinst_id)
519 cr = CM_Open_DevNode_Key(devinst, KEY_READ, 0, RegDisposition_OpenExisting, &key, CM_REGISTRY_SOFTWARE);
520 if (cr != CR_SUCCESS)
522 if (cr != CR_NO_SUCH_VALUE)
523 a->warning("Cannot retrieve driver key for device %s: %s.", devinst_id, cr_strerror(cr));
531 read_reg_key_string_value(struct pci_access *a, HKEY key, const char *name, DWORD *unkn_reg_type)
533 DWORD reg_type, reg_size, reg_len;
538 error = RegQueryValueExA(key, name, NULL, ®_type, NULL, ®_size);
539 if (error != ERROR_SUCCESS &&
540 error != ERROR_MORE_DATA)
545 else if (reg_type != REG_SZ)
548 *unkn_reg_type = reg_type;
553 value = pci_malloc(a, reg_size + 1);
555 error = RegQueryValueExA(key, name, NULL, ®_type, (PBYTE)value, ®_len);
556 if (error != ERROR_SUCCESS)
559 if (error == ERROR_MORE_DATA)
567 else if (reg_type != REG_SZ)
571 *unkn_reg_type = reg_type;
574 value[reg_len] = '\0';
580 driver_cmp(const char *driver, const char *match)
582 int len = strlen(driver);
583 if (driver[0] == '*')
585 if (len >= 4 && strcasecmp(driver + len - 4, ".vxd") == 0)
587 return strncasecmp(driver, match, len);
591 get_driver_path_for_regkey(struct pci_access *a, DEVINSTID_A devinst_id, HKEY key)
593 char *driver_list, *driver, *driver_next;
594 char *subdriver, *subname;
605 driver_list = read_reg_key_string_value(a, key, "DevLoader", &unkn_reg_type);
608 error = GetLastError();
610 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);
611 else if (error != ERROR_FILE_NOT_FOUND)
612 a->warning("Cannot read driver DevLoader key for PCI device %s: %s.", devinst_id, win32_strerror(error));
617 driver = driver_list;
620 driver_next = strchr(driver, ',');
622 *(driver_next++) = '\0';
624 if (driver_cmp(driver, "ios") == 0 ||
625 driver_cmp(driver, "vcomm") == 0)
626 subname = "PortDriver";
627 else if (driver_cmp(driver, "ntkern") == 0)
628 subname = "NTMPDriver";
629 else if (driver_cmp(driver, "ndis") == 0)
630 subname = "DeviceVxDs";
631 else if (driver_cmp(driver, "vdd") == 0)
637 if (subname && strcmp(subname, "minivdd") == 0)
639 error = RegOpenKeyA(key, "Default", &subkey);
640 if (error != ERROR_SUCCESS)
642 a->warning("Cannot open driver subkey Default for PCI device %s: %s.", devinst_id, win32_strerror(error));
653 subdriver = read_reg_key_string_value(a, subkey, subname, &unkn_reg_type);
656 error = GetLastError();
658 a->warning("Cannot read driver %s key for PCI device %s: %s key is stored as unknown type 0x%lx.", subname, devinst_id, subname, unkn_reg_type);
659 else if (error != ERROR_FILE_NOT_FOUND)
660 a->warning("Cannot read driver %s key for PCI device %s: %s.", subname, devinst_id, win32_strerror(error));
661 else if (strcmp(subname, "minivdd") == 0)
666 else if (strcmp(subname, "drv") == 0)
678 char *endptr = strchr(subdriver, ',');
685 driver = driver_next;
688 if (subdriver && subdriver[0])
689 driver_ptr = subdriver;
695 if (driver_ptr && driver_ptr[0] == '*')
706 len = driver_ptr ? strlen(driver_ptr) : 0;
707 noext = driver_ptr && (len < 4 || driver_ptr[len-4] != '.');
713 if (tolower(driver_ptr[0]) >= 'a' && tolower(driver_ptr[0]) <= 'z' && driver_ptr[1] == ':')
715 /* Driver is already with absolute path. */
716 driver_path = pci_strdup(a, driver_ptr);
718 else if (driver_cmp(driver, "ntkern") == 0 && subdriver)
720 /* Driver is relative to system32\drivers\ directory which is relative to windows directory. */
721 systemdir_len = GetWindowsDirectoryA(NULL, 0);
722 driver_path = pci_malloc(a, systemdir_len + 1 + sizeof("system32\\drivers\\")-1 + strlen(driver_ptr) + 4 + 1);
723 systemdir_len = GetWindowsDirectoryA(driver_path, systemdir_len + 1);
724 if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
725 driver_path[systemdir_len++] = '\\';
726 sprintf(driver_path + systemdir_len, "system32\\drivers\\%s%s", driver_ptr, noext ? ".sys" : "");
730 /* Driver is packed in vmm32.vxd which is stored in system directory. */
731 systemdir_len = GetSystemDirectoryA(NULL, 0);
732 driver_path = pci_malloc(a, systemdir_len + 1 + sizeof("vmm32.vxd ()")-1 + strlen(driver_ptr) + 4 + 1);
733 systemdir_len = GetSystemDirectoryA(driver_path, systemdir_len + 1);
734 if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
735 driver_path[systemdir_len++] = '\\';
736 sprintf(driver_path + systemdir_len, "vmm32.vxd (%s%s)", driver_ptr, noext ? ".vxd" : "");
740 /* Otherwise driver is relative to system directory. */
741 systemdir_len = GetSystemDirectoryA(NULL, 0);
742 driver_path = pci_malloc(a, systemdir_len + 1 + strlen(driver_ptr) + 4 + 1);
743 systemdir_len = GetSystemDirectoryA(driver_path, systemdir_len + 1);
744 if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
745 driver_path[systemdir_len++] = '\\';
746 sprintf(driver_path + systemdir_len, "%s%s", driver_ptr, noext ? ".vxd" : "");
751 pci_mfree(subdriver);
752 pci_mfree(driver_list);
757 get_device_driver_path(struct pci_dev *d, SC_HANDLE manager, BOOL manager_supported)
759 struct pci_access *a = d->access;
760 BOOL service_supported = TRUE;
761 DEVINSTID_A devinst_id = NULL;
762 LPWSTR service_name = NULL;
763 ULONG devinst_id_len = 0;
764 char *driver_path = NULL;
765 DEVINST devinst = (DEVINST)d->backend_data;
770 if (CM_Get_DevNode_Status(&status, &problem, devinst, 0) != CR_SUCCESS || !(status & DN_DRIVER_LOADED))
773 if (CM_Get_Device_ID_Size(&devinst_id_len, devinst, 0) == CR_SUCCESS)
775 devinst_id = pci_malloc(a, devinst_id_len + 1);
776 if (CM_Get_Device_IDA(devinst, devinst_id, devinst_id_len + 1, 0) != CR_SUCCESS)
778 pci_mfree(devinst_id);
779 devinst_id = pci_strdup(a, "UNKNOWN");
783 devinst_id = pci_strdup(a, "UNKNOWN");
785 service_name = get_device_service_name(d->access, devinst, devinst_id, &service_supported);
786 if ((!service_name || !manager) && service_supported && manager_supported)
788 else if (service_name && manager)
790 driver_path = get_driver_path_for_service(d->access, service_name, manager);
794 key = get_device_driver_devreg(d->access, devinst, devinst_id);
797 driver_path = get_driver_path_for_regkey(d->access, devinst_id, key);
805 pci_mfree(service_name);
806 pci_mfree(devinst_id);
811 fill_drivers(struct pci_access *a)
813 BOOL manager_supported;
819 /* ERROR_CALL_NOT_IMPLEMENTED is returned on systems without Service Manager support. */
820 manager_supported = TRUE;
821 manager = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
824 error = GetLastError();
825 if (error != ERROR_CALL_NOT_IMPLEMENTED)
826 a->warning("Cannot open Service Manager with connect right: %s.", win32_strerror(error));
828 manager_supported = FALSE;
831 for (d = a->devices; d; d = d->next)
833 driver = get_device_driver_path(d, manager, manager_supported);
836 pci_set_property(d, PCI_FILL_DRIVER, driver);
839 d->known_fields |= PCI_FILL_DRIVER;
843 CloseServiceHandle(manager);
847 res_id_to_str(RESOURCEID res_id)
849 static char hex_res_id[sizeof("0xffffffff")];
851 if (res_id == ResType_IO)
853 else if (res_id == ResType_Mem)
855 else if (res_id == ResType_IRQ)
858 sprintf(hex_res_id, "0x%lx", res_id);
863 fill_resources(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
865 struct pci_access *a = d->access;
873 RES_DES prev_res_des;
882 int last_shared_irq = -1;
884 cr = CM_Get_DevNode_Status(&status, &problem, devinst, 0);
885 if (cr != CR_SUCCESS)
887 a->warning("Cannot retrieve status of PCI device %s: %s.", devinst_id, cr_strerror(cr));
891 cr = CR_NO_MORE_LOG_CONF;
894 * If the device is running then retrieve allocated configuration by PnP
895 * manager which is currently in use by a device.
897 if (!(status & DN_HAS_PROBLEM))
898 cr = CM_Get_First_Log_Conf(&config, devinst, ALLOC_LOG_CONF);
901 * If the device is not running or it does not have allocated configuration by
902 * PnP manager then retrieve forced configuration which prevents PnP manager
903 * from assigning resources.
905 if (cr == CR_NO_MORE_LOG_CONF)
906 cr = CM_Get_First_Log_Conf(&config, devinst, FORCED_LOG_CONF);
909 * If the device does not have neither allocated configuration by PnP manager
910 * nor forced configuration and it is not disabled in the BIOS then retrieve
911 * boot configuration supplied by the BIOS.
913 if (cr == CR_NO_MORE_LOG_CONF &&
914 (!(status & DN_HAS_PROBLEM) || problem != CM_PROB_HARDWARE_DISABLED))
915 cr = CM_Get_First_Log_Conf(&config, devinst, BOOT_LOG_CONF);
917 if (cr != CR_SUCCESS)
920 * Note: Starting with Windows 8, CM_Get_First_Log_Conf returns
921 * CR_CALL_NOT_IMPLEMENTED when used in a Wow64 scenario.
922 * To request information about the hardware resources on a local machine
923 * it is necessary implement an architecture-native version of the
924 * application using the hardware resource APIs. For example: An AMD64
925 * application for AMD64 systems.
927 if (cr == CR_CALL_NOT_IMPLEMENTED && win32_is_32bit_on_win8_64bit_system())
929 static BOOL warn_once = FALSE;
933 a->warning("Cannot retrieve resources of PCI devices from 32-bit application on 64-bit system.");
936 else if (cr != CR_NO_MORE_LOG_CONF)
937 a->warning("Cannot retrieve resources of PCI device %s: %s.", devinst_id, cr_strerror(cr));
942 non_nt_system = win32_is_non_nt_system();
949 ULONG child_name_len;
953 if (CM_Get_Child(&child, devinst, 0) != CR_SUCCESS)
955 else if (CM_Get_Device_ID_Size(&child_name_len, child, 0) != CR_SUCCESS)
960 child_name = pci_malloc(a, child_name_len);
961 if (CM_Get_Device_IDA(child, child_name, child_name_len, 0) != CR_SUCCESS)
963 else if (strncmp(child_name, "PCI\\", 4) != 0)
967 pci_mfree(child_name);
970 if (has_child || d->device_class == PCI_CLASS_BRIDGE_PCI || d->device_class == PCI_CLASS_BRIDGE_CARDBUS)
979 prev_res_des = (RES_DES)config;
980 while ((cr = CM_Get_Next_Res_Des(&res_des, prev_res_des, ResType_All, &res_id, 0)) == CR_SUCCESS)
982 pciaddr_t start, end, size, flags;
983 ULONG res_des_data_size;
986 if (prev_res_des != config)
987 CM_Free_Res_Des_Handle(prev_res_des);
989 prev_res_des = res_des;
991 /* Skip other resources early */
992 if (res_id != ResType_IO && res_id != ResType_Mem && res_id != ResType_IRQ)
995 cr = CM_Get_Res_Des_Data_Size(&res_des_data_size, res_des, 0);
996 if (cr != CR_SUCCESS)
998 a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, cr_strerror(cr));
1002 if (!res_des_data_size)
1004 a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, "Empty data");
1008 res_des_data = pci_malloc(a, res_des_data_size);
1009 cr = CM_Get_Res_Des_Data(res_des, res_des_data, res_des_data_size, 0);
1010 if (cr != CR_SUCCESS)
1012 a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, cr_strerror(cr));
1013 pci_mfree(res_des_data);
1018 * There can be more resources with the same id. In this case we are
1019 * interested in the last one in the list as at the beginning of the list
1020 * can be some virtual resources (which are not set in PCI config space).
1023 if (res_id == ResType_IO)
1025 PIO_RESOURCE io_data = (PIO_RESOURCE)res_des_data;
1027 start = io_data->IO_Header.IOD_Alloc_Base;
1028 end = io_data->IO_Header.IOD_Alloc_End;
1029 size = (end > start) ? (end - start + 1) : 0;
1030 flags = PCI_IORESOURCE_IO;
1033 * If neither 10-bit, 12-bit, nor 16-bit support is presented then
1034 * expects that this is 32-bit I/O resource. If resource does not fit
1035 * into 16-bit space then it must be 32-bit. If PCI I/O resource is
1036 * not 32-bit then it is 16-bit.
1038 if (end <= 0xffff && (io_data->IO_Header.IOD_DesFlags & (fIOD_10_BIT_DECODE|fIOD_12_BIT_DECODE|fIOD_16_BIT_DECODE)))
1039 flags |= PCI_IORESOURCE_IO_16BIT_ADDR;
1042 * 16/32-bit non-NT systems do not support these two flags.
1043 * Most NT-based Windows versions support only the fIOD_WINDOW_DECODE
1044 * flag and put all BAR resources before window resources in this
1045 * resource list. So use this fIOD_WINDOW_DECODE flag as separator
1046 * between IO/MEM windows and IO/MEM BARs of PCI Bridges.
1048 if (io_data->IO_Header.IOD_DesFlags & fIOD_WINDOW_DECODE)
1050 else if (io_data->IO_Header.IOD_DesFlags & fIOD_PORT_BAR)
1053 if (is_bar_res && bar_res_count < 6)
1055 d->flags[bar_res_count] = flags;
1056 d->base_addr[bar_res_count] = start;
1057 d->size[bar_res_count] = size;
1060 else if (!is_bar_res)
1062 d->bridge_flags[0] = flags;
1063 d->bridge_base_addr[0] = start;
1064 d->bridge_size[0] = size;
1065 d->known_fields |= PCI_FILL_BRIDGE_BASES;
1068 else if (res_id == ResType_Mem)
1070 PMEM_RESOURCE mem_data = (PMEM_RESOURCE)res_des_data;
1072 start = mem_data->MEM_Header.MD_Alloc_Base;
1073 end = mem_data->MEM_Header.MD_Alloc_End;
1074 size = (end > start) ? (end - start + 1) : 0;
1075 flags = PCI_IORESOURCE_MEM;
1078 * If fMD_PrefetchAllowed flag is set then this is
1079 * PCI Prefetchable Memory resource.
1081 if ((mem_data->MEM_Header.MD_Flags & mMD_Prefetchable) == fMD_PrefetchAllowed)
1082 flags |= PCI_IORESOURCE_PREFETCH;
1084 /* If resource does not fit into 32-bit space then it must be 64-bit. */
1085 if (is_bar_res && end > 0xffffffff)
1086 flags |= PCI_IORESOURCE_MEM_64;
1089 * These two flags (fMD_WINDOW_DECODE and fMD_MEMORY_BAR) are
1090 * unsupported on most Windows versions, so distinguish between
1091 * window and BAR based on previous resource type.
1093 if (mem_data->MEM_Header.MD_Flags & fMD_WINDOW_DECODE)
1095 else if (mem_data->MEM_Header.MD_Flags & fMD_MEMORY_BAR)
1098 /* 64-bit BAR resource must be at even position. */
1099 if (is_bar_res && (flags & PCI_IORESOURCE_MEM_64) && bar_res_count % 2)
1102 if (is_bar_res && bar_res_count < 6)
1104 d->flags[bar_res_count] = flags;
1105 d->base_addr[bar_res_count] = start;
1106 d->size[bar_res_count] = size;
1108 /* 64-bit BAR resource occupies two slots. */
1109 if (flags & PCI_IORESOURCE_MEM_64)
1112 else if (!is_bar_res && !(flags & PCI_IORESOURCE_PREFETCH))
1114 d->bridge_flags[1] = flags;
1115 d->bridge_base_addr[1] = start;
1116 d->bridge_size[1] = size;
1117 d->known_fields |= PCI_FILL_BRIDGE_BASES;
1119 else if (!is_bar_res && (flags & PCI_IORESOURCE_PREFETCH))
1121 d->bridge_flags[2] = flags;
1122 d->bridge_base_addr[2] = start;
1123 d->bridge_size[2] = size;
1124 d->known_fields |= PCI_FILL_BRIDGE_BASES;
1127 else if (res_id == ResType_IRQ)
1129 PIRQ_RESOURCE irq_data = (PIRQ_RESOURCE)res_des_data;
1132 * libpci's d->irq should be set to the non-MSI PCI IRQ and therefore
1133 * it should be level IRQ which may be shared with other PCI devices
1134 * and drivers in the system. As always we want to retrieve the last
1135 * IRQ number from the resource list.
1137 * On 16/32-bit non-NT systems is fIRQD_Level set to 2 but on NT
1138 * systems to 0. Moreover it looks like that different PCI drivers
1139 * on both NT and non-NT systems set bits 0 and 1 to wrong values
1140 * and so reported value in this list may be incorrect.
1142 * Therefore take the last level-shared IRQ number from the resource
1143 * list and if there is none of this type then take the last IRQ
1144 * number from the list.
1146 last_irq = irq_data->IRQ_Header.IRQD_Alloc_Num;
1147 if ((irq_data->IRQ_Header.IRQD_Flags & (mIRQD_Share|mIRQD_Edge_Level)) == (fIRQD_Share|fIRQD_Level))
1148 last_shared_irq = irq_data->IRQ_Header.IRQD_Alloc_Num;
1151 * IRQ resource on 16/32-bit non-NT systems is separator between
1152 * IO/MEM windows and IO/MEM BARs of PCI Bridges. After the IRQ
1153 * resource are IO/MEM BAR resources.
1155 if (!is_bar_res && non_nt_system)
1159 pci_mfree(res_des_data);
1161 if (cr != CR_NO_MORE_RES_DES)
1162 a->warning("Cannot retrieve resources of PCI device %s: %s.", devinst_id, cr_strerror(cr));
1164 if (prev_res_des != config)
1165 CM_Free_Res_Des_Handle(prev_res_des);
1167 CM_Free_Log_Conf_Handle(config);
1169 /* Set the last IRQ from the resource list to pci_dev. */
1170 if (last_shared_irq >= 0)
1171 d->irq = last_shared_irq;
1172 else if (last_irq >= 0)
1174 if (last_shared_irq >= 0 || last_irq >= 0)
1175 d->known_fields |= PCI_FILL_IRQ;
1177 if (bar_res_count > 0)
1178 d->known_fields |= PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS;
1182 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)
1184 ULONG reg_type, reg_len;
1186 BOOL have_bus, have_devfunc;
1187 DWORD drp_bus_num, drp_address;
1191 have_devfunc = FALSE;
1194 * DRP_BUSNUMBER consists of PCI domain number in high 24 bits
1195 * and PCI bus number in low 8 bits.
1197 reg_len = sizeof(drp_bus_num);
1198 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_BUSNUMBER, ®_type, &drp_bus_num, ®_len, 0);
1199 if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_bus_num))
1201 *domain = drp_bus_num >> 8;
1202 *bus = drp_bus_num & 0xff;
1207 * DRP_ADDRESS consists of PCI device number in high 16 bits
1208 * and PCI function number in low 16 bits.
1210 reg_len = sizeof(drp_address);
1211 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_ADDRESS, ®_type, &drp_address, ®_len, 0);
1212 if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_address))
1214 *dev = drp_address >> 16;
1215 *func = drp_address & 0xffff;
1216 have_devfunc = TRUE;
1220 * Device Instance Id for PCI devices is of format:
1221 * "<enumerator>\\<device_id>\\<instance_id>"
1223 * "<enumerator>" is "PCI"
1224 * "<device_id>" is "VEN_####&DEV_####&SUBSYS_########&REV_##"
1225 * and "<instance_id>" for PCI devices is at least in one of following format:
1226 * "BUS_##&DEV_##&FUNC_##"
1227 * "##.." (sequence of devfn hex bytes, where bytes represents tree path to the root)
1228 * "#..&#..&#..&#.." (four hex numbers separated by "&"; meaning is unknown yet)
1230 * First two formats are used only on systems without support for multiple
1231 * domains. The second format uses intel-conf encoding of device and function
1232 * number: Low 3 bits is function number and high 5 bits is device number.
1233 * Bus number is not really encoded in second format!
1235 * The third format is used on systems with support for multiple domains but
1236 * format is variable length and currently its meaning is unknown. Apparently
1237 * it looks like that DRP_BUSNUMBER and DRP_ADDRESS registry properties are
1238 * supported on these systems.
1240 * If DRP_BUSNUMBER or DRP_ADDRESS failed then try to parse PCI bus, device
1241 * and function numbers from Instance Id part.
1243 if (!have_bus || !have_devfunc)
1245 const char *device_id0 = strchr(devinst_id, '\\');
1246 const char *instance_id0 = device_id0 ? strchr(device_id0 + 1, '\\') : NULL;
1247 const char *instance_id = instance_id0 ? instance_id0 + 1 : NULL;
1252 if (fmt_validate(instance_id, strlen(instance_id), "BUS_##&DEV_##&FUNC_##") &&
1253 sscanf(instance_id, "BUS_%x&DEV_%x&FUNC_%x", bus, dev, func) == 3)
1256 have_devfunc = TRUE;
1258 else if (seq_xdigit_validate(instance_id, 2, 2) &&
1259 sscanf(instance_id, "%2x", &devfn) == 1)
1262 *func = devfn & 0x7;
1263 have_devfunc = TRUE;
1269 * Virtual IRQ holder devices do not have assigned any bus/dev/func number and
1270 * have "IRQHOLDER" in their Device Id part. So skip them.
1272 if (!have_bus && !have_devfunc && strncmp(devinst_id, "PCI\\IRQHOLDER\\", 14) == 0)
1276 * When some numbers cannot be retrieved via cfgmgr32 then set them to zeros
1277 * to have structure initialized. It makes sense to report via libpci also
1278 * such "incomplete" device as cfgmgr32 can provide additional information
1279 * like device/vendor ids or assigned resources.
1281 if (!have_bus && !have_devfunc)
1283 *bus = *dev = *func = 0;
1284 a->warning("Cannot retrieve bus, device and function numbers for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1289 a->warning("Cannot retrieve bus number for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1291 else if (!have_devfunc)
1294 a->warning("Cannot retrieve device and function numbers for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1301 fill_data_from_string(struct pci_dev *d, const char *str)
1303 BOOL have_device_id;
1304 BOOL have_vendor_id;
1307 const char *endptr, *endptr2;
1311 have_device_id = have_vendor_id = (d->known_fields & PCI_FILL_IDENT);
1312 have_prog_if = have_rev_id = (d->known_fields & PCI_FILL_CLASS_EXT);
1316 endptr = strchr(str, '&');
1317 endptr2 = strchr(str, '\\');
1318 if (endptr2 && (!endptr || endptr > endptr2))
1320 len = endptr ? endptr-str : (int)strlen(str);
1322 if (!have_vendor_id &&
1323 fmt_validate(str, len, "VEN_####") &&
1324 sscanf(str, "VEN_%x", &hex) == 1)
1327 have_vendor_id = TRUE;
1329 else if (!have_device_id &&
1330 fmt_validate(str, len, "DEV_####") &&
1331 sscanf(str, "DEV_%x", &hex) == 1)
1334 have_device_id = TRUE;
1336 else if (!(d->known_fields & PCI_FILL_SUBSYS) &&
1337 fmt_validate(str, len, "SUBSYS_########") &&
1338 sscanf(str, "SUBSYS_%x", &hex) == 1)
1340 d->subsys_vendor_id = hex & 0xffff;
1341 d->subsys_id = hex >> 16;
1342 d->known_fields |= PCI_FILL_SUBSYS;
1344 else if (!have_rev_id &&
1345 fmt_validate(str, len, "REV_##") &&
1346 sscanf(str, "REV_%x", &hex) == 1)
1351 else if (!((d->known_fields & PCI_FILL_CLASS) && have_prog_if) &&
1352 (fmt_validate(str, len, "CC_####") || fmt_validate(str, len, "CC_######")) &&
1353 sscanf(str, "CC_%x", &hex) == 1)
1359 d->prog_if = hex & 0xff;
1360 have_prog_if = TRUE;
1364 if (!(d->known_fields & PCI_FILL_CLASS))
1366 d->device_class = hex;
1367 d->known_fields |= PCI_FILL_CLASS;
1371 if (!endptr || endptr == endptr2)
1377 if ((have_device_id || d->device_id) && (have_vendor_id || d->vendor_id))
1378 d->known_fields |= PCI_FILL_IDENT;
1380 if ((have_prog_if || d->prog_if) && (have_rev_id || d->rev_id))
1381 d->known_fields |= PCI_FILL_CLASS_EXT;
1385 fill_data_from_devinst_id(struct pci_dev *d, DEVINSTID_A devinst_id)
1387 const char *device_id;
1389 device_id = strchr(devinst_id, '\\');
1395 * Device Id part of Device Instance Id is in format:
1396 * "VEN_####&DEV_####&SUBSYS_########&REV_##"
1398 fill_data_from_string(d, device_id);
1402 fill_data_from_hardware_ids(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
1404 ULONG reg_type, reg_size, reg_len;
1405 struct pci_access *a = d->access;
1406 char *hardware_ids = NULL;
1411 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, ®_type, NULL, ®_size, 0);
1412 if (cr != CR_SUCCESS && cr != CR_BUFFER_SMALL)
1414 a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1417 else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1419 a->warning("Cannot retrieve hardware ids for PCI device %s: Hardware ids are stored as unknown type 0x%lx.", devinst_id, reg_type);
1425 * Returned size is on older Windows versions without nul-term char.
1426 * So explicitly increase size and fill nul-term byte.
1429 hardware_ids = pci_malloc(a, reg_size);
1431 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, ®_type, hardware_ids, ®_len, 0);
1432 hardware_ids[reg_size - 1] = 0;
1433 if (reg_len > reg_size)
1435 pci_mfree(hardware_ids);
1439 else if (cr != CR_SUCCESS)
1441 a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1442 pci_mfree(hardware_ids);
1445 else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1447 a->warning("Cannot retrieve hardware ids for PCI device %s: Hardware ids are stored as unknown type 0x%lx.", devinst_id, reg_type);
1448 pci_mfree(hardware_ids);
1453 * Hardware ids is nul-separated nul-term string list where each string has
1454 * one of the following format:
1455 * "PCI\\VEN_####&DEV_####&SUBSYS_########&REV_##"
1456 * "PCI\\VEN_####&DEV_####&SUBSYS_########"
1457 * "PCI\\VEN_####&DEV_####&REV_##&CC_####"
1458 * "PCI\\VEN_####&DEV_####&CC_######"
1459 * "PCI\\VEN_####&DEV_####&CC_####"
1460 * "PCI\\VEN_####&DEV_####&REV_##"
1461 * "PCI\\VEN_####&DEV_####"
1463 for (str = hardware_ids; *str != '\0'; str += strlen(str) + 1)
1465 if (strncmp(str, "PCI\\", 4) != 0)
1468 fill_data_from_string(d, str);
1471 pci_mfree(hardware_ids);
1475 scan_devinst_id(struct pci_access *a, DEVINSTID_A devinst_id)
1477 unsigned int domain, bus, dev, func;
1482 cr = CM_Locate_DevNodeA(&devinst, devinst_id, CM_LOCATE_DEVNODE_NORMAL);
1483 if (cr != CR_SUCCESS)
1485 /* Do not show warning when device is not present (= does not match NORMAL flag). */
1486 if (cr != CR_NO_SUCH_DEVNODE)
1487 a->warning("Cannot retrieve handle for device %s: %s.", devinst_id, cr_strerror(cr));
1491 /* get_device_location() returns FALSE if devinst is not real PCI device. */
1492 if (!get_device_location(a, devinst, devinst_id, &domain, &bus, &dev, &func))
1495 d = pci_get_dev(a, domain, bus, dev, func);
1497 if (!d->access->backend_data)
1498 d->no_config_access = 1;
1499 d->backend_data = (void *)devinst;
1501 /* Parse device id part of devinst id and fill details into pci_dev. */
1503 fill_data_from_devinst_id(d, devinst_id);
1505 /* Retrieve hardware ids of devinst, parse them and fill details into pci_dev. */
1507 fill_data_from_hardware_ids(d, devinst, devinst_id);
1510 fill_resources(d, devinst, devinst_id);
1513 * Set parent field to cfgmgr32 parent devinst handle and backend_data field to current
1514 * devinst handle. At later stage in win32_cfgmgr32_scan() when all pci_dev
1515 * devices are linked, change every devinst handle by pci_dev.
1519 DEVINST parent_devinst;
1520 if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS)
1523 a->warning("Cannot retrieve parent handle for device %s: %s.", devinst_id, cr_strerror(cr));
1525 d->parent = (void *)parent_devinst;
1530 win32_cfgmgr32_scan(struct pci_access *a)
1532 ULONG devinst_id_list_size;
1533 PCHAR devinst_id_list;
1534 DEVINSTID_A devinst_id;
1538 if (!resolve_cfgmgr32_functions())
1540 a->warning("Required cfgmgr32.dll functions are unavailable.");
1545 * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1546 * support this API but returns CR_SUCCESS without touching size argument.
1548 devinst_id_list_size = 0;
1549 cr = CM_Get_Device_ID_List_SizeA(&devinst_id_list_size, "PCI", CM_GETIDLIST_FILTER_ENUMERATOR);
1550 if (cr != CR_SUCCESS)
1552 a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1555 else if (devinst_id_list_size <= 1)
1557 a->warning("Cannot retrieve list of PCI devices: No device was found.");
1561 devinst_id_list = pci_malloc(a, devinst_id_list_size);
1562 cr = CM_Get_Device_ID_ListA("PCI", devinst_id_list, devinst_id_list_size, CM_GETIDLIST_FILTER_ENUMERATOR);
1563 if (cr != CR_SUCCESS)
1565 a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1566 pci_mfree(devinst_id_list);
1570 /* Register pci_dev for each cfgmgr32 devinst handle. */
1571 for (devinst_id = devinst_id_list; *devinst_id; devinst_id += strlen(devinst_id) + 1)
1572 scan_devinst_id(a, devinst_id);
1574 /* Fill all drivers. */
1578 /* Switch parent fields from cfgmgr32 devinst handle to pci_dev. */
1581 struct pci_dev *d1, *d2;
1582 for (d1 = a->devices; d1; d1 = d1->next)
1584 for (d2 = a->devices; d2; d2 = d2->next)
1585 if ((DEVINST)d1->parent == (DEVINST)d2->backend_data)
1589 d1->known_fields |= PCI_FILL_PARENT;
1593 /* devinst stored in ->backend_data is not needed anymore, clear it. */
1594 for (d = a->devices; d; d = d->next)
1595 d->backend_data = NULL;
1597 pci_mfree(devinst_id_list);
1601 win32_cfgmgr32_config(struct pci_access *a)
1603 pci_define_param(a, "win32.cfgmethod", "auto", "PCI config space access method");
1607 win32_cfgmgr32_detect(struct pci_access *a)
1609 ULONG devinst_id_list_size;
1612 if (!resolve_cfgmgr32_functions())
1614 a->debug("Required cfgmgr32.dll functions are unavailable.");
1619 * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1620 * support this API but returns CR_SUCCESS without touching size argument.
1622 devinst_id_list_size = 0;
1623 cr = CM_Get_Device_ID_List_SizeA(&devinst_id_list_size, "PCI", CM_GETIDLIST_FILTER_ENUMERATOR);
1624 if (cr != CR_SUCCESS)
1626 a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): %s.", cr_strerror(cr));
1629 else if (devinst_id_list_size <= 1)
1631 a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): No device was found.");
1639 win32_cfgmgr32_fill_info(struct pci_dev *d, unsigned int flags)
1642 * All available flags were filled by win32_cfgmgr32_scan().
1643 * Filling more flags is possible only from config space.
1645 if (!d->access->backend_data)
1648 pci_generic_fill_info(d, flags);
1652 win32_cfgmgr32_read(struct pci_dev *d, int pos, byte *buf, int len)
1654 struct pci_access *a = d->access;
1655 struct pci_access *acfg = a->backend_data;
1656 struct pci_dev *dcfg = d->backend_data;
1659 return pci_emulated_read(d, pos, buf, len);
1662 d->backend_data = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
1664 return pci_read_block(dcfg, pos, buf, len);
1668 win32_cfgmgr32_write(struct pci_dev *d, int pos, byte *buf, int len)
1670 struct pci_access *a = d->access;
1671 struct pci_access *acfg = a->backend_data;
1672 struct pci_dev *dcfg = d->backend_data;
1678 d->backend_data = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
1680 return pci_write_block(dcfg, pos, buf, len);
1684 win32_cfgmgr32_cleanup_dev(struct pci_dev *d)
1686 struct pci_dev *dcfg = d->backend_data;
1693 win32_cfgmgr32_init(struct pci_access *a)
1695 char *cfgmethod = pci_get_param(a, "win32.cfgmethod");
1696 struct pci_access *acfg;
1698 if (strcmp(cfgmethod, "") == 0 ||
1699 strcmp(cfgmethod, "auto") == 0)
1701 acfg = pci_clone_access(a);
1702 acfg->method = PCI_ACCESS_AUTO;
1704 else if (strcmp(cfgmethod, "none") == 0 ||
1705 strcmp(cfgmethod, "win32-cfgmgr32") == 0)
1708 a->error("Write access requested but option win32.cfgmethod was not set.");
1713 int m = pci_lookup_method(cfgmethod);
1715 a->error("Option win32.cfgmethod is set to an unknown access method \"%s\".", cfgmethod);
1716 acfg = pci_clone_access(a);
1720 a->debug("Loading config space access method...\n");
1721 if (!pci_init_internal(acfg, PCI_ACCESS_WIN32_CFGMGR32))
1724 a->debug("Cannot find any working config space access method.\n");
1726 a->error("Write access requested but no usable access method found.");
1730 a->backend_data = acfg;
1734 win32_cfgmgr32_cleanup(struct pci_access *a)
1736 struct pci_access *acfg = a->backend_data;
1742 struct pci_methods pm_win32_cfgmgr32 = {
1744 "Win32 device listing via Configuration Manager",
1745 win32_cfgmgr32_config,
1746 win32_cfgmgr32_detect,
1747 win32_cfgmgr32_init,
1748 win32_cfgmgr32_cleanup,
1749 win32_cfgmgr32_scan,
1750 win32_cfgmgr32_fill_info,
1751 win32_cfgmgr32_read,
1752 win32_cfgmgr32_write,
1753 NULL, /* read_vpd */
1754 NULL, /* init_dev */
1755 win32_cfgmgr32_cleanup_dev,