]> mj.ucw.cz Git - pciutils.git/blob - lib/win32-cfgmgr32.c
a001187901486ec88fe559d63d93d94739f22d9b
[pciutils.git] / lib / win32-cfgmgr32.c
1 /*
2  *      The PCI Library -- List PCI devices on Win32 via Configuration Manager
3  *
4  *      Copyright (c) 2021 Pali Rohár <pali@kernel.org>
5  *
6  *      Can be freely distributed and used under the terms of the GNU GPL v2+.
7  *
8  *      SPDX-License-Identifier: GPL-2.0-or-later
9  */
10
11 #include <windows.h>
12 #include <cfgmgr32.h>
13
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() */
18
19 #include "internal.h"
20 #include "win32-helpers.h"
21
22 /* Unfortunately MinGW32 toolchain does not provide these cfgmgr32 constants. */
23
24 #ifndef RegDisposition_OpenExisting
25 #define RegDisposition_OpenExisting 0x00000001
26 #endif
27
28 #ifndef CM_REGISTRY_SOFTWARE
29 #define CM_REGISTRY_SOFTWARE 0x00000001
30 #endif
31
32 #ifndef CM_DRP_HARDWAREID
33 #define CM_DRP_HARDWAREID 0x00000002
34 #endif
35 #ifndef CM_DRP_SERVICE
36 #define CM_DRP_SERVICE 0x00000005
37 #endif
38 #ifndef CM_DRP_BUSNUMBER
39 #define CM_DRP_BUSNUMBER 0x00000016
40 #endif
41 #ifndef CM_DRP_ADDRESS
42 #define CM_DRP_ADDRESS 0x0000001D
43 #endif
44
45 #ifndef CR_INVALID_CONFLICT_LIST
46 #define CR_INVALID_CONFLICT_LIST 0x00000039
47 #endif
48 #ifndef CR_INVALID_INDEX
49 #define CR_INVALID_INDEX 0x0000003A
50 #endif
51 #ifndef CR_INVALID_STRUCTURE_SIZE
52 #define CR_INVALID_STRUCTURE_SIZE 0x0000003B
53 #endif
54
55 #ifndef fIOD_10_BIT_DECODE
56 #define fIOD_10_BIT_DECODE 0x0004
57 #endif
58 #ifndef fIOD_12_BIT_DECODE
59 #define fIOD_12_BIT_DECODE 0x0008
60 #endif
61 #ifndef fIOD_16_BIT_DECODE
62 #define fIOD_16_BIT_DECODE 0x0010
63 #endif
64 #ifndef fIOD_POSITIVE_DECODE
65 #define fIOD_POSITIVE_DECODE 0x0020
66 #endif
67 #ifndef fIOD_PASSIVE_DECODE
68 #define fIOD_PASSIVE_DECODE 0x0040
69 #endif
70 #ifndef fIOD_WINDOW_DECODE
71 #define fIOD_WINDOW_DECODE 0x0080
72 #endif
73 #ifndef fIOD_PORT_BAR
74 #define fIOD_PORT_BAR 0x0100
75 #endif
76
77 #ifndef fMD_WINDOW_DECODE
78 #define fMD_WINDOW_DECODE 0x0040
79 #endif
80 #ifndef fMD_MEMORY_BAR
81 #define fMD_MEMORY_BAR 0x0080
82 #endif
83
84 /*
85  * Unfortunately MinGW32 toolchain does not provide import library for these
86  * cfgmgr32.dll functions. So resolve pointers to these functions at runtime.
87  */
88
89 #ifdef CM_Get_DevNode_Registry_PropertyA
90 #undef CM_Get_DevNode_Registry_PropertyA
91 #endif
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
94
95 #ifdef CM_Get_DevNode_Registry_PropertyW
96 #undef CM_Get_DevNode_Registry_PropertyW
97 #endif
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
100
101 #ifndef CM_Open_DevNode_Key
102 #undef CM_Open_DevNode_Key
103 #endif
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
106
107 static BOOL
108 resolve_cfgmgr32_functions(void)
109 {
110   HMODULE cfgmgr32;
111
112   if (CM_Get_DevNode_Registry_PropertyA && CM_Get_DevNode_Registry_PropertyW && CM_Open_DevNode_Key)
113     return TRUE;
114
115   cfgmgr32 = GetModuleHandleA("cfgmgr32.dll");
116   if (!cfgmgr32)
117     return FALSE;
118
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)
123     return FALSE;
124
125   return TRUE;
126 }
127
128 /*
129  * cfgmgr32.dll uses custom non-Win32 error numbers which are unsupported by
130  * Win32 APIs like GetLastError() and FormatMessage() functions.
131  *
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.
135  *
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.
140  *
141  * So define own function for translating CR_* errors directly to strings.
142  */
143 static const char *
144 cr_strerror(CONFIGRET cr_error_id)
145 {
146   static char unknown_error[sizeof("Unknown CR error XXXXXXXXXX")];
147   static const char *cr_errors[] = {
148     "The operation completed successfully",
149     "CR_DEFAULT",
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",
166     "CR_INVALID_RANGE",
167     "A general internal error occurred",
168     "CR_NO_SUCH_LOGICAL_DEV",
169     "The device is disabled for this configuration",
170     "CR_NOT_SYSTEM_VM",
171     "A service or application refused to allow removal of this device",
172     "CR_APM_VETOED",
173     "CR_INVALID_LOAD_TYPE",
174     "An output parameter was too small to hold all the data available",
175     "CR_NO_ARBITRATOR",
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",
180     "CR_INVALID_API",
181     "CR_DEVLOADER_NOT_READY",
182     "CR_NEED_RESTART",
183     "There are no more hardware profiles available",
184     "CR_DEVICE_NOT_THERE",
185     "The specified value does not exist in the registry",
186     "CR_WRONG_TYPE",
187     "The specified priority is invalid for this operation",
188     "This device cannot be disabled",
189     "CR_FREE_RESOURCES",
190     "CR_QUERY_VETOED",
191     "CR_CANT_SHARE_IRQ",
192     "CR_NO_DEPENDENT",
193     "CR_SAME_RESOURCES",
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",
199     "Access denied",
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",
206     "Invalid index",
207     "Invalid structure size"
208   };
209   if (cr_error_id <= 0 || cr_error_id >= sizeof(cr_errors)/sizeof(*cr_errors))
210     {
211       sprintf(unknown_error, "Unknown CR error %lu", cr_error_id);
212       return unknown_error;
213     }
214   return cr_errors[cr_error_id];
215 }
216
217 static int
218 fmt_validate(const char *s, int len, const char *fmt)
219 {
220   int i;
221
222   for (i = 0; i < len; i++)
223     if (!fmt[i] || (fmt[i] == '#' ? !isxdigit(s[i]) : fmt[i] != s[i]))
224       return 0;
225
226   return 1;
227 }
228
229 static int
230 seq_xdigit_validate(const char *s, int mult, int min)
231 {
232   int i, len;
233
234   len = strlen(s);
235   if (len < min*mult || len % mult)
236     return 0;
237
238   for (i = 0; i < len; i++)
239     if (!isxdigit(s[i]))
240       return 0;
241
242   return 1;
243 }
244
245 static LPWSTR
246 get_device_service_name(struct pci_access *a, DEVINST devinst, DEVINSTID_A devinst_id, BOOL *supported)
247 {
248   ULONG reg_type, reg_size, reg_len;
249   LPWSTR service_name;
250   CONFIGRET cr;
251
252   /*
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...
258    */
259
260   reg_size = 0;
261   cr = CM_Get_DevNode_Registry_PropertyW(devinst, CM_DRP_SERVICE, &reg_type, NULL, &reg_size, 0);
262   if (cr == CR_CALL_NOT_IMPLEMENTED)
263     {
264       *supported = FALSE;
265       return NULL;
266     }
267   else if (cr == CR_NO_SUCH_VALUE)
268     {
269       *supported = TRUE;
270       return NULL;
271     }
272   else if (cr != CR_SUCCESS &&
273            cr != CR_BUFFER_SMALL)
274     {
275       a->warning("Cannot retrieve service name for PCI device %s: %s.", devinst_id, cr_strerror(cr));
276       *supported = TRUE;
277       return NULL;
278     }
279   else if (reg_type != REG_SZ)
280     {
281       a->warning("Cannot retrieve service name for PCI device %s: Service name is stored as unknown type 0x%lx.", devinst_id, reg_type);
282       *supported = TRUE;
283       return NULL;
284     }
285
286 retry:
287   /*
288    * Returned size is on older Windows versions without nul-term char.
289    * So explicitly increase size and fill nul-term byte.
290    */
291   reg_size += sizeof(service_name[0]);
292   service_name = pci_malloc(a, reg_size);
293   reg_len = reg_size;
294   cr = CM_Get_DevNode_Registry_PropertyW(devinst, CM_DRP_SERVICE, &reg_type, service_name, &reg_len, 0);
295   service_name[reg_size/sizeof(service_name[0]) - 1] = 0;
296   if (reg_len > reg_size)
297     {
298       pci_mfree(service_name);
299       reg_size = reg_len;
300       goto retry;
301     }
302   else if (cr != CR_SUCCESS)
303     {
304       a->warning("Cannot retrieve service name for PCI device %s: %s.", devinst_id, cr_strerror(cr));
305       pci_mfree(service_name);
306       *supported = TRUE;
307       return NULL;
308     }
309   else if (reg_type != REG_SZ)
310     {
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);
313       *supported = TRUE;
314       return NULL;
315     }
316
317
318   return service_name;
319 }
320
321 static char*
322 get_driver_path_for_service(struct pci_access *a, LPCWSTR service_name, SC_HANDLE manager)
323 {
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;
332   UINT systemroot_len;
333   int driver_path_len;
334   UINT system32_len;
335   HMODULE kernel32;
336   WCHAR *trim_ptr;
337   DWORD error;
338
339   service = OpenServiceW(manager, service_name, SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS);
340   if (!service)
341     {
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));
345       goto out;
346     }
347
348   if (!QueryServiceStatus(service, &service_status))
349     {
350       error = GetLastError();
351       a->warning("Cannot query status of service %ls: %s.", service_name, win32_strerror(error));
352       goto out;
353     }
354
355   if (service_status.dwCurrentState == SERVICE_STOPPED)
356     goto out;
357
358   if (service_status.dwServiceType != SERVICE_KERNEL_DRIVER)
359     goto out;
360
361   if (!QueryServiceConfigW(service, NULL, 0, &service_config_size))
362     {
363       error = GetLastError();
364       if (error != ERROR_INSUFFICIENT_BUFFER)
365       {
366         a->warning("Cannot query config of service %ls: %s.", service_name, win32_strerror(error));
367         goto out;
368       }
369     }
370
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))
374     {
375       error = GetLastError();
376       if (error == ERROR_INSUFFICIENT_BUFFER)
377         {
378           pci_mfree(service_config);
379           service_config_size = service_config_len;
380           goto retry_service_config;
381         }
382       a->warning("Cannot query config of service %ls: %s.", service_name, win32_strerror(error));
383       goto out;
384     }
385
386   if (service_config->dwServiceType != SERVICE_KERNEL_DRIVER)
387     goto out;
388
389   /*
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.
394    */
395
396   /*
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.
402    */
403   kernel32 = GetModuleHandleW(L"kernel32.dll");
404   if (kernel32)
405     get_system_root_path = (void *)GetProcAddress(kernel32, "GetSystemWindowsDirectoryW");
406   else
407     {
408       get_system_root_path = &GetSystemDirectoryW;
409       trim_system32 = 1;
410     }
411
412   if (!service_config->lpBinaryPathName || !service_config->lpBinaryPathName[0])
413     {
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");
424     }
425   else if (wcsncmp(service_config->lpBinaryPathName, L"\\SystemRoot\\", sizeof("\\SystemRoot\\")-1) == 0)
426     {
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);
436     }
437   else if (wcsncmp(service_config->lpBinaryPathName, L"\\??\\UNC\\", sizeof("\\??\\UNC\\")-1) == 0 ||
438            wcsncmp(service_config->lpBinaryPathName, L"\\??\\\\UNC\\", sizeof("\\??\\\\UNC\\")-1) == 0)
439     {
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'\\')
445         driver_path_len++;
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);
449     }
450   else if (wcsncmp(service_config->lpBinaryPathName, L"\\??\\", sizeof("\\??\\")-1) == 0)
451     {
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'\\')
457         driver_path_len++;
458       wcscpy(service_image_path, service_config->lpBinaryPathName + driver_path_len);
459     }
460   else if (service_config->lpBinaryPathName[0] != L'\\')
461     {
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);
471     }
472   else
473     {
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);
477     }
478
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)
482     {
483       error = GetLastError();
484       a->warning("Cannot convert kernel driver path from wide string to 8-bit string: %s.", win32_strerror(error));
485       goto out;
486     }
487
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)
491     {
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);
495       driver_path = NULL;
496       goto out;
497     }
498
499 out:
500   if (service_image_path)
501     pci_mfree(service_image_path);
502   if (service_config)
503     pci_mfree(service_config);
504   if (service)
505     CloseServiceHandle(service);
506   return driver_path;
507 }
508
509 static HKEY
510 get_device_driver_devreg(struct pci_access *a, DEVINST devinst, DEVINSTID_A devinst_id)
511 {
512   CONFIGRET cr;
513   HKEY key;
514
515   cr = CM_Open_DevNode_Key(devinst, KEY_READ, 0, RegDisposition_OpenExisting, &key, CM_REGISTRY_SOFTWARE);
516   if (cr != CR_SUCCESS)
517     {
518       if (cr != CR_NO_SUCH_VALUE)
519         a->warning("Cannot retrieve driver key for device %s: %s.", devinst_id, cr_strerror(cr));
520       return NULL;
521     }
522
523   return key;
524 }
525
526 static char*
527 read_reg_key_string_value(struct pci_access *a, HKEY key, const char *name, DWORD *unkn_reg_type)
528 {
529   DWORD reg_type, reg_size, reg_len;
530   char *value;
531   LONG error;
532
533   reg_size = 0;
534   error = RegQueryValueExA(key, name, NULL, &reg_type, NULL, &reg_size);
535   if (error != ERROR_SUCCESS &&
536       error != ERROR_MORE_DATA)
537     {
538       SetLastError(error);
539       return NULL;
540     }
541   else if (reg_type != REG_SZ)
542     {
543       SetLastError(0);
544       *unkn_reg_type = reg_type;
545       return NULL;
546     }
547
548 retry:
549   value = pci_malloc(a, reg_size + 1);
550   reg_len = reg_size;
551   error = RegQueryValueExA(key, name, NULL, &reg_type, (PBYTE)value, &reg_len);
552   if (error != ERROR_SUCCESS)
553     {
554       pci_mfree(value);
555       if (error == ERROR_MORE_DATA)
556         {
557           reg_size = reg_len;
558           goto retry;
559         }
560       SetLastError(error);
561       return NULL;
562     }
563   else if (reg_type != REG_SZ)
564     {
565       pci_mfree(value);
566       SetLastError(0);
567       *unkn_reg_type = reg_type;
568       return NULL;
569     }
570   value[reg_len] = '\0';
571
572   return value;
573 }
574
575 static int
576 driver_cmp(const char *driver, const char *match)
577 {
578   int len = strlen(driver);
579   if (driver[0] == '*')
580     driver++;
581   if (len >= 4 && strcasecmp(driver + len - 4, ".vxd") == 0)
582     len -= 4;
583   return strncasecmp(driver, match, len);
584 }
585
586 static char*
587 get_driver_path_for_regkey(struct pci_access *a, DEVINSTID_A devinst_id, HKEY key)
588 {
589   char *driver_list, *driver, *driver_next;
590   char *subdriver, *subname;
591   char *driver_ptr;
592   char *driver_path;
593   DWORD unkn_reg_type;
594   UINT systemdir_len;
595   HKEY subkey;
596   LONG error;
597   BOOL vmm32;
598   BOOL noext;
599   int len;
600
601   driver_list = read_reg_key_string_value(a, key, "DevLoader", &unkn_reg_type);
602   if (!driver_list)
603     {
604       error = GetLastError();
605       if (error == 0)
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));
609       return NULL;
610     }
611
612   subdriver = NULL;
613   driver = driver_list;
614   while (*driver)
615     {
616       driver_next = strchr(driver, ',');
617       if (driver_next)
618           *(driver_next++) = '\0';
619
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)
628         subname = "minivdd";
629       else
630         subname = NULL;
631
632       subkey = key;
633       if (subname && strcmp(subname, "minivdd") == 0)
634         {
635           error = RegOpenKeyA(key, "Default", &subkey);
636           if (error != ERROR_SUCCESS)
637             {
638               a->warning("Cannot open driver subkey Default for PCI device %s: %s.", devinst_id, win32_strerror(error));
639               subkey = NULL;
640             }
641         }
642
643       if (!subname)
644         break;
645
646       if (subkey)
647         {
648 retry_subname:
649           subdriver = read_reg_key_string_value(a, subkey, subname, &unkn_reg_type);
650           if (!subdriver)
651             {
652               error = GetLastError();
653               if (error == 0)
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)
658                 {
659                   subname = "drv";
660                   goto retry_subname;
661                 }
662               else if (strcmp(subname, "drv") == 0)
663                 {
664                   subname = "vdd";
665                   goto retry_subname;
666                 }
667             }
668
669           if (subkey != key)
670             RegCloseKey(subkey);
671
672           if (subdriver)
673             {
674               char *endptr = strchr(subdriver, ',');
675               if (endptr)
676                 *endptr = '\0';
677               break;
678             }
679         }
680
681       driver = driver_next;
682     }
683
684   if (subdriver && subdriver[0])
685     driver_ptr = subdriver;
686   else if (driver[0])
687     driver_ptr = driver;
688   else
689     driver_ptr = NULL;
690
691   if (driver_ptr && driver_ptr[0] == '*')
692     {
693       vmm32 = TRUE;
694       driver_ptr++;
695     }
696   else
697     vmm32 = FALSE;
698
699   if (!driver_ptr[0])
700     driver_ptr = NULL;
701
702   len = driver_ptr ? strlen(driver_ptr) : 0;
703   noext = driver_ptr && (len < 4 || driver_ptr[len-4] != '.');
704
705   if (!driver_ptr)
706     driver_path = NULL;
707   else
708     {
709       if (tolower(driver_ptr[0]) >= 'a' && tolower(driver_ptr[0]) <= 'z' && driver_ptr[1] == ':')
710         {
711           /* Driver is already with absolute path. */
712           driver_path = pci_strdup(a, driver_ptr);
713         }
714       else if (driver_cmp(driver, "ntkern") == 0 && subdriver)
715         {
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" : "");
723         }
724       else if (vmm32)
725         {
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" : "");
733         }
734       else
735         {
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" : "");
743         }
744     }
745
746   if (subdriver)
747     pci_mfree(subdriver);
748   pci_mfree(driver_list);
749   return driver_path;
750 }
751
752 static char *
753 get_device_driver_path(struct pci_dev *d, SC_HANDLE manager, BOOL manager_supported)
754 {
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;
762   ULONG problem = 0;
763   ULONG status = 0;
764   HKEY key = NULL;
765
766   if (CM_Get_DevNode_Status(&status, &problem, devinst, 0) != CR_SUCCESS || !(status & DN_DRIVER_LOADED))
767     return NULL;
768
769   if (CM_Get_Device_ID_Size(&devinst_id_len, devinst, 0) == CR_SUCCESS)
770     {
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)
773         {
774           pci_mfree(devinst_id);
775           devinst_id = pci_strdup(a, "UNKNOWN");
776         }
777     }
778   else
779     devinst_id = pci_strdup(a, "UNKNOWN");
780
781   service_name = get_device_service_name(d->access, devinst, devinst_id, &service_supported);
782   if ((!service_name || !manager) && service_supported && manager_supported)
783     goto out;
784   else if (service_name && manager)
785     {
786       driver_path = get_driver_path_for_service(d->access, service_name, manager);
787       goto out;
788     }
789
790   key = get_device_driver_devreg(d->access, devinst, devinst_id);
791   if (key)
792     {
793       driver_path = get_driver_path_for_regkey(d->access, devinst_id, key);
794       goto out;
795     }
796
797 out:
798   if (key)
799     RegCloseKey(key);
800   if (service_name)
801     pci_mfree(service_name);
802   pci_mfree(devinst_id);
803   return driver_path;
804 }
805
806 static void
807 fill_drivers(struct pci_access *a)
808 {
809   BOOL manager_supported;
810   SC_HANDLE manager;
811   struct pci_dev *d;
812   char *driver;
813   DWORD error;
814
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);
818   if (!manager)
819     {
820       error = GetLastError();
821       if (error != ERROR_CALL_NOT_IMPLEMENTED)
822         a->warning("Cannot open Service Manager with connect right: %s.", win32_strerror(error));
823       else
824         manager_supported = FALSE;
825     }
826
827   for (d = a->devices; d; d = d->next)
828     {
829       driver = get_device_driver_path(d, manager, manager_supported);
830       if (driver)
831         {
832           pci_set_property(d, PCI_FILL_DRIVER, driver);
833           pci_mfree(driver);
834         }
835       d->known_fields |= PCI_FILL_DRIVER;
836     }
837
838   if (manager)
839     CloseServiceHandle(manager);
840 }
841
842 static const char *
843 res_id_to_str(RESOURCEID res_id)
844 {
845   static char hex_res_id[sizeof("0xffffffff")];
846
847   if (res_id == ResType_IO)
848     return "IO";
849   else if (res_id == ResType_Mem)
850     return "MEM";
851   else if (res_id == ResType_IRQ)
852     return "IRQ";
853
854   sprintf(hex_res_id, "0x%lx", res_id);
855   return hex_res_id;
856 }
857
858 static void
859 fill_resources(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
860 {
861   struct pci_access *a = d->access;
862
863   CONFIGRET cr;
864
865   LOG_CONF config;
866   ULONG problem;
867   ULONG status;
868
869   RES_DES prev_res_des;
870   RES_DES res_des;
871   RESOURCEID res_id;
872   DWORD bar_res_count;
873
874   BOOL is_bar_res;
875   BOOL non_nt_system;
876
877   int last_irq = -1;
878   int last_shared_irq = -1;
879
880   cr = CM_Get_DevNode_Status(&status, &problem, devinst, 0);
881   if (cr != CR_SUCCESS)
882     {
883       a->warning("Cannot retrieve status of PCI device %s: %s.", devinst_id, cr_strerror(cr));
884       return;
885     }
886
887   cr = CR_NO_MORE_LOG_CONF;
888
889   /*
890    * If the device is running then retrieve allocated configuration by PnP
891    * manager which is currently in use by a device.
892    */
893   if (!(status & DN_HAS_PROBLEM))
894     cr = CM_Get_First_Log_Conf(&config, devinst, ALLOC_LOG_CONF);
895
896   /*
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.
900    */
901   if (cr == CR_NO_MORE_LOG_CONF)
902     cr = CM_Get_First_Log_Conf(&config, devinst, FORCED_LOG_CONF);
903
904   /*
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.
908    */
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);
912
913   if (cr != CR_SUCCESS)
914     {
915       /*
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.
922        */
923       if (cr == CR_CALL_NOT_IMPLEMENTED && win32_is_32bit_on_win8_64bit_system())
924         {
925           static BOOL warn_once = FALSE;
926           if (!warn_once)
927             {
928               warn_once = TRUE;
929               a->warning("Cannot retrieve resources of PCI devices from 32-bit application on 64-bit system.");
930             }
931         }
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));
934       return;
935     }
936
937   bar_res_count = 0;
938   non_nt_system = win32_is_non_nt_system();
939
940   is_bar_res = TRUE;
941   if (non_nt_system)
942     {
943       BOOL has_child;
944       DEVINST child;
945       ULONG child_name_len;
946       PSTR child_name;
947       BOOL is_bridge;
948
949       if (CM_Get_Child(&child, devinst, 0) != CR_SUCCESS)
950         has_child = FALSE;
951       else if (CM_Get_Device_ID_Size(&child_name_len, child, 0) != CR_SUCCESS)
952         has_child = FALSE;
953       else
954         {
955           child_name_len++;
956           child_name = pci_malloc(a, child_name_len);
957           if (CM_Get_Device_IDA(child, child_name, child_name_len, 0) != CR_SUCCESS)
958             has_child = FALSE;
959           else if (strncmp(child_name, "PCI\\", 4) != 0)
960             has_child = FALSE;
961           else
962             has_child = TRUE;
963           pci_mfree(child_name);
964         }
965
966       if (has_child || d->device_class == PCI_CLASS_BRIDGE_PCI || d->device_class == PCI_CLASS_BRIDGE_CARDBUS)
967         is_bridge = TRUE;
968       else
969         is_bridge = FALSE;
970
971       if (is_bridge)
972         is_bar_res = FALSE;
973     }
974
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)
977     {
978       pciaddr_t start, end, size, flags;
979       ULONG res_des_data_size;
980       PBYTE res_des_data;
981
982       if (prev_res_des != config)
983         CM_Free_Res_Des_Handle(prev_res_des);
984
985       prev_res_des = res_des;
986
987       /* Skip other resources early */
988       if (res_id != ResType_IO && res_id != ResType_Mem && res_id != ResType_IRQ)
989         continue;
990
991       cr = CM_Get_Res_Des_Data_Size(&res_des_data_size, res_des, 0);
992       if (cr != CR_SUCCESS)
993         {
994           a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, cr_strerror(cr));
995           continue;
996         }
997
998       if (!res_des_data_size)
999         {
1000           a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, "Empty data");
1001           continue;
1002         }
1003
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)
1007         {
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);
1010           continue;
1011         }
1012
1013       /*
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).
1017        */
1018
1019       if (res_id == ResType_IO)
1020         {
1021           PIO_RESOURCE io_data = (PIO_RESOURCE)res_des_data;
1022
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;
1027
1028           /*
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.
1033            */
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;
1036
1037           /*
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.
1043            */
1044           if (io_data->IO_Header.IOD_DesFlags & fIOD_WINDOW_DECODE)
1045             is_bar_res = FALSE;
1046           else if (io_data->IO_Header.IOD_DesFlags & fIOD_PORT_BAR)
1047             is_bar_res = TRUE;
1048
1049           if (is_bar_res && bar_res_count < 6)
1050             {
1051               d->flags[bar_res_count] = flags;
1052               d->base_addr[bar_res_count] = start;
1053               d->size[bar_res_count] = size;
1054               bar_res_count++;
1055             }
1056           else if (!is_bar_res)
1057             {
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;
1062             }
1063         }
1064       else if (res_id == ResType_Mem)
1065         {
1066           PMEM_RESOURCE mem_data = (PMEM_RESOURCE)res_des_data;
1067
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;
1072
1073           /*
1074            * If fMD_PrefetchAllowed flag is set then this is
1075            * PCI Prefetchable Memory resource.
1076            */
1077           if ((mem_data->MEM_Header.MD_Flags & mMD_Prefetchable) == fMD_PrefetchAllowed)
1078             flags |= PCI_IORESOURCE_PREFETCH;
1079
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;
1083
1084           /*
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.
1088            */
1089           if (mem_data->MEM_Header.MD_Flags & fMD_WINDOW_DECODE)
1090             is_bar_res = FALSE;
1091           else if (mem_data->MEM_Header.MD_Flags & fMD_MEMORY_BAR)
1092             is_bar_res = TRUE;
1093
1094           /* 64-bit BAR resource must be at even position. */
1095           if (is_bar_res && (flags & PCI_IORESOURCE_MEM_64) && bar_res_count % 2)
1096             bar_res_count++;
1097
1098           if (is_bar_res && bar_res_count < 6)
1099             {
1100               d->flags[bar_res_count] = flags;
1101               d->base_addr[bar_res_count] = start;
1102               d->size[bar_res_count] = size;
1103               bar_res_count++;
1104               /* 64-bit BAR resource occupies two slots. */
1105               if (flags & PCI_IORESOURCE_MEM_64)
1106                 bar_res_count++;
1107             }
1108           else if (!is_bar_res && !(flags & PCI_IORESOURCE_PREFETCH))
1109             {
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;
1114             }
1115           else if (!is_bar_res && (flags & PCI_IORESOURCE_PREFETCH))
1116             {
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;
1121             }
1122         }
1123       else if (res_id == ResType_IRQ)
1124         {
1125           PIRQ_RESOURCE irq_data = (PIRQ_RESOURCE)res_des_data;
1126
1127           /*
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.
1132            *
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.
1137            *
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.
1141            */
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;
1145
1146           /*
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.
1150            */
1151           if (!is_bar_res && non_nt_system)
1152             is_bar_res = TRUE;
1153         }
1154
1155       pci_mfree(res_des_data);
1156     }
1157   if (cr != CR_NO_MORE_RES_DES)
1158     a->warning("Cannot retrieve resources of PCI device %s: %s.", devinst_id, cr_strerror(cr));
1159
1160   if (prev_res_des != config)
1161     CM_Free_Res_Des_Handle(prev_res_des);
1162
1163   CM_Free_Log_Conf_Handle(config);
1164
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)
1169     d->irq = last_irq;
1170   if (last_shared_irq >= 0 || last_irq >= 0)
1171     d->known_fields |= PCI_FILL_IRQ;
1172
1173   if (bar_res_count > 0)
1174     d->known_fields |= PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS;
1175 }
1176
1177 static BOOL
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)
1179 {
1180   ULONG reg_type, reg_len;
1181   CONFIGRET cr;
1182   BOOL have_bus, have_devfunc;
1183   DWORD drp_bus_num, drp_address;
1184
1185   *domain = 0;
1186   have_bus = FALSE;
1187   have_devfunc = FALSE;
1188
1189   /*
1190    * DRP_BUSNUMBER consists of PCI domain number in high 24 bits
1191    * and PCI bus number in low 8 bits.
1192    */
1193   reg_len = sizeof(drp_bus_num);
1194   cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_BUSNUMBER, &reg_type, &drp_bus_num, &reg_len, 0);
1195   if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_bus_num))
1196     {
1197       *domain = drp_bus_num >> 8;
1198       *bus = drp_bus_num & 0xff;
1199       have_bus = TRUE;
1200     }
1201
1202   /*
1203    * DRP_ADDRESS consists of PCI device number in high 16 bits
1204    * and PCI function number in low 16 bits.
1205    */
1206   reg_len = sizeof(drp_address);
1207   cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_ADDRESS, &reg_type, &drp_address, &reg_len, 0);
1208   if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_address))
1209     {
1210       *dev = drp_address >> 16;
1211       *func = drp_address & 0xffff;
1212       have_devfunc = TRUE;
1213     }
1214
1215   /*
1216    * Device Instance Id for PCI devices is of format:
1217    *  "<enumerator>\\<device_id>\\<instance_id>"
1218    * where:
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)
1225    *
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!
1230    *
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.
1235    *
1236    * If DRP_BUSNUMBER or DRP_ADDRESS failed then try to parse PCI bus, device
1237    * and function numbers from Instance Id part.
1238    */
1239   if (!have_bus || !have_devfunc)
1240     {
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;
1244       unsigned int devfn;
1245
1246       if (instance_id)
1247         {
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)
1250             {
1251               have_bus = TRUE;
1252               have_devfunc = TRUE;
1253             }
1254           else if (seq_xdigit_validate(instance_id, 2, 2) &&
1255                    sscanf(instance_id, "%2x", &devfn) == 1)
1256             {
1257               *dev = devfn >> 3;
1258               *func = devfn & 0x7;
1259               have_devfunc = TRUE;
1260             }
1261         }
1262     }
1263
1264   /*
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.
1267    */
1268   if (!have_bus && !have_devfunc && strncmp(devinst_id, "PCI\\IRQHOLDER\\", 14) == 0)
1269     return FALSE;
1270
1271   /*
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.
1276    */
1277   if (!have_bus && !have_devfunc)
1278     {
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));
1281     }
1282   else if (!have_bus)
1283     {
1284       *bus = 0;
1285       a->warning("Cannot retrieve bus number for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1286     }
1287   else if (!have_devfunc)
1288     {
1289       *dev = *func = 0;
1290       a->warning("Cannot retrieve device and function numbers for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1291     }
1292
1293   return TRUE;
1294 }
1295
1296 static void
1297 fill_data_from_string(struct pci_dev *d, const char *str)
1298 {
1299   BOOL have_device_id;
1300   BOOL have_vendor_id;
1301   BOOL have_prog_if;
1302   BOOL have_rev_id;
1303   const char *endptr, *endptr2;
1304   unsigned int hex;
1305   int len;
1306
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);
1309
1310   while (1)
1311     {
1312       endptr = strchr(str, '&');
1313       endptr2 = strchr(str, '\\');
1314       if (endptr2 && (!endptr || endptr > endptr2))
1315         endptr = endptr2;
1316       len = endptr ? endptr-str : (int)strlen(str);
1317
1318       if (!have_vendor_id &&
1319           fmt_validate(str, len, "VEN_####") &&
1320           sscanf(str, "VEN_%x", &hex) == 1)
1321         {
1322           d->vendor_id = hex;
1323           have_vendor_id = TRUE;
1324         }
1325       else if (!have_device_id &&
1326                fmt_validate(str, len, "DEV_####") &&
1327                sscanf(str, "DEV_%x", &hex) == 1)
1328         {
1329           d->device_id = hex;
1330           have_device_id = TRUE;
1331         }
1332       else if (!(d->known_fields & PCI_FILL_SUBSYS) &&
1333                fmt_validate(str, len, "SUBSYS_########") &&
1334                sscanf(str, "SUBSYS_%x", &hex) == 1)
1335         {
1336           d->subsys_vendor_id = hex & 0xffff;
1337           d->subsys_id = hex >> 16;
1338           d->known_fields |= PCI_FILL_SUBSYS;
1339         }
1340       else if (!have_rev_id &&
1341                fmt_validate(str, len, "REV_##") &&
1342                sscanf(str, "REV_%x", &hex) == 1)
1343         {
1344           d->rev_id = hex;
1345           have_rev_id = TRUE;
1346         }
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)
1350         {
1351           if (len == 9)
1352             {
1353               if (!have_prog_if)
1354                 {
1355                   d->prog_if = hex & 0xff;
1356                   have_prog_if = TRUE;
1357                 }
1358               hex >>= 8;
1359             }
1360           if (!(d->known_fields & PCI_FILL_CLASS))
1361             {
1362               d->device_class = hex;
1363               d->known_fields |= PCI_FILL_CLASS;
1364             }
1365         }
1366
1367       if (!endptr || endptr == endptr2)
1368         break;
1369
1370       str = endptr + 1;
1371     }
1372
1373   if ((have_device_id || d->device_id) && (have_vendor_id || d->vendor_id))
1374     d->known_fields |= PCI_FILL_IDENT;
1375
1376   if ((have_prog_if || d->prog_if) && (have_rev_id || d->rev_id))
1377     d->known_fields |= PCI_FILL_CLASS_EXT;
1378 }
1379
1380 static void
1381 fill_data_from_devinst_id(struct pci_dev *d, DEVINSTID_A devinst_id)
1382 {
1383   const char *device_id;
1384
1385   device_id = strchr(devinst_id, '\\');
1386   if (!device_id)
1387     return;
1388   device_id++;
1389
1390   /*
1391    * Device Id part of Device Instance Id is in format:
1392    *  "VEN_####&DEV_####&SUBSYS_########&REV_##"
1393    */
1394   fill_data_from_string(d, device_id);
1395 }
1396
1397 static void
1398 fill_data_from_hardware_ids(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
1399 {
1400   ULONG reg_type, reg_size, reg_len;
1401   struct pci_access *a = d->access;
1402   char *hardware_ids = NULL;
1403   const char *str;
1404   CONFIGRET cr;
1405
1406   reg_size = 0;
1407   cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, &reg_type, NULL, &reg_size, 0);
1408   if (cr != CR_SUCCESS && cr != CR_BUFFER_SMALL)
1409     {
1410       a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1411       return;
1412     }
1413   else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1414     {
1415       a->warning("Cannot retrieve hardware ids for PCI device %s: Hardware ids are stored as unknown type 0x%lx.", devinst_id, reg_type);
1416       return;
1417     }
1418
1419 retry:
1420   /*
1421    * Returned size is on older Windows versions without nul-term char.
1422    * So explicitly increase size and fill nul-term byte.
1423    */
1424   reg_size++;
1425   hardware_ids = pci_malloc(a, reg_size);
1426   reg_len = reg_size;
1427   cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, &reg_type, hardware_ids, &reg_len, 0);
1428   hardware_ids[reg_size - 1] = 0;
1429   if (reg_len > reg_size)
1430     {
1431       pci_mfree(hardware_ids);
1432       reg_size = reg_len;
1433       goto retry;
1434     }
1435   else if (cr != CR_SUCCESS)
1436     {
1437       a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1438       pci_mfree(hardware_ids);
1439       return;
1440     }
1441   else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1442     {
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);
1445       return;
1446     }
1447
1448   /*
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_####"
1458    */
1459   for (str = hardware_ids; *str != '\0'; str += strlen(str) + 1)
1460     {
1461       if (strncmp(str, "PCI\\", 4) != 0)
1462         continue;
1463       str += 4;
1464       fill_data_from_string(d, str);
1465     }
1466
1467   pci_mfree(hardware_ids);
1468 }
1469
1470 static void
1471 scan_devinst_id(struct pci_access *a, DEVINSTID_A devinst_id)
1472 {
1473   unsigned int domain, bus, dev, func;
1474   struct pci_dev *d;
1475   DEVINST devinst;
1476   CONFIGRET cr;
1477
1478   cr = CM_Locate_DevNodeA(&devinst, devinst_id, CM_LOCATE_DEVNODE_NORMAL);
1479   if (cr != CR_SUCCESS)
1480     {
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));
1484       return;
1485     }
1486
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))
1489     return;
1490
1491   d = pci_get_dev(a, domain, bus, dev, func);
1492   pci_link_dev(a, d);
1493   if (!d->access->backend_data)
1494     d->no_config_access = 1;
1495   d->backend_data = (void *)devinst;
1496
1497   /* Parse device id part of devinst id and fill details into pci_dev. */
1498   if (!a->buscentric)
1499     fill_data_from_devinst_id(d, devinst_id);
1500
1501   /* Retrieve hardware ids of devinst, parse them and fill details into pci_dev. */
1502   if (!a->buscentric)
1503     fill_data_from_hardware_ids(d, devinst, devinst_id);
1504
1505   if (!a->buscentric)
1506     fill_resources(d, devinst, devinst_id);
1507
1508   /*
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.
1512    */
1513   if (!a->buscentric)
1514     {
1515       DEVINST parent_devinst;
1516       if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS)
1517         {
1518           parent_devinst = 0;
1519           a->warning("Cannot retrieve parent handle for device %s: %s.", devinst_id, cr_strerror(cr));
1520         }
1521       d->parent = (void *)parent_devinst;
1522     }
1523 }
1524
1525 static void
1526 win32_cfgmgr32_scan(struct pci_access *a)
1527 {
1528   ULONG devinst_id_list_size;
1529   PCHAR devinst_id_list;
1530   DEVINSTID_A devinst_id;
1531   struct pci_dev *d;
1532   CONFIGRET cr;
1533
1534   if (!resolve_cfgmgr32_functions())
1535     {
1536       a->warning("Required cfgmgr32.dll functions are unavailable.");
1537       return;
1538     }
1539
1540   /*
1541    * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1542    * support this API but returns CR_SUCCESS without touching size argument.
1543    */
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)
1547     {
1548       a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1549       return;
1550     }
1551   else if (devinst_id_list_size <= 1)
1552     {
1553       a->warning("Cannot retrieve list of PCI devices: No device was found.");
1554       return;
1555     }
1556
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)
1560     {
1561       a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1562       pci_mfree(devinst_id_list);
1563       return;
1564     }
1565
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);
1569
1570   /* Fill all drivers. */
1571   if (!a->buscentric)
1572     fill_drivers(a);
1573
1574   /* Switch parent fields from cfgmgr32 devinst handle to pci_dev. */
1575   if (!a->buscentric)
1576     {
1577       struct pci_dev *d1, *d2;
1578       for (d1 = a->devices; d1; d1 = d1->next)
1579         {
1580           for (d2 = a->devices; d2; d2 = d2->next)
1581             if ((DEVINST)d1->parent == (DEVINST)d2->backend_data)
1582               break;
1583           d1->parent = d2;
1584           if (d1->parent)
1585             d1->known_fields |= PCI_FILL_PARENT;
1586         }
1587     }
1588
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;
1592
1593   pci_mfree(devinst_id_list);
1594 }
1595
1596 static void
1597 win32_cfgmgr32_config(struct pci_access *a)
1598 {
1599   pci_define_param(a, "win32.cfgmethod", "auto", "PCI config space access method");
1600 }
1601
1602 static int
1603 win32_cfgmgr32_detect(struct pci_access *a)
1604 {
1605   ULONG devinst_id_list_size;
1606   CONFIGRET cr;
1607
1608   if (!resolve_cfgmgr32_functions())
1609     {
1610       a->debug("Required cfgmgr32.dll functions are unavailable.");
1611       return 0;
1612     }
1613
1614   /*
1615    * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1616    * support this API but returns CR_SUCCESS without touching size argument.
1617    */
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)
1621     {
1622       a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): %s.", cr_strerror(cr));
1623       return 0;
1624     }
1625   else if (devinst_id_list_size <= 1)
1626     {
1627       a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): No device was found.");
1628       return 0;
1629     }
1630
1631   return 1;
1632 }
1633
1634 static void
1635 win32_cfgmgr32_fill_info(struct pci_dev *d, unsigned int flags)
1636 {
1637   /*
1638    * All available flags were filled by win32_cfgmgr32_scan().
1639    * Filling more flags is possible only from config space.
1640    */
1641   if (!d->access->backend_data)
1642     return;
1643
1644   pci_generic_fill_info(d, flags);
1645 }
1646
1647 static int
1648 win32_cfgmgr32_read(struct pci_dev *d, int pos, byte *buf, int len)
1649 {
1650   struct pci_access *a = d->access;
1651   struct pci_access *acfg = a->backend_data;
1652   struct pci_dev *dcfg = d->backend_data;
1653
1654   if (!acfg)
1655     return pci_emulated_read(d, pos, buf, len);
1656
1657   if (!dcfg)
1658     d->backend_data = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
1659
1660   return pci_read_block(dcfg, pos, buf, len);
1661 }
1662
1663 static int
1664 win32_cfgmgr32_write(struct pci_dev *d, int pos, byte *buf, int len)
1665 {
1666   struct pci_access *a = d->access;
1667   struct pci_access *acfg = a->backend_data;
1668   struct pci_dev *dcfg = d->backend_data;
1669
1670   if (!acfg)
1671     return 0;
1672
1673   if (!dcfg)
1674     d->backend_data = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
1675
1676   return pci_write_block(dcfg, pos, buf, len);
1677 }
1678
1679 static void
1680 win32_cfgmgr32_cleanup_dev(struct pci_dev *d)
1681 {
1682   struct pci_dev *dcfg = d->backend_data;
1683
1684   if (dcfg)
1685     pci_free_dev(dcfg);
1686 }
1687
1688 static void
1689 win32_cfgmgr32_init(struct pci_access *a)
1690 {
1691   char *cfgmethod = pci_get_param(a, "win32.cfgmethod");
1692   struct pci_access *acfg;
1693
1694   if (strcmp(cfgmethod, "") == 0 ||
1695       strcmp(cfgmethod, "auto") == 0)
1696     {
1697       acfg = pci_clone_access(a);
1698       acfg->method = PCI_ACCESS_AUTO;
1699     }
1700   else if (strcmp(cfgmethod, "none") == 0 ||
1701            strcmp(cfgmethod, "win32-cfgmgr32") == 0)
1702     {
1703       if (a->writeable)
1704         a->error("Write access requested but option win32.cfgmethod was not set.");
1705       return;
1706     }
1707   else
1708     {
1709       int m = pci_lookup_method(cfgmethod);
1710       if (m < 0)
1711         a->error("Option win32.cfgmethod is set to an unknown access method \"%s\".", cfgmethod);
1712       acfg = pci_clone_access(a);
1713       acfg->method = m;
1714     }
1715
1716   a->debug("Loading config space access method...\n");
1717   if (!pci_init_internal(acfg, PCI_ACCESS_WIN32_CFGMGR32))
1718     {
1719       pci_cleanup(acfg);
1720       a->debug("Cannot find any working config space access method.\n");
1721       if (a->writeable)
1722         a->error("Write access requested but no usable access method found.");
1723       return;
1724     }
1725
1726   a->backend_data = acfg;
1727 }
1728
1729 static void
1730 win32_cfgmgr32_cleanup(struct pci_access *a)
1731 {
1732   struct pci_access *acfg = a->backend_data;
1733
1734   if (acfg)
1735     pci_cleanup(acfg);
1736 }
1737
1738 struct pci_methods pm_win32_cfgmgr32 = {
1739   "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,
1752 };