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
85 * Unfortunately MinGW32 toolchain does not provide import library for these
86 * cfgmgr32.dll functions. So resolve pointers to these functions at runtime.
89 #ifdef CM_Get_DevNode_Registry_PropertyA
90 #undef CM_Get_DevNode_Registry_PropertyA
92 static CONFIGRET (WINAPI *MyCM_Get_DevNode_Registry_PropertyA)(DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType, PVOID Buffer, PULONG pulLength, ULONG ulFlags);
93 #define CM_Get_DevNode_Registry_PropertyA MyCM_Get_DevNode_Registry_PropertyA
95 #ifdef CM_Get_DevNode_Registry_PropertyW
96 #undef CM_Get_DevNode_Registry_PropertyW
98 static CONFIGRET (WINAPI *MyCM_Get_DevNode_Registry_PropertyW)(DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType, PVOID Buffer, PULONG pulLength, ULONG ulFlags);
99 #define CM_Get_DevNode_Registry_PropertyW MyCM_Get_DevNode_Registry_PropertyW
101 #ifndef CM_Open_DevNode_Key
102 #undef CM_Open_DevNode_Key
104 static CONFIGRET (WINAPI *MyCM_Open_DevNode_Key)(DEVINST dnDevNode, REGSAM samDesired, ULONG ulHardwareProfile, REGDISPOSITION Disposition, PHKEY phkDevice, ULONG ulFlags);
105 #define CM_Open_DevNode_Key MyCM_Open_DevNode_Key
108 resolve_cfgmgr32_functions(void)
112 if (CM_Get_DevNode_Registry_PropertyA && CM_Get_DevNode_Registry_PropertyW && CM_Open_DevNode_Key)
115 cfgmgr32 = GetModuleHandleA("cfgmgr32.dll");
119 CM_Get_DevNode_Registry_PropertyA = (void *)GetProcAddress(cfgmgr32, "CM_Get_DevNode_Registry_PropertyA");
120 CM_Get_DevNode_Registry_PropertyW = (void *)GetProcAddress(cfgmgr32, "CM_Get_DevNode_Registry_PropertyW");
121 CM_Open_DevNode_Key = (void *)GetProcAddress(cfgmgr32, "CM_Open_DevNode_Key");
122 if (!CM_Get_DevNode_Registry_PropertyA || !CM_Get_DevNode_Registry_PropertyW || !CM_Open_DevNode_Key)
129 * cfgmgr32.dll uses custom non-Win32 error numbers which are unsupported by
130 * Win32 APIs like GetLastError() and FormatMessage() functions.
132 * Windows 7 introduced new cfgmgr32.dll function CM_MapCrToWin32Err() for
133 * translating mapping CR_* errors to Win32 errors but most error codes are
134 * not mapped. So this function is unusable.
136 * Error strings for CR_* errors are defined in cmapi.rc file which is
137 * statically linked into some system libraries (e.g. filemgmt.dll,
138 * acledit.dll, netui0.dll or netui2.dll) but due to static linking it is
139 * not possible to access these error strings easily at runtime.
141 * So define own function for translating CR_* errors directly to strings.
144 cr_strerror(CONFIGRET cr_error_id)
146 static char unknown_error[sizeof("Unknown CR error XXXXXXXXXX")];
147 static const char *cr_errors[] = {
148 "The operation completed successfully",
150 "Not enough memory is available to process this command",
151 "A required pointer parameter is invalid",
152 "The ulFlags parameter specified is invalid for this operation",
153 "The device instance handle parameter is not valid",
154 "The supplied resource descriptor parameter is invalid",
155 "The supplied logical configuration parameter is invalid",
156 "CR_INVALID_ARBITRATOR",
157 "CR_INVALID_NODELIST",
158 "CR_DEVNODE_HAS_REQS/CR_DEVINST_HAS_REQS",
159 "The RESOURCEID parameter does not contain a valid RESOURCEID",
160 "CR_DLVXD_NOT_FOUND",
161 "The specified device instance handle does not correspond to a present device",
162 "There are no more logical configurations available",
163 "There are no more resource descriptions available",
164 "This device instance already exists",
165 "The supplied range list parameter is invalid",
167 "A general internal error occurred",
168 "CR_NO_SUCH_LOGICAL_DEV",
169 "The device is disabled for this configuration",
171 "A service or application refused to allow removal of this device",
173 "CR_INVALID_LOAD_TYPE",
174 "An output parameter was too small to hold all the data available",
176 "CR_NO_REGISTRY_HANDLE",
177 "A required entry in the registry is missing or an attempt to write to the registry failed",
178 "The specified Device ID is not a valid Device ID",
179 "One or more parameters were invalid",
181 "CR_DEVLOADER_NOT_READY",
183 "There are no more hardware profiles available",
184 "CR_DEVICE_NOT_THERE",
185 "The specified value does not exist in the registry",
187 "The specified priority is invalid for this operation",
188 "This device cannot be disabled",
194 "The specified key does not exist in the registry",
195 "The specified machine name does not meet the UNC naming conventions",
196 "A general remote communication error occurred",
197 "The machine selected for remote communication is not available at this time",
198 "The Plug and Play service or another required service is not available",
200 "This routine is not implemented in this version of the operating system",
201 "The specified property type is invalid for this operation",
202 "Device interface is active",
203 "No such device interface",
204 "Invalid reference string",
205 "Invalid conflict list",
207 "Invalid structure size"
209 if (cr_error_id <= 0 || cr_error_id >= sizeof(cr_errors)/sizeof(*cr_errors))
211 sprintf(unknown_error, "Unknown CR error %lu", cr_error_id);
212 return unknown_error;
214 return cr_errors[cr_error_id];
218 fmt_validate(const char *s, int len, const char *fmt)
222 for (i = 0; i < len; i++)
223 if (!fmt[i] || (fmt[i] == '#' ? !isxdigit(s[i]) : fmt[i] != s[i]))
230 seq_xdigit_validate(const char *s, int mult, int min)
235 if (len < min*mult || len % mult)
238 for (i = 0; i < len; i++)
246 get_device_service_name(struct pci_access *a, DEVINST devinst, DEVINSTID_A devinst_id, BOOL *supported)
248 ULONG reg_type, reg_size, reg_len;
253 * All data are stored as 7-bit ASCII strings in system but service name is
254 * exception. It can contain UNICODE. Moreover it is passed to other Win32 API
255 * functions and therefore it cannot be converted to 8-bit ANSI string without
256 * data loss. So use wide function CM_Get_DevNode_Registry_PropertyW() in this
257 * case and deal with all wchar_t problems...
261 cr = CM_Get_DevNode_Registry_PropertyW(devinst, CM_DRP_SERVICE, ®_type, NULL, ®_size, 0);
262 if (cr == CR_CALL_NOT_IMPLEMENTED)
267 else if (cr == CR_NO_SUCH_VALUE)
272 else if (cr != CR_SUCCESS &&
273 cr != CR_BUFFER_SMALL)
275 a->warning("Cannot retrieve service name for PCI device %s: %s.", devinst_id, cr_strerror(cr));
279 else if (reg_type != REG_SZ)
281 a->warning("Cannot retrieve service name for PCI device %s: Service name is stored as unknown type 0x%lx.", devinst_id, reg_type);
288 * Returned size is on older Windows versions without nul-term char.
289 * So explicitly increase size and fill nul-term byte.
291 reg_size += sizeof(service_name[0]);
292 service_name = pci_malloc(a, reg_size);
294 cr = CM_Get_DevNode_Registry_PropertyW(devinst, CM_DRP_SERVICE, ®_type, service_name, ®_len, 0);
295 service_name[reg_size/sizeof(service_name[0]) - 1] = 0;
296 if (reg_len > reg_size)
298 pci_mfree(service_name);
302 else if (cr != CR_SUCCESS)
304 a->warning("Cannot retrieve service name for PCI device %s: %s.", devinst_id, cr_strerror(cr));
305 pci_mfree(service_name);
309 else if (reg_type != REG_SZ)
311 a->warning("Cannot retrieve service name for PCI device %s: Service name is stored as unknown type 0x%lx.", devinst_id, reg_type);
312 pci_mfree(service_name);
322 get_driver_path_for_service(struct pci_access *a, LPCWSTR service_name, SC_HANDLE manager)
324 UINT (WINAPI *get_system_root_path)(LPWSTR buffer, UINT size) = NULL;
325 DWORD service_config_size, service_config_len;
326 LPQUERY_SERVICE_CONFIGW service_config = NULL;
327 LPWSTR service_image_path = NULL;
328 SERVICE_STATUS service_status;
329 SC_HANDLE service = NULL;
330 char *driver_path = NULL;
331 int trim_system32 = 0;
339 service = OpenServiceW(manager, service_name, SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS);
342 error = GetLastError();
343 if (error != ERROR_SERVICE_DOES_NOT_EXIST)
344 a->warning("Cannot open service %ls with query rights: %s.", service_name, win32_strerror(error));
348 if (!QueryServiceStatus(service, &service_status))
350 error = GetLastError();
351 a->warning("Cannot query status of service %ls: %s.", service_name, win32_strerror(error));
355 if (service_status.dwCurrentState == SERVICE_STOPPED)
358 if (service_status.dwServiceType != SERVICE_KERNEL_DRIVER)
361 if (!QueryServiceConfigW(service, NULL, 0, &service_config_size))
363 error = GetLastError();
364 if (error != ERROR_INSUFFICIENT_BUFFER)
366 a->warning("Cannot query config of service %ls: %s.", service_name, win32_strerror(error));
371 retry_service_config:
372 service_config = pci_malloc(a, service_config_size);
373 if (!QueryServiceConfigW(service, service_config, service_config_size, &service_config_len))
375 error = GetLastError();
376 if (error == ERROR_INSUFFICIENT_BUFFER)
378 pci_mfree(service_config);
379 service_config_size = service_config_len;
380 goto retry_service_config;
382 a->warning("Cannot query config of service %ls: %s.", service_name, win32_strerror(error));
386 if (service_config->dwServiceType != SERVICE_KERNEL_DRIVER)
390 * Despite QueryServiceConfig() is Win32 API, it returns lpBinaryPathName
391 * (ImagePath registry) in NT format. Unfortunately there is no Win32
392 * function for converting NT paths to Win32 paths. So do it manually and
393 * convert this NT format to human-readable Win32 path format.
397 * GetSystemWindowsDirectoryW() returns path to NT SystemRoot namespace.
398 * Alternativelly path to NT SystemRoot namespace can be constructed by
399 * GetSystemDirectoryW() by trimming "\\system32" from the end of path.
400 * GetSystemWindowsDirectoryW() is not provided in old Windows versions,
401 * so use GetProcAddress() for compatibility with all Windows versions.
403 kernel32 = GetModuleHandleW(L"kernel32.dll");
405 get_system_root_path = (void *)GetProcAddress(kernel32, "GetSystemWindowsDirectoryW");
408 get_system_root_path = &GetSystemDirectoryW;
412 if (!service_config->lpBinaryPathName || !service_config->lpBinaryPathName[0])
414 /* No ImagePath is specified, NT kernel assumes implicit kernel driver path by service name, which is relative to "\\system32\\drivers". */
415 /* GetSystemDirectoryW() returns path to "\\system32" directory on all Windows versions. */
416 system32_len = GetSystemDirectoryW(NULL, 0); /* Returns number of WCHARs plus 1 for nul-term. */
417 service_image_path = pci_malloc(a, sizeof(WCHAR) * (system32_len + sizeof("\\drivers\\")-1 + wcslen(service_name) + sizeof(".sys")-1));
418 system32_len = GetSystemDirectoryW(service_image_path, system32_len); /* Now it returns number of WCHARs without nul-term. */
419 if (system32_len && service_image_path[system32_len-1] != L'\\')
420 service_image_path[system32_len++] = L'\\';
421 wcscpy(service_image_path + system32_len, L"drivers\\");
422 wcscpy(service_image_path + system32_len + sizeof("drivers\\")-1, service_name);
423 wcscpy(service_image_path + system32_len + sizeof("drivers\\")-1 + wcslen(service_name), L".sys");
425 else if (wcsncmp(service_config->lpBinaryPathName, L"\\SystemRoot\\", sizeof("\\SystemRoot\\")-1) == 0)
427 /* ImagePath is in NT SystemRoot namespace, convert to Win32 path via GetSystemWindowsDirectoryW()/GetSystemDirectoryW(). */
428 systemroot_len = get_system_root_path(NULL, 0); /* Returns number of WCHARs plus 1 for nul-term. */
429 service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + wcslen(service_config->lpBinaryPathName) - (sizeof("\\SystemRoot")-1)));
430 systemroot_len = get_system_root_path(service_image_path, systemroot_len); /* Now it returns number of WCHARs without nul-term. */
431 if (trim_system32 && systemroot_len && (trim_ptr = wcsrchr(service_image_path, L'\\')) != NULL)
432 systemroot_len = trim_ptr - service_image_path;
433 if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
434 service_image_path[systemroot_len++] = L'\\';
435 wcscpy(service_image_path + systemroot_len, service_config->lpBinaryPathName + sizeof("\\SystemRoot\\")-1);
437 else if (wcsncmp(service_config->lpBinaryPathName, L"\\??\\UNC\\", sizeof("\\??\\UNC\\")-1) == 0 ||
438 wcsncmp(service_config->lpBinaryPathName, L"\\??\\\\UNC\\", sizeof("\\??\\\\UNC\\")-1) == 0)
440 /* ImagePath is in NT UNC namespace, convert to Win32 UNC path via "\\\\" prefix. */
441 service_image_path = pci_malloc(a, sizeof(WCHAR) * (sizeof("\\\\") + wcslen(service_config->lpBinaryPathName) - (sizeof("\\??\\UNC\\")-1)));
442 /* Namespace separator may be single or double backslash. */
443 driver_path_len = sizeof("\\??\\")-1;
444 if (service_config->lpBinaryPathName[driver_path_len] == L'\\')
446 driver_path_len += sizeof("UNC\\")-1;
447 wcscpy(service_image_path, L"\\\\");
448 wcscpy(service_image_path + sizeof("\\\\")-1, service_config->lpBinaryPathName + driver_path_len);
450 else if (wcsncmp(service_config->lpBinaryPathName, L"\\??\\", sizeof("\\??\\")-1) == 0)
452 /* ImagePath is in NT Global?? namespace, root of the Win32 file namespace, so just remove "\\??\\" prefix to get Win32 path. */
453 service_image_path = pci_malloc(a, sizeof(WCHAR) * (wcslen(service_config->lpBinaryPathName) - (sizeof("\\??\\")-1)));
454 /* Namespace separator may be single or double backslash. */
455 driver_path_len = sizeof("\\??\\")-1;
456 if (service_config->lpBinaryPathName[driver_path_len] == L'\\')
458 wcscpy(service_image_path, service_config->lpBinaryPathName + driver_path_len);
460 else if (service_config->lpBinaryPathName[0] != L'\\')
462 /* ImagePath is relative to the NT SystemRoot namespace, convert to Win32 path via GetSystemWindowsDirectoryW()/GetSystemDirectoryW(). */
463 systemroot_len = get_system_root_path(NULL, 0); /* Returns number of WCHARs plus 1 for nul-term. */
464 service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + sizeof("\\")-1 + wcslen(service_config->lpBinaryPathName)));
465 systemroot_len = get_system_root_path(service_image_path, systemroot_len); /* Now it returns number of WCHARs without nul-term. */
466 if (trim_system32 && systemroot_len && (trim_ptr = wcsrchr(service_image_path, L'\\')) != NULL)
467 systemroot_len = trim_ptr - service_image_path;
468 if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
469 service_image_path[systemroot_len++] = L'\\';
470 wcscpy(service_image_path + systemroot_len, service_config->lpBinaryPathName);
474 /* 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. */
475 service_image_path = pci_malloc(a, sizeof(WCHAR) * wcslen(service_config->lpBinaryPathName));
476 wcscpy(service_image_path, service_config->lpBinaryPathName);
479 /* Calculate len of buffer needed for conversion from LPWSTR to char*. */
480 driver_path_len = WideCharToMultiByte(CP_ACP, 0, service_image_path, -1, NULL, 0, NULL, NULL);
481 if (driver_path_len <= 0)
483 error = GetLastError();
484 a->warning("Cannot convert kernel driver path from wide string to 8-bit string: %s.", win32_strerror(error));
488 driver_path = pci_malloc(a, driver_path_len);
489 driver_path_len = WideCharToMultiByte(CP_ACP, 0, service_image_path, -1, driver_path, driver_path_len, NULL, NULL);
490 if (driver_path_len <= 0)
492 error = GetLastError();
493 a->warning("Cannot convert kernel driver path from wide string to 8-bit string: %s.", win32_strerror(error));
494 pci_mfree(driver_path);
500 if (service_image_path)
501 pci_mfree(service_image_path);
503 pci_mfree(service_config);
505 CloseServiceHandle(service);
510 get_device_driver_devreg(struct pci_access *a, DEVINST devinst, DEVINSTID_A devinst_id)
515 cr = CM_Open_DevNode_Key(devinst, KEY_READ, 0, RegDisposition_OpenExisting, &key, CM_REGISTRY_SOFTWARE);
516 if (cr != CR_SUCCESS)
518 if (cr != CR_NO_SUCH_VALUE)
519 a->warning("Cannot retrieve driver key for device %s: %s.", devinst_id, cr_strerror(cr));
527 read_reg_key_string_value(struct pci_access *a, HKEY key, const char *name, DWORD *unkn_reg_type)
529 DWORD reg_type, reg_size, reg_len;
534 error = RegQueryValueExA(key, name, NULL, ®_type, NULL, ®_size);
535 if (error != ERROR_SUCCESS &&
536 error != ERROR_MORE_DATA)
541 else if (reg_type != REG_SZ)
544 *unkn_reg_type = reg_type;
549 value = pci_malloc(a, reg_size + 1);
551 error = RegQueryValueExA(key, name, NULL, ®_type, (PBYTE)value, ®_len);
552 if (error != ERROR_SUCCESS)
555 if (error == ERROR_MORE_DATA)
563 else if (reg_type != REG_SZ)
567 *unkn_reg_type = reg_type;
570 value[reg_len] = '\0';
576 driver_cmp(const char *driver, const char *match)
578 int len = strlen(driver);
579 if (driver[0] == '*')
581 if (len >= 4 && strcasecmp(driver + len - 4, ".vxd") == 0)
583 return strncasecmp(driver, match, len);
587 get_driver_path_for_regkey(struct pci_access *a, DEVINSTID_A devinst_id, HKEY key)
589 char *driver_list, *driver, *driver_next;
590 char *subdriver, *subname;
601 driver_list = read_reg_key_string_value(a, key, "DevLoader", &unkn_reg_type);
604 error = GetLastError();
606 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);
607 else if (error != ERROR_FILE_NOT_FOUND)
608 a->warning("Cannot read driver DevLoader key for PCI device %s: %s.", devinst_id, win32_strerror(error));
613 driver = driver_list;
616 driver_next = strchr(driver, ',');
618 *(driver_next++) = '\0';
620 if (driver_cmp(driver, "ios") == 0 ||
621 driver_cmp(driver, "vcomm") == 0)
622 subname = "PortDriver";
623 else if (driver_cmp(driver, "ntkern") == 0)
624 subname = "NTMPDriver";
625 else if (driver_cmp(driver, "ndis") == 0)
626 subname = "DeviceVxDs";
627 else if (driver_cmp(driver, "vdd") == 0)
633 if (subname && strcmp(subname, "minivdd") == 0)
635 error = RegOpenKeyA(key, "Default", &subkey);
636 if (error != ERROR_SUCCESS)
638 a->warning("Cannot open driver subkey Default for PCI device %s: %s.", devinst_id, win32_strerror(error));
649 subdriver = read_reg_key_string_value(a, subkey, subname, &unkn_reg_type);
652 error = GetLastError();
654 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);
655 else if (error != ERROR_FILE_NOT_FOUND)
656 a->warning("Cannot read driver %s key for PCI device %s: %s.", subname, devinst_id, win32_strerror(error));
657 else if (strcmp(subname, "minivdd") == 0)
662 else if (strcmp(subname, "drv") == 0)
674 char *endptr = strchr(subdriver, ',');
681 driver = driver_next;
684 if (subdriver && subdriver[0])
685 driver_ptr = subdriver;
691 if (driver_ptr && driver_ptr[0] == '*')
702 len = driver_ptr ? strlen(driver_ptr) : 0;
703 noext = driver_ptr && (len < 4 || driver_ptr[len-4] != '.');
709 if (tolower(driver_ptr[0]) >= 'a' && tolower(driver_ptr[0]) <= 'z' && driver_ptr[1] == ':')
711 /* Driver is already with absolute path. */
712 driver_path = pci_strdup(a, driver_ptr);
714 else if (driver_cmp(driver, "ntkern") == 0 && subdriver)
716 /* Driver is relative to system32\drivers\ directory which is relative to windows directory. */
717 systemdir_len = GetWindowsDirectoryA(NULL, 0);
718 driver_path = pci_malloc(a, systemdir_len + 1 + sizeof("system32\\drivers\\")-1 + strlen(driver_ptr) + 4 + 1);
719 systemdir_len = GetWindowsDirectoryA(driver_path, systemdir_len + 1);
720 if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
721 driver_path[systemdir_len++] = '\\';
722 sprintf(driver_path + systemdir_len, "system32\\drivers\\%s%s", driver_ptr, noext ? ".sys" : "");
726 /* Driver is packed in vmm32.vxd which is stored in system directory. */
727 systemdir_len = GetSystemDirectoryA(NULL, 0);
728 driver_path = pci_malloc(a, systemdir_len + 1 + sizeof("vmm32.vxd ()")-1 + strlen(driver_ptr) + 4 + 1);
729 systemdir_len = GetSystemDirectoryA(driver_path, systemdir_len + 1);
730 if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
731 driver_path[systemdir_len++] = '\\';
732 sprintf(driver_path + systemdir_len, "vmm32.vxd (%s%s)", driver_ptr, noext ? ".vxd" : "");
736 /* Otherwise driver is relative to system directory. */
737 systemdir_len = GetSystemDirectoryA(NULL, 0);
738 driver_path = pci_malloc(a, systemdir_len + 1 + strlen(driver_ptr) + 4 + 1);
739 systemdir_len = GetSystemDirectoryA(driver_path, systemdir_len + 1);
740 if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
741 driver_path[systemdir_len++] = '\\';
742 sprintf(driver_path + systemdir_len, "%s%s", driver_ptr, noext ? ".vxd" : "");
747 pci_mfree(subdriver);
748 pci_mfree(driver_list);
753 get_device_driver_path(struct pci_dev *d, SC_HANDLE manager, BOOL manager_supported)
755 struct pci_access *a = d->access;
756 BOOL service_supported = TRUE;
757 DEVINSTID_A devinst_id = NULL;
758 LPWSTR service_name = NULL;
759 ULONG devinst_id_len = 0;
760 char *driver_path = NULL;
761 DEVINST devinst = (DEVINST)d->backend_data;
766 if (CM_Get_DevNode_Status(&status, &problem, devinst, 0) != CR_SUCCESS || !(status & DN_DRIVER_LOADED))
769 if (CM_Get_Device_ID_Size(&devinst_id_len, devinst, 0) == CR_SUCCESS)
771 devinst_id = pci_malloc(a, devinst_id_len + 1);
772 if (CM_Get_Device_IDA(devinst, devinst_id, devinst_id_len + 1, 0) != CR_SUCCESS)
774 pci_mfree(devinst_id);
775 devinst_id = pci_strdup(a, "UNKNOWN");
779 devinst_id = pci_strdup(a, "UNKNOWN");
781 service_name = get_device_service_name(d->access, devinst, devinst_id, &service_supported);
782 if ((!service_name || !manager) && service_supported && manager_supported)
784 else if (service_name && manager)
786 driver_path = get_driver_path_for_service(d->access, service_name, manager);
790 key = get_device_driver_devreg(d->access, devinst, devinst_id);
793 driver_path = get_driver_path_for_regkey(d->access, devinst_id, key);
801 pci_mfree(service_name);
802 pci_mfree(devinst_id);
807 fill_drivers(struct pci_access *a)
809 BOOL manager_supported;
815 /* ERROR_CALL_NOT_IMPLEMENTED is returned on systems without Service Manager support. */
816 manager_supported = TRUE;
817 manager = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
820 error = GetLastError();
821 if (error != ERROR_CALL_NOT_IMPLEMENTED)
822 a->warning("Cannot open Service Manager with connect right: %s.", win32_strerror(error));
824 manager_supported = FALSE;
827 for (d = a->devices; d; d = d->next)
829 driver = get_device_driver_path(d, manager, manager_supported);
832 pci_set_property(d, PCI_FILL_DRIVER, driver);
835 d->known_fields |= PCI_FILL_DRIVER;
839 CloseServiceHandle(manager);
843 res_id_to_str(RESOURCEID res_id)
845 static char hex_res_id[sizeof("0xffffffff")];
847 if (res_id == ResType_IO)
849 else if (res_id == ResType_Mem)
851 else if (res_id == ResType_IRQ)
854 sprintf(hex_res_id, "0x%lx", res_id);
859 fill_resources(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
861 struct pci_access *a = d->access;
869 RES_DES prev_res_des;
878 int last_shared_irq = -1;
880 cr = CM_Get_DevNode_Status(&status, &problem, devinst, 0);
881 if (cr != CR_SUCCESS)
883 a->warning("Cannot retrieve status of PCI device %s: %s.", devinst_id, cr_strerror(cr));
887 cr = CR_NO_MORE_LOG_CONF;
890 * If the device is running then retrieve allocated configuration by PnP
891 * manager which is currently in use by a device.
893 if (!(status & DN_HAS_PROBLEM))
894 cr = CM_Get_First_Log_Conf(&config, devinst, ALLOC_LOG_CONF);
897 * If the device is not running or it does not have allocated configuration by
898 * PnP manager then retrieve forced configuration which prevents PnP manager
899 * from assigning resources.
901 if (cr == CR_NO_MORE_LOG_CONF)
902 cr = CM_Get_First_Log_Conf(&config, devinst, FORCED_LOG_CONF);
905 * If the device does not have neither allocated configuration by PnP manager
906 * nor forced configuration and it is not disabled in the BIOS then retrieve
907 * boot configuration supplied by the BIOS.
909 if (cr == CR_NO_MORE_LOG_CONF &&
910 (!(status & DN_HAS_PROBLEM) || problem != CM_PROB_HARDWARE_DISABLED))
911 cr = CM_Get_First_Log_Conf(&config, devinst, BOOT_LOG_CONF);
913 if (cr != CR_SUCCESS)
916 * Note: Starting with Windows 8, CM_Get_First_Log_Conf returns
917 * CR_CALL_NOT_IMPLEMENTED when used in a Wow64 scenario.
918 * To request information about the hardware resources on a local machine
919 * it is necessary implement an architecture-native version of the
920 * application using the hardware resource APIs. For example: An AMD64
921 * application for AMD64 systems.
923 if (cr == CR_CALL_NOT_IMPLEMENTED && win32_is_32bit_on_win8_64bit_system())
925 static BOOL warn_once = FALSE;
929 a->warning("Cannot retrieve resources of PCI devices from 32-bit application on 64-bit system.");
932 else if (cr != CR_NO_MORE_LOG_CONF)
933 a->warning("Cannot retrieve resources of PCI device %s: %s.", devinst_id, cr_strerror(cr));
938 non_nt_system = win32_is_non_nt_system();
945 ULONG child_name_len;
949 if (CM_Get_Child(&child, devinst, 0) != CR_SUCCESS)
951 else if (CM_Get_Device_ID_Size(&child_name_len, child, 0) != CR_SUCCESS)
956 child_name = pci_malloc(a, child_name_len);
957 if (CM_Get_Device_IDA(child, child_name, child_name_len, 0) != CR_SUCCESS)
959 else if (strncmp(child_name, "PCI\\", 4) != 0)
963 pci_mfree(child_name);
966 if (has_child || d->device_class == PCI_CLASS_BRIDGE_PCI || d->device_class == PCI_CLASS_BRIDGE_CARDBUS)
975 prev_res_des = (RES_DES)config;
976 while ((cr = CM_Get_Next_Res_Des(&res_des, prev_res_des, ResType_All, &res_id, 0)) == CR_SUCCESS)
978 pciaddr_t start, end, size, flags;
979 ULONG res_des_data_size;
982 if (prev_res_des != config)
983 CM_Free_Res_Des_Handle(prev_res_des);
985 prev_res_des = res_des;
987 /* Skip other resources early */
988 if (res_id != ResType_IO && res_id != ResType_Mem && res_id != ResType_IRQ)
991 cr = CM_Get_Res_Des_Data_Size(&res_des_data_size, res_des, 0);
992 if (cr != CR_SUCCESS)
994 a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, cr_strerror(cr));
998 if (!res_des_data_size)
1000 a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, "Empty data");
1004 res_des_data = pci_malloc(a, res_des_data_size);
1005 cr = CM_Get_Res_Des_Data(res_des, res_des_data, res_des_data_size, 0);
1006 if (cr != CR_SUCCESS)
1008 a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, cr_strerror(cr));
1009 pci_mfree(res_des_data);
1014 * There can be more resources with the same id. In this case we are
1015 * interested in the last one in the list as at the beginning of the list
1016 * can be some virtual resources (which are not set in PCI config space).
1019 if (res_id == ResType_IO)
1021 PIO_RESOURCE io_data = (PIO_RESOURCE)res_des_data;
1023 start = io_data->IO_Header.IOD_Alloc_Base;
1024 end = io_data->IO_Header.IOD_Alloc_End;
1025 size = (end > start) ? (end - start + 1) : 0;
1026 flags = PCI_IORESOURCE_IO;
1029 * If neither 10-bit, 12-bit, nor 16-bit support is presented then
1030 * expects that this is 32-bit I/O resource. If resource does not fit
1031 * into 16-bit space then it must be 32-bit. If PCI I/O resource is
1032 * not 32-bit then it is 16-bit.
1034 if (end <= 0xffff && (io_data->IO_Header.IOD_DesFlags & (fIOD_10_BIT_DECODE|fIOD_12_BIT_DECODE|fIOD_16_BIT_DECODE)))
1035 flags |= PCI_IORESOURCE_IO_16BIT_ADDR;
1038 * 16/32-bit non-NT systems do not support these two flags.
1039 * Most NT-based Windows versions support only the fIOD_WINDOW_DECODE
1040 * flag and put all BAR resources before window resources in this
1041 * resource list. So use this fIOD_WINDOW_DECODE flag as separator
1042 * between IO/MEM windows and IO/MEM BARs of PCI Bridges.
1044 if (io_data->IO_Header.IOD_DesFlags & fIOD_WINDOW_DECODE)
1046 else if (io_data->IO_Header.IOD_DesFlags & fIOD_PORT_BAR)
1049 if (is_bar_res && bar_res_count < 6)
1051 d->flags[bar_res_count] = flags;
1052 d->base_addr[bar_res_count] = start;
1053 d->size[bar_res_count] = size;
1056 else if (!is_bar_res)
1058 d->bridge_flags[0] = flags;
1059 d->bridge_base_addr[0] = start;
1060 d->bridge_size[0] = size;
1061 d->known_fields |= PCI_FILL_BRIDGE_BASES;
1064 else if (res_id == ResType_Mem)
1066 PMEM_RESOURCE mem_data = (PMEM_RESOURCE)res_des_data;
1068 start = mem_data->MEM_Header.MD_Alloc_Base;
1069 end = mem_data->MEM_Header.MD_Alloc_End;
1070 size = (end > start) ? (end - start + 1) : 0;
1071 flags = PCI_IORESOURCE_MEM;
1074 * If fMD_PrefetchAllowed flag is set then this is
1075 * PCI Prefetchable Memory resource.
1077 if ((mem_data->MEM_Header.MD_Flags & mMD_Prefetchable) == fMD_PrefetchAllowed)
1078 flags |= PCI_IORESOURCE_PREFETCH;
1080 /* If resource does not fit into 32-bit space then it must be 64-bit. */
1081 if (is_bar_res && end > 0xffffffff)
1082 flags |= PCI_IORESOURCE_MEM_64;
1085 * These two flags (fMD_WINDOW_DECODE and fMD_MEMORY_BAR) are
1086 * unsupported on most Windows versions, so distinguish between
1087 * window and BAR based on previous resource type.
1089 if (mem_data->MEM_Header.MD_Flags & fMD_WINDOW_DECODE)
1091 else if (mem_data->MEM_Header.MD_Flags & fMD_MEMORY_BAR)
1094 /* 64-bit BAR resource must be at even position. */
1095 if (is_bar_res && (flags & PCI_IORESOURCE_MEM_64) && bar_res_count % 2)
1098 if (is_bar_res && bar_res_count < 6)
1100 d->flags[bar_res_count] = flags;
1101 d->base_addr[bar_res_count] = start;
1102 d->size[bar_res_count] = size;
1104 /* 64-bit BAR resource occupies two slots. */
1105 if (flags & PCI_IORESOURCE_MEM_64)
1108 else if (!is_bar_res && !(flags & PCI_IORESOURCE_PREFETCH))
1110 d->bridge_flags[1] = flags;
1111 d->bridge_base_addr[1] = start;
1112 d->bridge_size[1] = size;
1113 d->known_fields |= PCI_FILL_BRIDGE_BASES;
1115 else if (!is_bar_res && (flags & PCI_IORESOURCE_PREFETCH))
1117 d->bridge_flags[2] = flags;
1118 d->bridge_base_addr[2] = start;
1119 d->bridge_size[2] = size;
1120 d->known_fields |= PCI_FILL_BRIDGE_BASES;
1123 else if (res_id == ResType_IRQ)
1125 PIRQ_RESOURCE irq_data = (PIRQ_RESOURCE)res_des_data;
1128 * libpci's d->irq should be set to the non-MSI PCI IRQ and therefore
1129 * it should be level IRQ which may be shared with other PCI devices
1130 * and drivers in the system. As always we want to retrieve the last
1131 * IRQ number from the resource list.
1133 * On 16/32-bit non-NT systems is fIRQD_Level set to 2 but on NT
1134 * systems to 0. Moreover it looks like that different PCI drivers
1135 * on both NT and non-NT systems set bits 0 and 1 to wrong values
1136 * and so reported value in this list may be incorrect.
1138 * Therefore take the last level-shared IRQ number from the resource
1139 * list and if there is none of this type then take the last IRQ
1140 * number from the list.
1142 last_irq = irq_data->IRQ_Header.IRQD_Alloc_Num;
1143 if ((irq_data->IRQ_Header.IRQD_Flags & (mIRQD_Share|mIRQD_Edge_Level)) == (fIRQD_Share|fIRQD_Level))
1144 last_shared_irq = irq_data->IRQ_Header.IRQD_Alloc_Num;
1147 * IRQ resource on 16/32-bit non-NT systems is separator between
1148 * IO/MEM windows and IO/MEM BARs of PCI Bridges. After the IRQ
1149 * resource are IO/MEM BAR resources.
1151 if (!is_bar_res && non_nt_system)
1155 pci_mfree(res_des_data);
1157 if (cr != CR_NO_MORE_RES_DES)
1158 a->warning("Cannot retrieve resources of PCI device %s: %s.", devinst_id, cr_strerror(cr));
1160 if (prev_res_des != config)
1161 CM_Free_Res_Des_Handle(prev_res_des);
1163 CM_Free_Log_Conf_Handle(config);
1165 /* Set the last IRQ from the resource list to pci_dev. */
1166 if (last_shared_irq >= 0)
1167 d->irq = last_shared_irq;
1168 else if (last_irq >= 0)
1170 if (last_shared_irq >= 0 || last_irq >= 0)
1171 d->known_fields |= PCI_FILL_IRQ;
1173 if (bar_res_count > 0)
1174 d->known_fields |= PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS;
1178 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)
1180 ULONG reg_type, reg_len;
1182 BOOL have_bus, have_devfunc;
1183 DWORD drp_bus_num, drp_address;
1187 have_devfunc = FALSE;
1190 * DRP_BUSNUMBER consists of PCI domain number in high 24 bits
1191 * and PCI bus number in low 8 bits.
1193 reg_len = sizeof(drp_bus_num);
1194 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_BUSNUMBER, ®_type, &drp_bus_num, ®_len, 0);
1195 if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_bus_num))
1197 *domain = drp_bus_num >> 8;
1198 *bus = drp_bus_num & 0xff;
1203 * DRP_ADDRESS consists of PCI device number in high 16 bits
1204 * and PCI function number in low 16 bits.
1206 reg_len = sizeof(drp_address);
1207 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_ADDRESS, ®_type, &drp_address, ®_len, 0);
1208 if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_address))
1210 *dev = drp_address >> 16;
1211 *func = drp_address & 0xffff;
1212 have_devfunc = TRUE;
1216 * Device Instance Id for PCI devices is of format:
1217 * "<enumerator>\\<device_id>\\<instance_id>"
1219 * "<enumerator>" is "PCI"
1220 * "<device_id>" is "VEN_####&DEV_####&SUBSYS_########&REV_##"
1221 * and "<instance_id>" for PCI devices is at least in one of following format:
1222 * "BUS_##&DEV_##&FUNC_##"
1223 * "##.." (sequence of devfn hex bytes, where bytes represents tree path to the root)
1224 * "#..&#..&#..&#.." (four hex numbers separated by "&"; meaning is unknown yet)
1226 * First two formats are used only on systems without support for multiple
1227 * domains. The second format uses intel-conf encoding of device and function
1228 * number: Low 3 bits is function number and high 5 bits is device number.
1229 * Bus number is not really encoded in second format!
1231 * The third format is used on systems with support for multiple domains but
1232 * format is variable length and currently its meaning is unknown. Apparently
1233 * it looks like that DRP_BUSNUMBER and DRP_ADDRESS registry properties are
1234 * supported on these systems.
1236 * If DRP_BUSNUMBER or DRP_ADDRESS failed then try to parse PCI bus, device
1237 * and function numbers from Instance Id part.
1239 if (!have_bus || !have_devfunc)
1241 const char *device_id0 = strchr(devinst_id, '\\');
1242 const char *instance_id0 = device_id0 ? strchr(device_id0 + 1, '\\') : NULL;
1243 const char *instance_id = instance_id0 ? instance_id0 + 1 : NULL;
1248 if (fmt_validate(instance_id, strlen(instance_id), "BUS_##&DEV_##&FUNC_##") &&
1249 sscanf(instance_id, "BUS_%x&DEV_%x&FUNC_%x", bus, dev, func) == 3)
1252 have_devfunc = TRUE;
1254 else if (seq_xdigit_validate(instance_id, 2, 2) &&
1255 sscanf(instance_id, "%2x", &devfn) == 1)
1258 *func = devfn & 0x7;
1259 have_devfunc = TRUE;
1265 * Virtual IRQ holder devices do not have assigned any bus/dev/func number and
1266 * have "IRQHOLDER" in their Device Id part. So skip them.
1268 if (!have_bus && !have_devfunc && strncmp(devinst_id, "PCI\\IRQHOLDER\\", 14) == 0)
1272 * When some numbers cannot be retrieved via cfgmgr32 then set them to zeros
1273 * to have structure initialized. It makes sense to report via libpci also
1274 * such "incomplete" device as cfgmgr32 can provide additional information
1275 * like device/vendor ids or assigned resources.
1277 if (!have_bus && !have_devfunc)
1279 *bus = *dev = *func = 0;
1280 a->warning("Cannot retrieve bus, device and function numbers for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1285 a->warning("Cannot retrieve bus number for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1287 else if (!have_devfunc)
1290 a->warning("Cannot retrieve device and function numbers for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1297 fill_data_from_string(struct pci_dev *d, const char *str)
1299 BOOL have_device_id;
1300 BOOL have_vendor_id;
1303 const char *endptr, *endptr2;
1307 have_device_id = have_vendor_id = (d->known_fields & PCI_FILL_IDENT);
1308 have_prog_if = have_rev_id = (d->known_fields & PCI_FILL_CLASS_EXT);
1312 endptr = strchr(str, '&');
1313 endptr2 = strchr(str, '\\');
1314 if (endptr2 && (!endptr || endptr > endptr2))
1316 len = endptr ? endptr-str : (int)strlen(str);
1318 if (!have_vendor_id &&
1319 fmt_validate(str, len, "VEN_####") &&
1320 sscanf(str, "VEN_%x", &hex) == 1)
1323 have_vendor_id = TRUE;
1325 else if (!have_device_id &&
1326 fmt_validate(str, len, "DEV_####") &&
1327 sscanf(str, "DEV_%x", &hex) == 1)
1330 have_device_id = TRUE;
1332 else if (!(d->known_fields & PCI_FILL_SUBSYS) &&
1333 fmt_validate(str, len, "SUBSYS_########") &&
1334 sscanf(str, "SUBSYS_%x", &hex) == 1)
1336 d->subsys_vendor_id = hex & 0xffff;
1337 d->subsys_id = hex >> 16;
1338 d->known_fields |= PCI_FILL_SUBSYS;
1340 else if (!have_rev_id &&
1341 fmt_validate(str, len, "REV_##") &&
1342 sscanf(str, "REV_%x", &hex) == 1)
1347 else if (!((d->known_fields & PCI_FILL_CLASS) && have_prog_if) &&
1348 (fmt_validate(str, len, "CC_####") || fmt_validate(str, len, "CC_######")) &&
1349 sscanf(str, "CC_%x", &hex) == 1)
1355 d->prog_if = hex & 0xff;
1356 have_prog_if = TRUE;
1360 if (!(d->known_fields & PCI_FILL_CLASS))
1362 d->device_class = hex;
1363 d->known_fields |= PCI_FILL_CLASS;
1367 if (!endptr || endptr == endptr2)
1373 if ((have_device_id || d->device_id) && (have_vendor_id || d->vendor_id))
1374 d->known_fields |= PCI_FILL_IDENT;
1376 if ((have_prog_if || d->prog_if) && (have_rev_id || d->rev_id))
1377 d->known_fields |= PCI_FILL_CLASS_EXT;
1381 fill_data_from_devinst_id(struct pci_dev *d, DEVINSTID_A devinst_id)
1383 const char *device_id;
1385 device_id = strchr(devinst_id, '\\');
1391 * Device Id part of Device Instance Id is in format:
1392 * "VEN_####&DEV_####&SUBSYS_########&REV_##"
1394 fill_data_from_string(d, device_id);
1398 fill_data_from_hardware_ids(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
1400 ULONG reg_type, reg_size, reg_len;
1401 struct pci_access *a = d->access;
1402 char *hardware_ids = NULL;
1407 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, ®_type, NULL, ®_size, 0);
1408 if (cr != CR_SUCCESS && cr != CR_BUFFER_SMALL)
1410 a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1413 else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1415 a->warning("Cannot retrieve hardware ids for PCI device %s: Hardware ids are stored as unknown type 0x%lx.", devinst_id, reg_type);
1421 * Returned size is on older Windows versions without nul-term char.
1422 * So explicitly increase size and fill nul-term byte.
1425 hardware_ids = pci_malloc(a, reg_size);
1427 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, ®_type, hardware_ids, ®_len, 0);
1428 hardware_ids[reg_size - 1] = 0;
1429 if (reg_len > reg_size)
1431 pci_mfree(hardware_ids);
1435 else if (cr != CR_SUCCESS)
1437 a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1438 pci_mfree(hardware_ids);
1441 else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1443 a->warning("Cannot retrieve hardware ids for PCI device %s: Hardware ids are stored as unknown type 0x%lx.", devinst_id, reg_type);
1444 pci_mfree(hardware_ids);
1449 * Hardware ids is nul-separated nul-term string list where each string has
1450 * one of the following format:
1451 * "PCI\\VEN_####&DEV_####&SUBSYS_########&REV_##"
1452 * "PCI\\VEN_####&DEV_####&SUBSYS_########"
1453 * "PCI\\VEN_####&DEV_####&REV_##&CC_####"
1454 * "PCI\\VEN_####&DEV_####&CC_######"
1455 * "PCI\\VEN_####&DEV_####&CC_####"
1456 * "PCI\\VEN_####&DEV_####&REV_##"
1457 * "PCI\\VEN_####&DEV_####"
1459 for (str = hardware_ids; *str != '\0'; str += strlen(str) + 1)
1461 if (strncmp(str, "PCI\\", 4) != 0)
1464 fill_data_from_string(d, str);
1467 pci_mfree(hardware_ids);
1471 scan_devinst_id(struct pci_access *a, DEVINSTID_A devinst_id)
1473 unsigned int domain, bus, dev, func;
1478 cr = CM_Locate_DevNodeA(&devinst, devinst_id, CM_LOCATE_DEVNODE_NORMAL);
1479 if (cr != CR_SUCCESS)
1481 /* Do not show warning when device is not present (= does not match NORMAL flag). */
1482 if (cr != CR_NO_SUCH_DEVNODE)
1483 a->warning("Cannot retrieve handle for device %s: %s.", devinst_id, cr_strerror(cr));
1487 /* get_device_location() returns FALSE if devinst is not real PCI device. */
1488 if (!get_device_location(a, devinst, devinst_id, &domain, &bus, &dev, &func))
1491 d = pci_get_dev(a, domain, bus, dev, func);
1493 if (!d->access->backend_data)
1494 d->no_config_access = 1;
1495 d->backend_data = (void *)devinst;
1497 /* Parse device id part of devinst id and fill details into pci_dev. */
1499 fill_data_from_devinst_id(d, devinst_id);
1501 /* Retrieve hardware ids of devinst, parse them and fill details into pci_dev. */
1503 fill_data_from_hardware_ids(d, devinst, devinst_id);
1506 fill_resources(d, devinst, devinst_id);
1509 * Set parent field to cfgmgr32 parent devinst handle and backend_data field to current
1510 * devinst handle. At later stage in win32_cfgmgr32_scan() when all pci_dev
1511 * devices are linked, change every devinst handle by pci_dev.
1515 DEVINST parent_devinst;
1516 if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS)
1519 a->warning("Cannot retrieve parent handle for device %s: %s.", devinst_id, cr_strerror(cr));
1521 d->parent = (void *)parent_devinst;
1526 win32_cfgmgr32_scan(struct pci_access *a)
1528 ULONG devinst_id_list_size;
1529 PCHAR devinst_id_list;
1530 DEVINSTID_A devinst_id;
1534 if (!resolve_cfgmgr32_functions())
1536 a->warning("Required cfgmgr32.dll functions are unavailable.");
1541 * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1542 * support this API but returns CR_SUCCESS without touching size argument.
1544 devinst_id_list_size = 0;
1545 cr = CM_Get_Device_ID_List_SizeA(&devinst_id_list_size, "PCI", CM_GETIDLIST_FILTER_ENUMERATOR);
1546 if (cr != CR_SUCCESS)
1548 a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1551 else if (devinst_id_list_size <= 1)
1553 a->warning("Cannot retrieve list of PCI devices: No device was found.");
1557 devinst_id_list = pci_malloc(a, devinst_id_list_size);
1558 cr = CM_Get_Device_ID_ListA("PCI", devinst_id_list, devinst_id_list_size, CM_GETIDLIST_FILTER_ENUMERATOR);
1559 if (cr != CR_SUCCESS)
1561 a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1562 pci_mfree(devinst_id_list);
1566 /* Register pci_dev for each cfgmgr32 devinst handle. */
1567 for (devinst_id = devinst_id_list; *devinst_id; devinst_id += strlen(devinst_id) + 1)
1568 scan_devinst_id(a, devinst_id);
1570 /* Fill all drivers. */
1574 /* Switch parent fields from cfgmgr32 devinst handle to pci_dev. */
1577 struct pci_dev *d1, *d2;
1578 for (d1 = a->devices; d1; d1 = d1->next)
1580 for (d2 = a->devices; d2; d2 = d2->next)
1581 if ((DEVINST)d1->parent == (DEVINST)d2->backend_data)
1585 d1->known_fields |= PCI_FILL_PARENT;
1589 /* devinst stored in ->backend_data is not needed anymore, clear it. */
1590 for (d = a->devices; d; d = d->next)
1591 d->backend_data = NULL;
1593 pci_mfree(devinst_id_list);
1597 win32_cfgmgr32_config(struct pci_access *a)
1599 pci_define_param(a, "win32.cfgmethod", "auto", "PCI config space access method");
1603 win32_cfgmgr32_detect(struct pci_access *a)
1605 ULONG devinst_id_list_size;
1608 if (!resolve_cfgmgr32_functions())
1610 a->debug("Required cfgmgr32.dll functions are unavailable.");
1615 * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1616 * support this API but returns CR_SUCCESS without touching size argument.
1618 devinst_id_list_size = 0;
1619 cr = CM_Get_Device_ID_List_SizeA(&devinst_id_list_size, "PCI", CM_GETIDLIST_FILTER_ENUMERATOR);
1620 if (cr != CR_SUCCESS)
1622 a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): %s.", cr_strerror(cr));
1625 else if (devinst_id_list_size <= 1)
1627 a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): No device was found.");
1635 win32_cfgmgr32_fill_info(struct pci_dev *d, unsigned int flags)
1638 * All available flags were filled by win32_cfgmgr32_scan().
1639 * Filling more flags is possible only from config space.
1641 if (!d->access->backend_data)
1644 pci_generic_fill_info(d, flags);
1648 win32_cfgmgr32_read(struct pci_dev *d, int pos, byte *buf, int len)
1650 struct pci_access *a = d->access;
1651 struct pci_access *acfg = a->backend_data;
1652 struct pci_dev *dcfg = d->backend_data;
1655 return pci_emulated_read(d, pos, buf, len);
1658 d->backend_data = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
1660 return pci_read_block(dcfg, pos, buf, len);
1664 win32_cfgmgr32_write(struct pci_dev *d, int pos, byte *buf, int len)
1666 struct pci_access *a = d->access;
1667 struct pci_access *acfg = a->backend_data;
1668 struct pci_dev *dcfg = d->backend_data;
1674 d->backend_data = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
1676 return pci_write_block(dcfg, pos, buf, len);
1680 win32_cfgmgr32_cleanup_dev(struct pci_dev *d)
1682 struct pci_dev *dcfg = d->backend_data;
1689 win32_cfgmgr32_init(struct pci_access *a)
1691 char *cfgmethod = pci_get_param(a, "win32.cfgmethod");
1692 struct pci_access *acfg;
1694 if (strcmp(cfgmethod, "") == 0 ||
1695 strcmp(cfgmethod, "auto") == 0)
1697 acfg = pci_clone_access(a);
1698 acfg->method = PCI_ACCESS_AUTO;
1700 else if (strcmp(cfgmethod, "none") == 0 ||
1701 strcmp(cfgmethod, "win32-cfgmgr32") == 0)
1704 a->error("Write access requested but option win32.cfgmethod was not set.");
1709 int m = pci_lookup_method(cfgmethod);
1711 a->error("Option win32.cfgmethod is set to an unknown access method \"%s\".", cfgmethod);
1712 acfg = pci_clone_access(a);
1716 a->debug("Loading config space access method...\n");
1717 if (!pci_init_internal(acfg, PCI_ACCESS_WIN32_CFGMGR32))
1720 a->debug("Cannot find any working config space access method.\n");
1722 a->error("Write access requested but no usable access method found.");
1726 a->backend_data = acfg;
1730 win32_cfgmgr32_cleanup(struct pci_access *a)
1732 struct pci_access *acfg = a->backend_data;
1738 struct pci_methods pm_win32_cfgmgr32 = {
1740 "Win32 device listing via Configuration Manager",
1741 win32_cfgmgr32_config,
1742 win32_cfgmgr32_detect,
1743 win32_cfgmgr32_init,
1744 win32_cfgmgr32_cleanup,
1745 win32_cfgmgr32_scan,
1746 win32_cfgmgr32_fill_info,
1747 win32_cfgmgr32_read,
1748 win32_cfgmgr32_write,
1749 NULL, /* read_vpd */
1750 NULL, /* init_dev */
1751 win32_cfgmgr32_cleanup_dev,