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() */
21 /* Unfortunately MinGW32 toolchain does not provide these cfgmgr32 constants. */
23 #ifndef RegDisposition_OpenExisting
24 #define RegDisposition_OpenExisting 0x00000001
27 #ifndef CM_REGISTRY_SOFTWARE
28 #define CM_REGISTRY_SOFTWARE 0x00000001
31 #ifndef CM_DRP_HARDWAREID
32 #define CM_DRP_HARDWAREID 0x00000002
34 #ifndef CM_DRP_SERVICE
35 #define CM_DRP_SERVICE 0x00000005
37 #ifndef CM_DRP_BUSNUMBER
38 #define CM_DRP_BUSNUMBER 0x00000016
40 #ifndef CM_DRP_ADDRESS
41 #define CM_DRP_ADDRESS 0x0000001D
44 #ifndef CR_INVALID_CONFLICT_LIST
45 #define CR_INVALID_CONFLICT_LIST 0x00000039
47 #ifndef CR_INVALID_INDEX
48 #define CR_INVALID_INDEX 0x0000003A
50 #ifndef CR_INVALID_STRUCTURE_SIZE
51 #define CR_INVALID_STRUCTURE_SIZE 0x0000003B
54 #ifndef fIOD_10_BIT_DECODE
55 #define fIOD_10_BIT_DECODE 0x0004
57 #ifndef fIOD_12_BIT_DECODE
58 #define fIOD_12_BIT_DECODE 0x0008
60 #ifndef fIOD_16_BIT_DECODE
61 #define fIOD_16_BIT_DECODE 0x0010
63 #ifndef fIOD_POSITIVE_DECODE
64 #define fIOD_POSITIVE_DECODE 0x0020
66 #ifndef fIOD_PASSIVE_DECODE
67 #define fIOD_PASSIVE_DECODE 0x0040
69 #ifndef fIOD_WINDOW_DECODE
70 #define fIOD_WINDOW_DECODE 0x0080
73 #define fIOD_PORT_BAR 0x0100
76 #ifndef fMD_WINDOW_DECODE
77 #define fMD_WINDOW_DECODE 0x0040
79 #ifndef fMD_MEMORY_BAR
80 #define fMD_MEMORY_BAR 0x0080
84 * Unfortunately MinGW32 toolchain does not provide import library for these
85 * cfgmgr32.dll functions. So resolve pointers to these functions at runtime.
88 #ifdef CM_Get_DevNode_Registry_PropertyA
89 #undef CM_Get_DevNode_Registry_PropertyA
91 static CONFIGRET (WINAPI *MyCM_Get_DevNode_Registry_PropertyA)(DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType, PVOID Buffer, PULONG pulLength, ULONG ulFlags);
92 #define CM_Get_DevNode_Registry_PropertyA MyCM_Get_DevNode_Registry_PropertyA
94 #ifdef CM_Get_DevNode_Registry_PropertyW
95 #undef CM_Get_DevNode_Registry_PropertyW
97 static CONFIGRET (WINAPI *MyCM_Get_DevNode_Registry_PropertyW)(DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType, PVOID Buffer, PULONG pulLength, ULONG ulFlags);
98 #define CM_Get_DevNode_Registry_PropertyW MyCM_Get_DevNode_Registry_PropertyW
100 #ifndef CM_Open_DevNode_Key
101 #undef CM_Open_DevNode_Key
103 static CONFIGRET (WINAPI *MyCM_Open_DevNode_Key)(DEVINST dnDevNode, REGSAM samDesired, ULONG ulHardwareProfile, REGDISPOSITION Disposition, PHKEY phkDevice, ULONG ulFlags);
104 #define CM_Open_DevNode_Key MyCM_Open_DevNode_Key
107 resolve_cfgmgr32_functions(void)
111 if (CM_Get_DevNode_Registry_PropertyA && CM_Get_DevNode_Registry_PropertyW && CM_Open_DevNode_Key)
114 cfgmgr32 = GetModuleHandleA("cfgmgr32.dll");
118 CM_Get_DevNode_Registry_PropertyA = (void *)GetProcAddress(cfgmgr32, "CM_Get_DevNode_Registry_PropertyA");
119 CM_Get_DevNode_Registry_PropertyW = (void *)GetProcAddress(cfgmgr32, "CM_Get_DevNode_Registry_PropertyW");
120 CM_Open_DevNode_Key = (void *)GetProcAddress(cfgmgr32, "CM_Open_DevNode_Key");
121 if (!CM_Get_DevNode_Registry_PropertyA || !CM_Get_DevNode_Registry_PropertyW || !CM_Open_DevNode_Key)
128 * cfgmgr32.dll uses custom non-Win32 error numbers which are unsupported by
129 * Win32 APIs like GetLastError() and FormatMessage() functions.
131 * Windows 7 introduced new cfgmgr32.dll function CM_MapCrToWin32Err() for
132 * translating mapping CR_* errors to Win32 errors but most error codes are
133 * not mapped. So this function is unusable.
135 * Error strings for CR_* errors are defined in cmapi.rc file which is
136 * statically linked into some system libraries (e.g. filemgmt.dll,
137 * acledit.dll, netui0.dll or netui2.dll) but due to static linking it is
138 * not possible to access these error strings easily at runtime.
140 * So define own function for translating CR_* errors directly to strings.
143 cr_strerror(CONFIGRET cr_error_id)
145 static char unknown_error[sizeof("Unknown CR error XXXXXXXXXX")];
146 static const char *cr_errors[] = {
147 "The operation completed successfully",
149 "Not enough memory is available to process this command",
150 "A required pointer parameter is invalid",
151 "The ulFlags parameter specified is invalid for this operation",
152 "The device instance handle parameter is not valid",
153 "The supplied resource descriptor parameter is invalid",
154 "The supplied logical configuration parameter is invalid",
155 "CR_INVALID_ARBITRATOR",
156 "CR_INVALID_NODELIST",
157 "CR_DEVNODE_HAS_REQS/CR_DEVINST_HAS_REQS",
158 "The RESOURCEID parameter does not contain a valid RESOURCEID",
159 "CR_DLVXD_NOT_FOUND",
160 "The specified device instance handle does not correspond to a present device",
161 "There are no more logical configurations available",
162 "There are no more resource descriptions available",
163 "This device instance already exists",
164 "The supplied range list parameter is invalid",
166 "A general internal error occurred",
167 "CR_NO_SUCH_LOGICAL_DEV",
168 "The device is disabled for this configuration",
170 "A service or application refused to allow removal of this device",
172 "CR_INVALID_LOAD_TYPE",
173 "An output parameter was too small to hold all the data available",
175 "CR_NO_REGISTRY_HANDLE",
176 "A required entry in the registry is missing or an attempt to write to the registry failed",
177 "The specified Device ID is not a valid Device ID",
178 "One or more parameters were invalid",
180 "CR_DEVLOADER_NOT_READY",
182 "There are no more hardware profiles available",
183 "CR_DEVICE_NOT_THERE",
184 "The specified value does not exist in the registry",
186 "The specified priority is invalid for this operation",
187 "This device cannot be disabled",
193 "The specified key does not exist in the registry",
194 "The specified machine name does not meet the UNC naming conventions",
195 "A general remote communication error occurred",
196 "The machine selected for remote communication is not available at this time",
197 "The Plug and Play service or another required service is not available",
199 "This routine is not implemented in this version of the operating system",
200 "The specified property type is invalid for this operation",
201 "Device interface is active",
202 "No such device interface",
203 "Invalid reference string",
204 "Invalid conflict list",
206 "Invalid structure size"
208 if (cr_error_id <= 0 || cr_error_id >= sizeof(cr_errors)/sizeof(*cr_errors))
210 sprintf(unknown_error, "Unknown CR error %lu", cr_error_id);
211 return unknown_error;
213 return cr_errors[cr_error_id];
217 win32_strerror(DWORD win32_error_id)
220 * Use static buffer which is large enough.
221 * Hopefully no Win32 API error message string is longer than 4 kB.
223 static char buffer[4096];
226 len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, win32_error_id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, sizeof(buffer), NULL);
228 /* FormatMessage() automatically appends ".\r\n" to the error message. */
229 if (len && buffer[len-1] == '\n')
230 buffer[--len] = '\0';
231 if (len && buffer[len-1] == '\r')
232 buffer[--len] = '\0';
233 if (len && buffer[len-1] == '.')
234 buffer[--len] = '\0';
237 sprintf(buffer, "Unknown Win32 error %lu", win32_error_id);
243 fmt_validate(const char *s, int len, const char *fmt)
247 for (i = 0; i < len; i++)
248 if (!fmt[i] || (fmt[i] == '#' ? !isxdigit(s[i]) : fmt[i] != s[i]))
255 seq_xdigit_validate(const char *s, int mult, int min)
260 if (len < min*mult || len % mult)
263 for (i = 0; i < len; i++)
271 is_non_nt_system(void)
273 OSVERSIONINFOA version;
274 version.dwOSVersionInfoSize = sizeof(version);
275 return GetVersionExA(&version) && version.dwPlatformId < VER_PLATFORM_WIN32_NT;
279 is_32bit_on_win8_64bit_system(void)
284 BOOL (WINAPI *MyIsWow64Process)(HANDLE, PBOOL);
285 OSVERSIONINFOA version;
289 /* Check for Windows 8 (NT 6.2). */
290 version.dwOSVersionInfoSize = sizeof(version);
291 if (!GetVersionExA(&version) ||
292 version.dwPlatformId != VER_PLATFORM_WIN32_NT ||
293 version.dwMajorVersion < 6 ||
294 (version.dwMajorVersion == 6 && version.dwMinorVersion < 2))
298 * Check for 64-bit system via IsWow64Process() function exported
299 * from 32-bit kernel32.dll library available on the 64-bit systems.
300 * Resolve pointer to this function at runtime as this code path is
301 * primary running on 32-bit systems where are not available 64-bit
305 kernel32 = GetModuleHandleA("kernel32.dll");
309 MyIsWow64Process = (void *)GetProcAddress(kernel32, "IsWow64Process");
310 if (!MyIsWow64Process)
313 if (!MyIsWow64Process(GetCurrentProcess(), &is_wow64))
321 get_device_service_name(struct pci_access *a, DEVINST devinst, DEVINSTID_A devinst_id, BOOL *supported)
323 ULONG reg_type, reg_size, reg_len;
328 * All data are stored as 7-bit ASCII strings in system but service name is
329 * exception. It can contain UNICODE. Moreover it is passed to other Win32 API
330 * functions and therefore it cannot be converted to 8-bit ANSI string without
331 * data loss. So use wide function CM_Get_DevNode_Registry_PropertyW() in this
332 * case and deal with all wchar_t problems...
336 cr = CM_Get_DevNode_Registry_PropertyW(devinst, CM_DRP_SERVICE, ®_type, NULL, ®_size, 0);
337 if (cr == CR_CALL_NOT_IMPLEMENTED)
342 else if (cr == CR_NO_SUCH_VALUE)
347 else if (cr != CR_SUCCESS &&
348 cr != CR_BUFFER_SMALL)
350 a->warning("Cannot retrieve service name for PCI device %s: %s.", devinst_id, cr_strerror(cr));
354 else if (reg_type != REG_SZ)
356 a->warning("Cannot retrieve service name for PCI device %s: Service name is stored as unknown type 0x%lx.", devinst_id, reg_type);
363 * Returned size is on older Windows versions without nul-term char.
364 * So explicitly increase size and fill nul-term byte.
366 reg_size += sizeof(service_name[0]);
367 service_name = pci_malloc(a, reg_size);
369 cr = CM_Get_DevNode_Registry_PropertyW(devinst, CM_DRP_SERVICE, ®_type, service_name, ®_len, 0);
370 service_name[reg_size/sizeof(service_name[0]) - 1] = 0;
371 if (reg_len > reg_size)
373 pci_mfree(service_name);
377 else if (cr != CR_SUCCESS)
379 a->warning("Cannot retrieve service name for PCI device %s: %s.", devinst_id, cr_strerror(cr));
380 pci_mfree(service_name);
384 else if (reg_type != REG_SZ)
386 a->warning("Cannot retrieve service name for PCI device %s: Service name is stored as unknown type 0x%lx.", devinst_id, reg_type);
387 pci_mfree(service_name);
397 get_driver_path_for_service(struct pci_access *a, LPCWSTR service_name, SC_HANDLE manager)
399 UINT (WINAPI *get_system_root_path)(LPWSTR buffer, UINT size) = NULL;
400 DWORD service_config_size, service_config_len;
401 LPQUERY_SERVICE_CONFIGW service_config = NULL;
402 LPWSTR service_image_path = NULL;
403 SERVICE_STATUS service_status;
404 SC_HANDLE service = NULL;
405 char *driver_path = NULL;
406 int trim_system32 = 0;
414 service = OpenServiceW(manager, service_name, SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS);
417 error = GetLastError();
418 if (error != ERROR_SERVICE_DOES_NOT_EXIST)
419 a->warning("Cannot open service %ls with query rights: %s.", service_name, win32_strerror(error));
423 if (!QueryServiceStatus(service, &service_status))
425 error = GetLastError();
426 a->warning("Cannot query status of service %ls: %s.", service_name, win32_strerror(error));
430 if (service_status.dwCurrentState == SERVICE_STOPPED)
433 if (service_status.dwServiceType != SERVICE_KERNEL_DRIVER)
436 if (!QueryServiceConfigW(service, NULL, 0, &service_config_size))
438 error = GetLastError();
439 if (error != ERROR_INSUFFICIENT_BUFFER)
441 a->warning("Cannot query config of service %ls: %s.", service_name, win32_strerror(error));
446 retry_service_config:
447 service_config = pci_malloc(a, service_config_size);
448 if (!QueryServiceConfigW(service, service_config, service_config_size, &service_config_len))
450 error = GetLastError();
451 if (error == ERROR_INSUFFICIENT_BUFFER)
453 pci_mfree(service_config);
454 service_config_size = service_config_len;
455 goto retry_service_config;
457 a->warning("Cannot query config of service %ls: %s.", service_name, win32_strerror(error));
461 if (service_config->dwServiceType != SERVICE_KERNEL_DRIVER)
465 * Despite QueryServiceConfig() is Win32 API, it returns lpBinaryPathName
466 * (ImagePath registry) in NT format. Unfortunately there is no Win32
467 * function for converting NT paths to Win32 paths. So do it manually and
468 * convert this NT format to human-readable Win32 path format.
472 * GetSystemWindowsDirectoryW() returns path to NT SystemRoot namespace.
473 * Alternativelly path to NT SystemRoot namespace can be constructed by
474 * GetSystemDirectoryW() by trimming "\\system32" from the end of path.
475 * GetSystemWindowsDirectoryW() is not provided in old Windows versions,
476 * so use GetProcAddress() for compatibility with all Windows versions.
478 kernel32 = GetModuleHandleW(L"kernel32.dll");
480 get_system_root_path = (void *)GetProcAddress(kernel32, "GetSystemWindowsDirectoryW");
483 get_system_root_path = &GetSystemDirectoryW;
487 if (!service_config->lpBinaryPathName || !service_config->lpBinaryPathName[0])
489 /* No ImagePath is specified, NT kernel assumes implicit kernel driver path by service name, which is relative to "\\system32\\drivers". */
490 /* GetSystemDirectoryW() returns path to "\\system32" directory on all Windows versions. */
491 system32_len = GetSystemDirectoryW(NULL, 0); /* Returns number of WCHARs plus 1 for nul-term. */
492 service_image_path = pci_malloc(a, sizeof(WCHAR) * (system32_len + sizeof("\\drivers\\")-1 + wcslen(service_name) + sizeof(".sys")-1));
493 system32_len = GetSystemDirectoryW(service_image_path, system32_len); /* Now it returns number of WCHARs without nul-term. */
494 if (system32_len && service_image_path[system32_len-1] != L'\\')
495 service_image_path[system32_len++] = L'\\';
496 wcscpy(service_image_path + system32_len, L"drivers\\");
497 wcscpy(service_image_path + system32_len + sizeof("drivers\\")-1, service_name);
498 wcscpy(service_image_path + system32_len + sizeof("drivers\\")-1 + wcslen(service_name), L".sys");
500 else if (wcsncmp(service_config->lpBinaryPathName, L"\\SystemRoot\\", sizeof("\\SystemRoot\\")-1) == 0)
502 /* ImagePath is in NT SystemRoot namespace, convert to Win32 path via GetSystemWindowsDirectoryW()/GetSystemDirectoryW(). */
503 systemroot_len = get_system_root_path(NULL, 0); /* Returns number of WCHARs plus 1 for nul-term. */
504 service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + wcslen(service_config->lpBinaryPathName) - (sizeof("\\SystemRoot")-1)));
505 systemroot_len = get_system_root_path(service_image_path, systemroot_len); /* Now it returns number of WCHARs without nul-term. */
506 if (trim_system32 && systemroot_len && (trim_ptr = wcsrchr(service_image_path, L'\\')) != NULL)
507 systemroot_len = trim_ptr - service_image_path;
508 if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
509 service_image_path[systemroot_len++] = L'\\';
510 wcscpy(service_image_path + systemroot_len, service_config->lpBinaryPathName + sizeof("\\SystemRoot\\")-1);
512 else if (wcsncmp(service_config->lpBinaryPathName, L"\\??\\UNC\\", sizeof("\\??\\UNC\\")-1) == 0 ||
513 wcsncmp(service_config->lpBinaryPathName, L"\\??\\\\UNC\\", sizeof("\\??\\\\UNC\\")-1) == 0)
515 /* ImagePath is in NT UNC namespace, convert to Win32 UNC path via "\\\\" prefix. */
516 service_image_path = pci_malloc(a, sizeof(WCHAR) * (sizeof("\\\\") + wcslen(service_config->lpBinaryPathName) - (sizeof("\\??\\UNC\\")-1)));
517 /* Namespace separator may be single or double backslash. */
518 driver_path_len = sizeof("\\??\\")-1;
519 if (service_config->lpBinaryPathName[driver_path_len] == L'\\')
521 driver_path_len += sizeof("UNC\\")-1;
522 wcscpy(service_image_path, L"\\\\");
523 wcscpy(service_image_path + sizeof("\\\\")-1, service_config->lpBinaryPathName + driver_path_len);
525 else if (wcsncmp(service_config->lpBinaryPathName, L"\\??\\", sizeof("\\??\\")-1) == 0)
527 /* ImagePath is in NT Global?? namespace, root of the Win32 file namespace, so just remove "\\??\\" prefix to get Win32 path. */
528 service_image_path = pci_malloc(a, sizeof(WCHAR) * (wcslen(service_config->lpBinaryPathName) - (sizeof("\\??\\")-1)));
529 /* Namespace separator may be single or double backslash. */
530 driver_path_len = sizeof("\\??\\")-1;
531 if (service_config->lpBinaryPathName[driver_path_len] == L'\\')
533 wcscpy(service_image_path, service_config->lpBinaryPathName + driver_path_len);
535 else if (service_config->lpBinaryPathName[0] != L'\\')
537 /* ImagePath is relative to the NT SystemRoot namespace, convert to Win32 path via GetSystemWindowsDirectoryW()/GetSystemDirectoryW(). */
538 systemroot_len = get_system_root_path(NULL, 0); /* Returns number of WCHARs plus 1 for nul-term. */
539 service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + sizeof("\\")-1 + wcslen(service_config->lpBinaryPathName)));
540 systemroot_len = get_system_root_path(service_image_path, systemroot_len); /* Now it returns number of WCHARs without nul-term. */
541 if (trim_system32 && systemroot_len && (trim_ptr = wcsrchr(service_image_path, L'\\')) != NULL)
542 systemroot_len = trim_ptr - service_image_path;
543 if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
544 service_image_path[systemroot_len++] = L'\\';
545 wcscpy(service_image_path + systemroot_len, service_config->lpBinaryPathName);
549 /* 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. */
550 service_image_path = pci_malloc(a, sizeof(WCHAR) * wcslen(service_config->lpBinaryPathName));
551 wcscpy(service_image_path, service_config->lpBinaryPathName);
554 /* Calculate len of buffer needed for conversion from LPWSTR to char*. */
555 driver_path_len = WideCharToMultiByte(CP_ACP, 0, service_image_path, -1, NULL, 0, NULL, NULL);
556 if (driver_path_len <= 0)
558 error = GetLastError();
559 a->warning("Cannot convert kernel driver path from wide string to 8-bit string: %s.", win32_strerror(error));
563 driver_path = pci_malloc(a, driver_path_len);
564 driver_path_len = WideCharToMultiByte(CP_ACP, 0, service_image_path, -1, driver_path, driver_path_len, NULL, NULL);
565 if (driver_path_len <= 0)
567 error = GetLastError();
568 a->warning("Cannot convert kernel driver path from wide string to 8-bit string: %s.", win32_strerror(error));
569 pci_mfree(driver_path);
575 if (service_image_path)
576 pci_mfree(service_image_path);
578 pci_mfree(service_config);
580 CloseServiceHandle(service);
585 get_device_driver_devreg(struct pci_access *a, DEVINST devinst, DEVINSTID_A devinst_id)
590 cr = CM_Open_DevNode_Key(devinst, KEY_READ, 0, RegDisposition_OpenExisting, &key, CM_REGISTRY_SOFTWARE);
591 if (cr != CR_SUCCESS)
593 if (cr != CR_NO_SUCH_VALUE)
594 a->warning("Cannot retrieve driver key for device %s: %s.", devinst_id, cr_strerror(cr));
602 read_reg_key_string_value(struct pci_access *a, HKEY key, const char *name, DWORD *unkn_reg_type)
604 DWORD reg_type, reg_size, reg_len;
609 error = RegQueryValueExA(key, name, NULL, ®_type, NULL, ®_size);
610 if (error != ERROR_SUCCESS &&
611 error != ERROR_MORE_DATA)
616 else if (reg_type != REG_SZ)
619 *unkn_reg_type = reg_type;
624 value = pci_malloc(a, reg_size + 1);
626 error = RegQueryValueExA(key, name, NULL, ®_type, (PBYTE)value, ®_len);
627 if (error != ERROR_SUCCESS)
630 if (error == ERROR_MORE_DATA)
638 else if (reg_type != REG_SZ)
642 *unkn_reg_type = reg_type;
645 value[reg_len] = '\0';
651 driver_cmp(const char *driver, const char *match)
653 int len = strlen(driver);
654 if (driver[0] == '*')
656 if (len >= 4 && strcasecmp(driver + len - 4, ".vxd") == 0)
658 return strncasecmp(driver, match, len);
662 get_driver_path_for_regkey(struct pci_access *a, DEVINSTID_A devinst_id, HKEY key)
664 char *driver_list, *driver, *driver_next;
665 char *subdriver, *subname;
676 driver_list = read_reg_key_string_value(a, key, "DevLoader", &unkn_reg_type);
679 error = GetLastError();
681 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);
682 else if (error != ERROR_FILE_NOT_FOUND)
683 a->warning("Cannot read driver DevLoader key for PCI device %s: %s.", devinst_id, win32_strerror(error));
688 driver = driver_list;
691 driver_next = strchr(driver, ',');
693 *(driver_next++) = '\0';
695 if (driver_cmp(driver, "ios") == 0 ||
696 driver_cmp(driver, "vcomm") == 0)
697 subname = "PortDriver";
698 else if (driver_cmp(driver, "ntkern") == 0)
699 subname = "NTMPDriver";
700 else if (driver_cmp(driver, "ndis") == 0)
701 subname = "DeviceVxDs";
702 else if (driver_cmp(driver, "vdd") == 0)
708 if (subname && strcmp(subname, "minivdd") == 0)
710 error = RegOpenKeyA(key, "Default", &subkey);
711 if (error != ERROR_SUCCESS)
713 a->warning("Cannot open driver subkey Default for PCI device %s: %s.", devinst_id, win32_strerror(error));
724 subdriver = read_reg_key_string_value(a, subkey, subname, &unkn_reg_type);
727 error = GetLastError();
729 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);
730 else if (error != ERROR_FILE_NOT_FOUND)
731 a->warning("Cannot read driver %s key for PCI device %s: %s.", subname, devinst_id, win32_strerror(error));
732 else if (strcmp(subname, "minivdd") == 0)
737 else if (strcmp(subname, "drv") == 0)
749 char *endptr = strchr(subdriver, ',');
756 driver = driver_next;
759 if (subdriver && subdriver[0])
760 driver_ptr = subdriver;
766 if (driver_ptr && driver_ptr[0] == '*')
777 len = driver_ptr ? strlen(driver_ptr) : 0;
778 noext = driver_ptr && (len < 4 || driver_ptr[len-4] != '.');
784 if (tolower(driver_ptr[0]) >= 'a' && tolower(driver_ptr[0]) <= 'z' && driver_ptr[1] == ':')
786 /* Driver is already with absolute path. */
787 driver_path = pci_strdup(a, driver_ptr);
789 else if (driver_cmp(driver, "ntkern") == 0 && subdriver)
791 /* Driver is relative to system32\drivers\ directory which is relative to windows directory. */
792 systemdir_len = GetWindowsDirectoryA(NULL, 0);
793 driver_path = pci_malloc(a, systemdir_len + 1 + sizeof("system32\\drivers\\")-1 + strlen(driver_ptr) + 4 + 1);
794 systemdir_len = GetWindowsDirectoryA(driver_path, systemdir_len + 1);
795 if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
796 driver_path[systemdir_len++] = '\\';
797 sprintf(driver_path + systemdir_len, "system32\\drivers\\%s%s", driver_ptr, noext ? ".sys" : "");
801 /* Driver is packed in vmm32.vxd which is stored in system directory. */
802 systemdir_len = GetSystemDirectoryA(NULL, 0);
803 driver_path = pci_malloc(a, systemdir_len + 1 + sizeof("vmm32.vxd ()")-1 + strlen(driver_ptr) + 4 + 1);
804 systemdir_len = GetSystemDirectoryA(driver_path, systemdir_len + 1);
805 if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
806 driver_path[systemdir_len++] = '\\';
807 sprintf(driver_path + systemdir_len, "vmm32.vxd (%s%s)", driver_ptr, noext ? ".vxd" : "");
811 /* Otherwise driver is relative to system directory. */
812 systemdir_len = GetSystemDirectoryA(NULL, 0);
813 driver_path = pci_malloc(a, systemdir_len + 1 + strlen(driver_ptr) + 4 + 1);
814 systemdir_len = GetSystemDirectoryA(driver_path, systemdir_len + 1);
815 if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
816 driver_path[systemdir_len++] = '\\';
817 sprintf(driver_path + systemdir_len, "%s%s", driver_ptr, noext ? ".vxd" : "");
822 pci_mfree(subdriver);
823 pci_mfree(driver_list);
828 get_device_driver_path(struct pci_dev *d, SC_HANDLE manager, BOOL manager_supported)
830 struct pci_access *a = d->access;
831 BOOL service_supported = TRUE;
832 DEVINSTID_A devinst_id = NULL;
833 LPWSTR service_name = NULL;
834 ULONG devinst_id_len = 0;
835 char *driver_path = NULL;
836 DEVINST devinst = (DEVINST)d->backend_data;
841 if (CM_Get_DevNode_Status(&status, &problem, devinst, 0) != CR_SUCCESS || !(status & DN_DRIVER_LOADED))
844 if (CM_Get_Device_ID_Size(&devinst_id_len, devinst, 0) == CR_SUCCESS)
846 devinst_id = pci_malloc(a, devinst_id_len + 1);
847 if (CM_Get_Device_IDA(devinst, devinst_id, devinst_id_len + 1, 0) != CR_SUCCESS)
849 pci_mfree(devinst_id);
850 devinst_id = pci_strdup(a, "UNKNOWN");
854 devinst_id = pci_strdup(a, "UNKNOWN");
856 service_name = get_device_service_name(d->access, devinst, devinst_id, &service_supported);
857 if ((!service_name || !manager) && service_supported && manager_supported)
859 else if (service_name && manager)
861 driver_path = get_driver_path_for_service(d->access, service_name, manager);
865 key = get_device_driver_devreg(d->access, devinst, devinst_id);
868 driver_path = get_driver_path_for_regkey(d->access, devinst_id, key);
876 pci_mfree(service_name);
877 pci_mfree(devinst_id);
882 fill_drivers(struct pci_access *a)
884 BOOL manager_supported;
890 /* ERROR_CALL_NOT_IMPLEMENTED is returned on systems without Service Manager support. */
891 manager_supported = TRUE;
892 manager = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
895 error = GetLastError();
896 if (error != ERROR_CALL_NOT_IMPLEMENTED)
897 a->warning("Cannot open Service Manager with connect right: %s.", win32_strerror(error));
899 manager_supported = FALSE;
902 for (d = a->devices; d; d = d->next)
904 driver = get_device_driver_path(d, manager, manager_supported);
907 pci_set_property(d, PCI_FILL_DRIVER, driver);
910 d->known_fields |= PCI_FILL_DRIVER;
914 CloseServiceHandle(manager);
918 res_id_to_str(RESOURCEID res_id)
920 static char hex_res_id[sizeof("0xffffffff")];
922 if (res_id == ResType_IO)
924 else if (res_id == ResType_Mem)
926 else if (res_id == ResType_IRQ)
929 sprintf(hex_res_id, "0x%lx", res_id);
934 fill_resources(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
936 struct pci_access *a = d->access;
944 RES_DES prev_res_des;
953 int last_shared_irq = -1;
955 cr = CM_Get_DevNode_Status(&status, &problem, devinst, 0);
956 if (cr != CR_SUCCESS)
958 a->warning("Cannot retrieve status of PCI device %s: %s.", devinst_id, cr_strerror(cr));
962 cr = CR_NO_MORE_LOG_CONF;
965 * If the device is running then retrieve allocated configuration by PnP
966 * manager which is currently in use by a device.
968 if (!(status & DN_HAS_PROBLEM))
969 cr = CM_Get_First_Log_Conf(&config, devinst, ALLOC_LOG_CONF);
972 * If the device is not running or it does not have allocated configuration by
973 * PnP manager then retrieve forced configuration which prevents PnP manager
974 * from assigning resources.
976 if (cr == CR_NO_MORE_LOG_CONF)
977 cr = CM_Get_First_Log_Conf(&config, devinst, FORCED_LOG_CONF);
980 * If the device does not have neither allocated configuration by PnP manager
981 * nor forced configuration and it is not disabled in the BIOS then retrieve
982 * boot configuration supplied by the BIOS.
984 if (cr == CR_NO_MORE_LOG_CONF &&
985 (!(status & DN_HAS_PROBLEM) || problem != CM_PROB_HARDWARE_DISABLED))
986 cr = CM_Get_First_Log_Conf(&config, devinst, BOOT_LOG_CONF);
988 if (cr != CR_SUCCESS)
991 * Note: Starting with Windows 8, CM_Get_First_Log_Conf returns
992 * CR_CALL_NOT_IMPLEMENTED when used in a Wow64 scenario.
993 * To request information about the hardware resources on a local machine
994 * it is necessary implement an architecture-native version of the
995 * application using the hardware resource APIs. For example: An AMD64
996 * application for AMD64 systems.
998 if (cr == CR_CALL_NOT_IMPLEMENTED && is_32bit_on_win8_64bit_system())
1000 static BOOL warn_once = FALSE;
1004 a->warning("Cannot retrieve resources of PCI devices from 32-bit application on 64-bit system.");
1007 else if (cr != CR_NO_MORE_LOG_CONF)
1008 a->warning("Cannot retrieve resources of PCI device %s: %s.", devinst_id, cr_strerror(cr));
1013 non_nt_system = is_non_nt_system();
1020 ULONG child_name_len;
1024 if (CM_Get_Child(&child, devinst, 0) != CR_SUCCESS)
1026 else if (CM_Get_Device_ID_Size(&child_name_len, child, 0) != CR_SUCCESS)
1031 child_name = pci_malloc(a, child_name_len);
1032 if (CM_Get_Device_IDA(child, child_name, child_name_len, 0) != CR_SUCCESS)
1034 else if (strncmp(child_name, "PCI\\", 4) != 0)
1038 pci_mfree(child_name);
1041 if (has_child || d->device_class == PCI_CLASS_BRIDGE_PCI || d->device_class == PCI_CLASS_BRIDGE_CARDBUS)
1050 prev_res_des = (RES_DES)config;
1051 while ((cr = CM_Get_Next_Res_Des(&res_des, prev_res_des, ResType_All, &res_id, 0)) == CR_SUCCESS)
1053 pciaddr_t start, end, size, flags;
1054 ULONG res_des_data_size;
1057 if (prev_res_des != config)
1058 CM_Free_Res_Des_Handle(prev_res_des);
1060 prev_res_des = res_des;
1062 /* Skip other resources early */
1063 if (res_id != ResType_IO && res_id != ResType_Mem && res_id != ResType_IRQ)
1066 cr = CM_Get_Res_Des_Data_Size(&res_des_data_size, res_des, 0);
1067 if (cr != CR_SUCCESS)
1069 a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, cr_strerror(cr));
1073 if (!res_des_data_size)
1075 a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, "Empty data");
1079 res_des_data = pci_malloc(a, res_des_data_size);
1080 cr = CM_Get_Res_Des_Data(res_des, res_des_data, res_des_data_size, 0);
1081 if (cr != CR_SUCCESS)
1083 a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, cr_strerror(cr));
1084 pci_mfree(res_des_data);
1089 * There can be more resources with the same id. In this case we are
1090 * interested in the last one in the list as at the beginning of the list
1091 * can be some virtual resources (which are not set in PCI config space).
1094 if (res_id == ResType_IO)
1096 PIO_RESOURCE io_data = (PIO_RESOURCE)res_des_data;
1098 start = io_data->IO_Header.IOD_Alloc_Base;
1099 end = io_data->IO_Header.IOD_Alloc_End;
1100 size = (end > start) ? (end - start + 1) : 0;
1101 flags = PCI_IORESOURCE_IO;
1104 * If neither 10-bit, 12-bit, nor 16-bit support is presented then
1105 * expects that this is 32-bit I/O resource. If resource does not fit
1106 * into 16-bit space then it must be 32-bit. If PCI I/O resource is
1107 * not 32-bit then it is 16-bit.
1109 if (end <= 0xffff && (io_data->IO_Header.IOD_DesFlags & (fIOD_10_BIT_DECODE|fIOD_12_BIT_DECODE|fIOD_16_BIT_DECODE)))
1110 flags |= PCI_IORESOURCE_IO_16BIT_ADDR;
1113 * 16/32-bit non-NT systems do not support these two flags.
1114 * Most NT-based Windows versions support only the fIOD_WINDOW_DECODE
1115 * flag and put all BAR resources before window resources in this
1116 * resource list. So use this fIOD_WINDOW_DECODE flag as separator
1117 * between IO/MEM windows and IO/MEM BARs of PCI Bridges.
1119 if (io_data->IO_Header.IOD_DesFlags & fIOD_WINDOW_DECODE)
1121 else if (io_data->IO_Header.IOD_DesFlags & fIOD_PORT_BAR)
1124 if (is_bar_res && bar_res_count < 6)
1126 d->flags[bar_res_count] = flags;
1127 d->base_addr[bar_res_count] = start;
1128 d->size[bar_res_count] = size;
1131 else if (!is_bar_res)
1133 d->bridge_flags[0] = flags;
1134 d->bridge_base_addr[0] = start;
1135 d->bridge_size[0] = size;
1136 d->known_fields |= PCI_FILL_BRIDGE_BASES;
1139 else if (res_id == ResType_Mem)
1141 PMEM_RESOURCE mem_data = (PMEM_RESOURCE)res_des_data;
1143 start = mem_data->MEM_Header.MD_Alloc_Base;
1144 end = mem_data->MEM_Header.MD_Alloc_End;
1145 size = (end > start) ? (end - start + 1) : 0;
1146 flags = PCI_IORESOURCE_MEM;
1149 * If fMD_PrefetchAllowed flag is set then this is
1150 * PCI Prefetchable Memory resource.
1152 if ((mem_data->MEM_Header.MD_Flags & mMD_Prefetchable) == fMD_PrefetchAllowed)
1153 flags |= PCI_IORESOURCE_PREFETCH;
1155 /* If resource does not fit into 32-bit space then it must be 64-bit. */
1156 if (is_bar_res && end > 0xffffffff)
1157 flags |= PCI_IORESOURCE_MEM_64;
1160 * These two flags (fMD_WINDOW_DECODE and fMD_MEMORY_BAR) are
1161 * unsupported on most Windows versions, so distinguish between
1162 * window and BAR based on previous resource type.
1164 if (mem_data->MEM_Header.MD_Flags & fMD_WINDOW_DECODE)
1166 else if (mem_data->MEM_Header.MD_Flags & fMD_MEMORY_BAR)
1169 /* 64-bit BAR resource must be at even position. */
1170 if (is_bar_res && (flags & PCI_IORESOURCE_MEM_64) && bar_res_count % 2)
1173 if (is_bar_res && bar_res_count < 6)
1175 d->flags[bar_res_count] = flags;
1176 d->base_addr[bar_res_count] = start;
1177 d->size[bar_res_count] = size;
1179 /* 64-bit BAR resource occupies two slots. */
1180 if (flags & PCI_IORESOURCE_MEM_64)
1183 else if (!is_bar_res && !(flags & PCI_IORESOURCE_PREFETCH))
1185 d->bridge_flags[1] = flags;
1186 d->bridge_base_addr[1] = start;
1187 d->bridge_size[1] = size;
1188 d->known_fields |= PCI_FILL_BRIDGE_BASES;
1190 else if (!is_bar_res && (flags & PCI_IORESOURCE_PREFETCH))
1192 d->bridge_flags[2] = flags;
1193 d->bridge_base_addr[2] = start;
1194 d->bridge_size[2] = size;
1195 d->known_fields |= PCI_FILL_BRIDGE_BASES;
1198 else if (res_id == ResType_IRQ)
1200 PIRQ_RESOURCE irq_data = (PIRQ_RESOURCE)res_des_data;
1203 * libpci's d->irq should be set to the non-MSI PCI IRQ and therefore
1204 * it should be level IRQ which may be shared with other PCI devices
1205 * and drivers in the system. As always we want to retrieve the last
1206 * IRQ number from the resource list.
1208 * On 16/32-bit non-NT systems is fIRQD_Level set to 2 but on NT
1209 * systems to 0. Moreover it looks like that different PCI drivers
1210 * on both NT and non-NT systems set bits 0 and 1 to wrong values
1211 * and so reported value in this list may be incorrect.
1213 * Therefore take the last level-shared IRQ number from the resource
1214 * list and if there is none of this type then take the last IRQ
1215 * number from the list.
1217 last_irq = irq_data->IRQ_Header.IRQD_Alloc_Num;
1218 if ((irq_data->IRQ_Header.IRQD_Flags & (mIRQD_Share|mIRQD_Edge_Level)) == (fIRQD_Share|fIRQD_Level))
1219 last_shared_irq = irq_data->IRQ_Header.IRQD_Alloc_Num;
1222 * IRQ resource on 16/32-bit non-NT systems is separator between
1223 * IO/MEM windows and IO/MEM BARs of PCI Bridges. After the IRQ
1224 * resource are IO/MEM BAR resources.
1226 if (!is_bar_res && non_nt_system)
1230 pci_mfree(res_des_data);
1232 if (cr != CR_NO_MORE_RES_DES)
1233 a->warning("Cannot retrieve resources of PCI device %s: %s.", devinst_id, cr_strerror(cr));
1235 if (prev_res_des != config)
1236 CM_Free_Res_Des_Handle(prev_res_des);
1238 CM_Free_Log_Conf_Handle(config);
1240 /* Set the last IRQ from the resource list to pci_dev. */
1241 if (last_shared_irq >= 0)
1242 d->irq = last_shared_irq;
1243 else if (last_irq >= 0)
1245 if (last_shared_irq >= 0 || last_irq >= 0)
1246 d->known_fields |= PCI_FILL_IRQ;
1248 if (bar_res_count > 0)
1249 d->known_fields |= PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS;
1253 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)
1255 ULONG reg_type, reg_len;
1257 BOOL have_bus, have_devfunc;
1258 DWORD drp_bus_num, drp_address;
1262 have_devfunc = FALSE;
1265 * DRP_BUSNUMBER consists of PCI domain number in high 24 bits
1266 * and PCI bus number in low 8 bits.
1268 reg_len = sizeof(drp_bus_num);
1269 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_BUSNUMBER, ®_type, &drp_bus_num, ®_len, 0);
1270 if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_bus_num))
1272 *domain = drp_bus_num >> 8;
1273 *bus = drp_bus_num & 0xff;
1278 * DRP_ADDRESS consists of PCI device number in high 16 bits
1279 * and PCI function number in low 16 bits.
1281 reg_len = sizeof(drp_address);
1282 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_ADDRESS, ®_type, &drp_address, ®_len, 0);
1283 if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_address))
1285 *dev = drp_address >> 16;
1286 *func = drp_address & 0xffff;
1287 have_devfunc = TRUE;
1291 * Device Instance Id for PCI devices is of format:
1292 * "<enumerator>\\<device_id>\\<instance_id>"
1294 * "<enumerator>" is "PCI"
1295 * "<device_id>" is "VEN_####&DEV_####&SUBSYS_########&REV_##"
1296 * and "<instance_id>" for PCI devices is at least in one of following format:
1297 * "BUS_##&DEV_##&FUNC_##"
1298 * "##.." (sequence of devfn hex bytes, where bytes represents tree path to the root)
1299 * "#..&#..&#..&#.." (four hex numbers separated by "&"; meaning is unknown yet)
1301 * First two formats are used only on systems without support for multiple
1302 * domains. The second format uses intel-conf encoding of device and function
1303 * number: Low 3 bits is function number and high 5 bits is device number.
1304 * Bus number is not really encoded in second format!
1306 * The third format is used on systems with support for multiple domains but
1307 * format is variable length and currently its meaning is unknown. Apparently
1308 * it looks like that DRP_BUSNUMBER and DRP_ADDRESS registry properties are
1309 * supported on these systems.
1311 * If DRP_BUSNUMBER or DRP_ADDRESS failed then try to parse PCI bus, device
1312 * and function numbers from Instance Id part.
1314 if (!have_bus || !have_devfunc)
1316 const char *device_id0 = strchr(devinst_id, '\\');
1317 const char *instance_id0 = device_id0 ? strchr(device_id0 + 1, '\\') : NULL;
1318 const char *instance_id = instance_id0 ? instance_id0 + 1 : NULL;
1323 if (fmt_validate(instance_id, strlen(instance_id), "BUS_##&DEV_##&FUNC_##") &&
1324 sscanf(instance_id, "BUS_%x&DEV_%x&FUNC_%x", bus, dev, func) == 3)
1327 have_devfunc = TRUE;
1329 else if (seq_xdigit_validate(instance_id, 2, 2) &&
1330 sscanf(instance_id, "%2x", &devfn) == 1)
1333 *func = devfn & 0x7;
1334 have_devfunc = TRUE;
1340 * Virtual IRQ holder devices do not have assigned any bus/dev/func number and
1341 * have "IRQHOLDER" in their Device Id part. So skip them.
1343 if (!have_bus && !have_devfunc && strncmp(devinst_id, "PCI\\IRQHOLDER\\", 14) == 0)
1347 * When some numbers cannot be retrieved via cfgmgr32 then set them to zeros
1348 * to have structure initialized. It makes sense to report via libpci also
1349 * such "incomplete" device as cfgmgr32 can provide additional information
1350 * like device/vendor ids or assigned resources.
1352 if (!have_bus && !have_devfunc)
1354 *bus = *dev = *func = 0;
1355 a->warning("Cannot retrieve bus, device and function numbers for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1360 a->warning("Cannot retrieve bus number for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1362 else if (!have_devfunc)
1365 a->warning("Cannot retrieve device and function numbers for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1372 fill_data_from_string(struct pci_dev *d, const char *str)
1374 BOOL have_device_id;
1375 BOOL have_vendor_id;
1378 const char *endptr, *endptr2;
1382 have_device_id = have_vendor_id = (d->known_fields & PCI_FILL_IDENT);
1383 have_prog_if = have_rev_id = (d->known_fields & PCI_FILL_CLASS_EXT);
1387 endptr = strchr(str, '&');
1388 endptr2 = strchr(str, '\\');
1389 if (endptr2 && (!endptr || endptr > endptr2))
1391 len = endptr ? endptr-str : (int)strlen(str);
1393 if (!have_vendor_id &&
1394 fmt_validate(str, len, "VEN_####") &&
1395 sscanf(str, "VEN_%x", &hex) == 1)
1398 have_vendor_id = TRUE;
1400 else if (!have_device_id &&
1401 fmt_validate(str, len, "DEV_####") &&
1402 sscanf(str, "DEV_%x", &hex) == 1)
1405 have_device_id = TRUE;
1407 else if (!(d->known_fields & PCI_FILL_SUBSYS) &&
1408 fmt_validate(str, len, "SUBSYS_########") &&
1409 sscanf(str, "SUBSYS_%x", &hex) == 1)
1411 d->subsys_vendor_id = hex & 0xffff;
1412 d->subsys_id = hex >> 16;
1413 d->known_fields |= PCI_FILL_SUBSYS;
1415 else if (!have_rev_id &&
1416 fmt_validate(str, len, "REV_##") &&
1417 sscanf(str, "REV_%x", &hex) == 1)
1422 else if (!((d->known_fields & PCI_FILL_CLASS) && have_prog_if) &&
1423 (fmt_validate(str, len, "CC_####") || fmt_validate(str, len, "CC_######")) &&
1424 sscanf(str, "CC_%x", &hex) == 1)
1430 d->prog_if = hex & 0xff;
1431 have_prog_if = TRUE;
1435 if (!(d->known_fields & PCI_FILL_CLASS))
1437 d->device_class = hex;
1438 d->known_fields |= PCI_FILL_CLASS;
1442 if (!endptr || endptr == endptr2)
1448 if ((have_device_id || d->device_id) && (have_vendor_id || d->vendor_id))
1449 d->known_fields |= PCI_FILL_IDENT;
1451 if ((have_prog_if || d->prog_if) && (have_rev_id || d->rev_id))
1452 d->known_fields |= PCI_FILL_CLASS_EXT;
1456 fill_data_from_devinst_id(struct pci_dev *d, DEVINSTID_A devinst_id)
1458 const char *device_id;
1460 device_id = strchr(devinst_id, '\\');
1466 * Device Id part of Device Instance Id is in format:
1467 * "VEN_####&DEV_####&SUBSYS_########&REV_##"
1469 fill_data_from_string(d, device_id);
1473 fill_data_from_hardware_ids(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
1475 ULONG reg_type, reg_size, reg_len;
1476 struct pci_access *a = d->access;
1477 char *hardware_ids = NULL;
1482 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, ®_type, NULL, ®_size, 0);
1483 if (cr != CR_SUCCESS && cr != CR_BUFFER_SMALL)
1485 a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1488 else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1490 a->warning("Cannot retrieve hardware ids for PCI device %s: Hardware ids are stored as unknown type 0x%lx.", devinst_id, reg_type);
1496 * Returned size is on older Windows versions without nul-term char.
1497 * So explicitly increase size and fill nul-term byte.
1500 hardware_ids = pci_malloc(a, reg_size);
1502 cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, ®_type, hardware_ids, ®_len, 0);
1503 hardware_ids[reg_size - 1] = 0;
1504 if (reg_len > reg_size)
1506 pci_mfree(hardware_ids);
1510 else if (cr != CR_SUCCESS)
1512 a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1513 pci_mfree(hardware_ids);
1516 else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1518 a->warning("Cannot retrieve hardware ids for PCI device %s: Hardware ids are stored as unknown type 0x%lx.", devinst_id, reg_type);
1519 pci_mfree(hardware_ids);
1524 * Hardware ids is nul-separated nul-term string list where each string has
1525 * one of the following format:
1526 * "PCI\\VEN_####&DEV_####&SUBSYS_########&REV_##"
1527 * "PCI\\VEN_####&DEV_####&SUBSYS_########"
1528 * "PCI\\VEN_####&DEV_####&REV_##&CC_####"
1529 * "PCI\\VEN_####&DEV_####&CC_######"
1530 * "PCI\\VEN_####&DEV_####&CC_####"
1531 * "PCI\\VEN_####&DEV_####&REV_##"
1532 * "PCI\\VEN_####&DEV_####"
1534 for (str = hardware_ids; *str != '\0'; str += strlen(str) + 1)
1536 if (strncmp(str, "PCI\\", 4) != 0)
1539 fill_data_from_string(d, str);
1542 pci_mfree(hardware_ids);
1546 scan_devinst_id(struct pci_access *a, DEVINSTID_A devinst_id)
1548 unsigned int domain, bus, dev, func;
1553 cr = CM_Locate_DevNodeA(&devinst, devinst_id, CM_LOCATE_DEVNODE_NORMAL);
1554 if (cr != CR_SUCCESS)
1556 /* Do not show warning when device is not present (= does not match NORMAL flag). */
1557 if (cr != CR_NO_SUCH_DEVNODE)
1558 a->warning("Cannot retrieve handle for device %s: %s.", devinst_id, cr_strerror(cr));
1562 /* get_device_location() returns FALSE if devinst is not real PCI device. */
1563 if (!get_device_location(a, devinst, devinst_id, &domain, &bus, &dev, &func))
1566 d = pci_get_dev(a, domain, bus, dev, func);
1568 if (!d->access->backend_data)
1569 d->no_config_access = 1;
1570 d->backend_data = (void *)devinst;
1572 /* Parse device id part of devinst id and fill details into pci_dev. */
1574 fill_data_from_devinst_id(d, devinst_id);
1576 /* Retrieve hardware ids of devinst, parse them and fill details into pci_dev. */
1578 fill_data_from_hardware_ids(d, devinst, devinst_id);
1581 fill_resources(d, devinst, devinst_id);
1584 * Set parent field to cfgmgr32 parent devinst handle and backend_data field to current
1585 * devinst handle. At later stage in win32_cfgmgr32_scan() when all pci_dev
1586 * devices are linked, change every devinst handle by pci_dev.
1590 DEVINST parent_devinst;
1591 if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS)
1594 a->warning("Cannot retrieve parent handle for device %s: %s.", devinst_id, cr_strerror(cr));
1596 d->parent = (void *)parent_devinst;
1601 win32_cfgmgr32_scan(struct pci_access *a)
1603 ULONG devinst_id_list_size;
1604 PCHAR devinst_id_list;
1605 DEVINSTID_A devinst_id;
1609 if (!resolve_cfgmgr32_functions())
1611 a->warning("Required cfgmgr32.dll functions are unavailable.");
1616 * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1617 * support this API but returns CR_SUCCESS without touching size argument.
1619 devinst_id_list_size = 0;
1620 cr = CM_Get_Device_ID_List_SizeA(&devinst_id_list_size, "PCI", CM_GETIDLIST_FILTER_ENUMERATOR);
1621 if (cr != CR_SUCCESS)
1623 a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1626 else if (devinst_id_list_size <= 1)
1628 a->warning("Cannot retrieve list of PCI devices: No device was found.");
1632 devinst_id_list = pci_malloc(a, devinst_id_list_size);
1633 cr = CM_Get_Device_ID_ListA("PCI", devinst_id_list, devinst_id_list_size, CM_GETIDLIST_FILTER_ENUMERATOR);
1634 if (cr != CR_SUCCESS)
1636 a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1637 pci_mfree(devinst_id_list);
1641 /* Register pci_dev for each cfgmgr32 devinst handle. */
1642 for (devinst_id = devinst_id_list; *devinst_id; devinst_id += strlen(devinst_id) + 1)
1643 scan_devinst_id(a, devinst_id);
1645 /* Fill all drivers. */
1649 /* Switch parent fields from cfgmgr32 devinst handle to pci_dev. */
1652 struct pci_dev *d1, *d2;
1653 for (d1 = a->devices; d1; d1 = d1->next)
1655 for (d2 = a->devices; d2; d2 = d2->next)
1656 if ((DEVINST)d1->parent == (DEVINST)d2->backend_data)
1660 d1->known_fields |= PCI_FILL_PARENT;
1664 /* devinst stored in ->backend_data is not needed anymore, clear it. */
1665 for (d = a->devices; d; d = d->next)
1666 d->backend_data = NULL;
1668 pci_mfree(devinst_id_list);
1672 win32_cfgmgr32_config(struct pci_access *a)
1674 pci_define_param(a, "win32.cfgmethod", "auto", "PCI config space access method");
1678 win32_cfgmgr32_detect(struct pci_access *a)
1680 ULONG devinst_id_list_size;
1683 if (!resolve_cfgmgr32_functions())
1685 a->debug("Required cfgmgr32.dll functions are unavailable.");
1690 * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1691 * support this API but returns CR_SUCCESS without touching size argument.
1693 devinst_id_list_size = 0;
1694 cr = CM_Get_Device_ID_List_SizeA(&devinst_id_list_size, "PCI", CM_GETIDLIST_FILTER_ENUMERATOR);
1695 if (cr != CR_SUCCESS)
1697 a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): %s.", cr_strerror(cr));
1700 else if (devinst_id_list_size <= 1)
1702 a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): No device was found.");
1710 win32_cfgmgr32_fill_info(struct pci_dev *d, unsigned int flags)
1713 * All available flags were filled by win32_cfgmgr32_scan().
1714 * Filling more flags is possible only from config space.
1716 if (!d->access->backend_data)
1719 pci_generic_fill_info(d, flags);
1723 win32_cfgmgr32_read(struct pci_dev *d, int pos, byte *buf, int len)
1725 struct pci_access *a = d->access;
1726 struct pci_access *acfg = a->backend_data;
1727 struct pci_dev *dcfg = d->backend_data;
1730 return pci_emulated_read(d, pos, buf, len);
1733 d->backend_data = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
1735 return pci_read_block(dcfg, pos, buf, len);
1739 win32_cfgmgr32_write(struct pci_dev *d, int pos, byte *buf, int len)
1741 struct pci_access *a = d->access;
1742 struct pci_access *acfg = a->backend_data;
1743 struct pci_dev *dcfg = d->backend_data;
1749 d->backend_data = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
1751 return pci_write_block(dcfg, pos, buf, len);
1755 win32_cfgmgr32_cleanup_dev(struct pci_dev *d)
1757 struct pci_dev *dcfg = d->backend_data;
1764 win32_cfgmgr32_init(struct pci_access *a)
1766 char *cfgmethod = pci_get_param(a, "win32.cfgmethod");
1767 struct pci_access *acfg;
1769 if (strcmp(cfgmethod, "") == 0 ||
1770 strcmp(cfgmethod, "auto") == 0)
1772 acfg = pci_clone_access(a);
1773 acfg->method = PCI_ACCESS_AUTO;
1775 else if (strcmp(cfgmethod, "none") == 0 ||
1776 strcmp(cfgmethod, "win32-cfgmgr32") == 0)
1779 a->error("Write access requested but option win32.cfgmethod was not set.");
1784 int m = pci_lookup_method(cfgmethod);
1786 a->error("Option win32.cfgmethod is set to an unknown access method \"%s\".", cfgmethod);
1787 acfg = pci_clone_access(a);
1791 a->debug("Loading config space access method...\n");
1792 if (!pci_init_internal(acfg, PCI_ACCESS_WIN32_CFGMGR32))
1795 a->debug("Cannot find any working config space access method.\n");
1797 a->error("Write access requested but no usable access method found.");
1801 a->backend_data = acfg;
1805 win32_cfgmgr32_cleanup(struct pci_access *a)
1807 struct pci_access *acfg = a->backend_data;
1813 struct pci_methods pm_win32_cfgmgr32 = {
1815 "Win32 device listing via Configuration Manager",
1816 win32_cfgmgr32_config,
1817 win32_cfgmgr32_detect,
1818 win32_cfgmgr32_init,
1819 win32_cfgmgr32_cleanup,
1820 win32_cfgmgr32_scan,
1821 win32_cfgmgr32_fill_info,
1822 win32_cfgmgr32_read,
1823 win32_cfgmgr32_write,
1824 NULL, /* read_vpd */
1825 NULL, /* init_dev */
1826 win32_cfgmgr32_cleanup_dev,