]> mj.ucw.cz Git - pciutils.git/blob - lib/win32-cfgmgr32.c
libpci: win32-cfgmgr32: Define mMD_Prefetchable constant
[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 #ifndef mMD_Prefetchable
85 #define mMD_Prefetchable fMD_Prefetchable
86 #endif
87
88 /*
89  * Unfortunately MinGW32 toolchain does not provide import library for these
90  * cfgmgr32.dll functions. So resolve pointers to these functions at runtime.
91  */
92
93 #ifdef CM_Get_DevNode_Registry_PropertyA
94 #undef CM_Get_DevNode_Registry_PropertyA
95 #endif
96 static CONFIGRET (WINAPI *MyCM_Get_DevNode_Registry_PropertyA)(DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType, PVOID Buffer, PULONG pulLength, ULONG ulFlags);
97 #define CM_Get_DevNode_Registry_PropertyA MyCM_Get_DevNode_Registry_PropertyA
98
99 #ifdef CM_Get_DevNode_Registry_PropertyW
100 #undef CM_Get_DevNode_Registry_PropertyW
101 #endif
102 static CONFIGRET (WINAPI *MyCM_Get_DevNode_Registry_PropertyW)(DEVINST dnDevInst, ULONG ulProperty, PULONG pulRegDataType, PVOID Buffer, PULONG pulLength, ULONG ulFlags);
103 #define CM_Get_DevNode_Registry_PropertyW MyCM_Get_DevNode_Registry_PropertyW
104
105 #ifndef CM_Open_DevNode_Key
106 #undef CM_Open_DevNode_Key
107 #endif
108 static CONFIGRET (WINAPI *MyCM_Open_DevNode_Key)(DEVINST dnDevNode, REGSAM samDesired, ULONG ulHardwareProfile, REGDISPOSITION Disposition, PHKEY phkDevice, ULONG ulFlags);
109 #define CM_Open_DevNode_Key MyCM_Open_DevNode_Key
110
111 static BOOL
112 resolve_cfgmgr32_functions(void)
113 {
114   HMODULE cfgmgr32;
115
116   if (CM_Get_DevNode_Registry_PropertyA && CM_Get_DevNode_Registry_PropertyW && CM_Open_DevNode_Key)
117     return TRUE;
118
119   cfgmgr32 = GetModuleHandleA("cfgmgr32.dll");
120   if (!cfgmgr32)
121     return FALSE;
122
123   CM_Get_DevNode_Registry_PropertyA = (void *)GetProcAddress(cfgmgr32, "CM_Get_DevNode_Registry_PropertyA");
124   CM_Get_DevNode_Registry_PropertyW = (void *)GetProcAddress(cfgmgr32, "CM_Get_DevNode_Registry_PropertyW");
125   CM_Open_DevNode_Key = (void *)GetProcAddress(cfgmgr32, "CM_Open_DevNode_Key");
126   if (!CM_Get_DevNode_Registry_PropertyA || !CM_Get_DevNode_Registry_PropertyW || !CM_Open_DevNode_Key)
127     return FALSE;
128
129   return TRUE;
130 }
131
132 /*
133  * cfgmgr32.dll uses custom non-Win32 error numbers which are unsupported by
134  * Win32 APIs like GetLastError() and FormatMessage() functions.
135  *
136  * Windows 7 introduced new cfgmgr32.dll function CM_MapCrToWin32Err() for
137  * translating mapping CR_* errors to Win32 errors but most error codes are
138  * not mapped. So this function is unusable.
139  *
140  * Error strings for CR_* errors are defined in cmapi.rc file which is
141  * statically linked into some system libraries (e.g. filemgmt.dll,
142  * acledit.dll, netui0.dll or netui2.dll) but due to static linking it is
143  * not possible to access these error strings easily at runtime.
144  *
145  * So define own function for translating CR_* errors directly to strings.
146  */
147 static const char *
148 cr_strerror(CONFIGRET cr_error_id)
149 {
150   static char unknown_error[sizeof("Unknown CR error XXXXXXXXXX")];
151   static const char *cr_errors[] = {
152     "The operation completed successfully",
153     "CR_DEFAULT",
154     "Not enough memory is available to process this command",
155     "A required pointer parameter is invalid",
156     "The ulFlags parameter specified is invalid for this operation",
157     "The device instance handle parameter is not valid",
158     "The supplied resource descriptor parameter is invalid",
159     "The supplied logical configuration parameter is invalid",
160     "CR_INVALID_ARBITRATOR",
161     "CR_INVALID_NODELIST",
162     "CR_DEVNODE_HAS_REQS/CR_DEVINST_HAS_REQS",
163     "The RESOURCEID parameter does not contain a valid RESOURCEID",
164     "CR_DLVXD_NOT_FOUND",
165     "The specified device instance handle does not correspond to a present device",
166     "There are no more logical configurations available",
167     "There are no more resource descriptions available",
168     "This device instance already exists",
169     "The supplied range list parameter is invalid",
170     "CR_INVALID_RANGE",
171     "A general internal error occurred",
172     "CR_NO_SUCH_LOGICAL_DEV",
173     "The device is disabled for this configuration",
174     "CR_NOT_SYSTEM_VM",
175     "A service or application refused to allow removal of this device",
176     "CR_APM_VETOED",
177     "CR_INVALID_LOAD_TYPE",
178     "An output parameter was too small to hold all the data available",
179     "CR_NO_ARBITRATOR",
180     "CR_NO_REGISTRY_HANDLE",
181     "A required entry in the registry is missing or an attempt to write to the registry failed",
182     "The specified Device ID is not a valid Device ID",
183     "One or more parameters were invalid",
184     "CR_INVALID_API",
185     "CR_DEVLOADER_NOT_READY",
186     "CR_NEED_RESTART",
187     "There are no more hardware profiles available",
188     "CR_DEVICE_NOT_THERE",
189     "The specified value does not exist in the registry",
190     "CR_WRONG_TYPE",
191     "The specified priority is invalid for this operation",
192     "This device cannot be disabled",
193     "CR_FREE_RESOURCES",
194     "CR_QUERY_VETOED",
195     "CR_CANT_SHARE_IRQ",
196     "CR_NO_DEPENDENT",
197     "CR_SAME_RESOURCES",
198     "The specified key does not exist in the registry",
199     "The specified machine name does not meet the UNC naming conventions",
200     "A general remote communication error occurred",
201     "The machine selected for remote communication is not available at this time",
202     "The Plug and Play service or another required service is not available",
203     "Access denied",
204     "This routine is not implemented in this version of the operating system",
205     "The specified property type is invalid for this operation",
206     "Device interface is active",
207     "No such device interface",
208     "Invalid reference string",
209     "Invalid conflict list",
210     "Invalid index",
211     "Invalid structure size"
212   };
213   if (cr_error_id <= 0 || cr_error_id >= sizeof(cr_errors)/sizeof(*cr_errors))
214     {
215       sprintf(unknown_error, "Unknown CR error %lu", cr_error_id);
216       return unknown_error;
217     }
218   return cr_errors[cr_error_id];
219 }
220
221 static int
222 fmt_validate(const char *s, int len, const char *fmt)
223 {
224   int i;
225
226   for (i = 0; i < len; i++)
227     if (!fmt[i] || (fmt[i] == '#' ? !isxdigit(s[i]) : fmt[i] != s[i]))
228       return 0;
229
230   return 1;
231 }
232
233 static int
234 seq_xdigit_validate(const char *s, int mult, int min)
235 {
236   int i, len;
237
238   len = strlen(s);
239   if (len < min*mult || len % mult)
240     return 0;
241
242   for (i = 0; i < len; i++)
243     if (!isxdigit(s[i]))
244       return 0;
245
246   return 1;
247 }
248
249 static LPWSTR
250 get_device_service_name(struct pci_access *a, DEVINST devinst, DEVINSTID_A devinst_id, BOOL *supported)
251 {
252   ULONG reg_type, reg_size, reg_len;
253   LPWSTR service_name;
254   CONFIGRET cr;
255
256   /*
257    * All data are stored as 7-bit ASCII strings in system but service name is
258    * exception. It can contain UNICODE. Moreover it is passed to other Win32 API
259    * functions and therefore it cannot be converted to 8-bit ANSI string without
260    * data loss. So use wide function CM_Get_DevNode_Registry_PropertyW() in this
261    * case and deal with all wchar_t problems...
262    */
263
264   reg_size = 0;
265   cr = CM_Get_DevNode_Registry_PropertyW(devinst, CM_DRP_SERVICE, &reg_type, NULL, &reg_size, 0);
266   if (cr == CR_CALL_NOT_IMPLEMENTED)
267     {
268       *supported = FALSE;
269       return NULL;
270     }
271   else if (cr == CR_NO_SUCH_VALUE)
272     {
273       *supported = TRUE;
274       return NULL;
275     }
276   else if (cr != CR_SUCCESS &&
277            cr != CR_BUFFER_SMALL)
278     {
279       a->warning("Cannot retrieve service name for PCI device %s: %s.", devinst_id, cr_strerror(cr));
280       *supported = TRUE;
281       return NULL;
282     }
283   else if (reg_type != REG_SZ)
284     {
285       a->warning("Cannot retrieve service name for PCI device %s: Service name is stored as unknown type 0x%lx.", devinst_id, reg_type);
286       *supported = TRUE;
287       return NULL;
288     }
289
290 retry:
291   /*
292    * Returned size is on older Windows versions without nul-term char.
293    * So explicitly increase size and fill nul-term byte.
294    */
295   reg_size += sizeof(service_name[0]);
296   service_name = pci_malloc(a, reg_size);
297   reg_len = reg_size;
298   cr = CM_Get_DevNode_Registry_PropertyW(devinst, CM_DRP_SERVICE, &reg_type, service_name, &reg_len, 0);
299   service_name[reg_size/sizeof(service_name[0]) - 1] = 0;
300   if (reg_len > reg_size)
301     {
302       pci_mfree(service_name);
303       reg_size = reg_len;
304       goto retry;
305     }
306   else if (cr != CR_SUCCESS)
307     {
308       a->warning("Cannot retrieve service name for PCI device %s: %s.", devinst_id, cr_strerror(cr));
309       pci_mfree(service_name);
310       *supported = TRUE;
311       return NULL;
312     }
313   else if (reg_type != REG_SZ)
314     {
315       a->warning("Cannot retrieve service name for PCI device %s: Service name is stored as unknown type 0x%lx.", devinst_id, reg_type);
316       pci_mfree(service_name);
317       *supported = TRUE;
318       return NULL;
319     }
320
321
322   return service_name;
323 }
324
325 static char*
326 get_driver_path_for_service(struct pci_access *a, LPCWSTR service_name, SC_HANDLE manager)
327 {
328   UINT (WINAPI *get_system_root_path)(LPWSTR buffer, UINT size) = NULL;
329   DWORD service_config_size, service_config_len;
330   LPQUERY_SERVICE_CONFIGW service_config = NULL;
331   LPWSTR service_image_path = NULL;
332   SERVICE_STATUS service_status;
333   SC_HANDLE service = NULL;
334   char *driver_path = NULL;
335   int trim_system32 = 0;
336   UINT systemroot_len;
337   int driver_path_len;
338   UINT system32_len;
339   HMODULE kernel32;
340   WCHAR *trim_ptr;
341   DWORD error;
342
343   service = OpenServiceW(manager, service_name, SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS);
344   if (!service)
345     {
346       error = GetLastError();
347       if (error != ERROR_SERVICE_DOES_NOT_EXIST)
348         a->warning("Cannot open service %ls with query rights: %s.", service_name, win32_strerror(error));
349       goto out;
350     }
351
352   if (!QueryServiceStatus(service, &service_status))
353     {
354       error = GetLastError();
355       a->warning("Cannot query status of service %ls: %s.", service_name, win32_strerror(error));
356       goto out;
357     }
358
359   if (service_status.dwCurrentState == SERVICE_STOPPED)
360     goto out;
361
362   if (service_status.dwServiceType != SERVICE_KERNEL_DRIVER)
363     goto out;
364
365   if (!QueryServiceConfigW(service, NULL, 0, &service_config_size))
366     {
367       error = GetLastError();
368       if (error != ERROR_INSUFFICIENT_BUFFER)
369       {
370         a->warning("Cannot query config of service %ls: %s.", service_name, win32_strerror(error));
371         goto out;
372       }
373     }
374
375 retry_service_config:
376   service_config = pci_malloc(a, service_config_size);
377   if (!QueryServiceConfigW(service, service_config, service_config_size, &service_config_len))
378     {
379       error = GetLastError();
380       if (error == ERROR_INSUFFICIENT_BUFFER)
381         {
382           pci_mfree(service_config);
383           service_config_size = service_config_len;
384           goto retry_service_config;
385         }
386       a->warning("Cannot query config of service %ls: %s.", service_name, win32_strerror(error));
387       goto out;
388     }
389
390   if (service_config->dwServiceType != SERVICE_KERNEL_DRIVER)
391     goto out;
392
393   /*
394    * Despite QueryServiceConfig() is Win32 API, it returns lpBinaryPathName
395    * (ImagePath registry) in NT format. Unfortunately there is no Win32
396    * function for converting NT paths to Win32 paths. So do it manually and
397    * convert this NT format to human-readable Win32 path format.
398    */
399
400   /*
401    * GetSystemWindowsDirectoryW() returns path to NT SystemRoot namespace.
402    * Alternativelly path to NT SystemRoot namespace can be constructed by
403    * GetSystemDirectoryW() by trimming "\\system32" from the end of path.
404    * GetSystemWindowsDirectoryW() is not provided in old Windows versions,
405    * so use GetProcAddress() for compatibility with all Windows versions.
406    */
407   kernel32 = GetModuleHandleW(L"kernel32.dll");
408   if (kernel32)
409     get_system_root_path = (void *)GetProcAddress(kernel32, "GetSystemWindowsDirectoryW");
410   else
411     {
412       get_system_root_path = &GetSystemDirectoryW;
413       trim_system32 = 1;
414     }
415
416   if (!service_config->lpBinaryPathName || !service_config->lpBinaryPathName[0])
417     {
418       /* No ImagePath is specified, NT kernel assumes implicit kernel driver path by service name, which is relative to "\\system32\\drivers". */
419       /* GetSystemDirectoryW() returns path to "\\system32" directory on all Windows versions. */
420       system32_len = GetSystemDirectoryW(NULL, 0); /* Returns number of WCHARs plus 1 for nul-term. */
421       service_image_path = pci_malloc(a, sizeof(WCHAR) * (system32_len + sizeof("\\drivers\\")-1 + wcslen(service_name) + sizeof(".sys")-1));
422       system32_len = GetSystemDirectoryW(service_image_path, system32_len); /* Now it returns number of WCHARs without nul-term. */
423       if (system32_len && service_image_path[system32_len-1] != L'\\')
424         service_image_path[system32_len++] = L'\\';
425       wcscpy(service_image_path + system32_len, L"drivers\\");
426       wcscpy(service_image_path + system32_len + sizeof("drivers\\")-1, service_name);
427       wcscpy(service_image_path + system32_len + sizeof("drivers\\")-1 + wcslen(service_name), L".sys");
428     }
429   else if (wcsncmp(service_config->lpBinaryPathName, L"\\SystemRoot\\", sizeof("\\SystemRoot\\")-1) == 0)
430     {
431       /* ImagePath is in NT SystemRoot namespace, convert to Win32 path via GetSystemWindowsDirectoryW()/GetSystemDirectoryW(). */
432       systemroot_len = get_system_root_path(NULL, 0); /* Returns number of WCHARs plus 1 for nul-term. */
433       service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + wcslen(service_config->lpBinaryPathName) - (sizeof("\\SystemRoot")-1)));
434       systemroot_len = get_system_root_path(service_image_path, systemroot_len); /* Now it returns number of WCHARs without nul-term. */
435       if (trim_system32 && systemroot_len && (trim_ptr = wcsrchr(service_image_path, L'\\')) != NULL)
436         systemroot_len = trim_ptr - service_image_path;
437       if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
438         service_image_path[systemroot_len++] = L'\\';
439       wcscpy(service_image_path + systemroot_len, service_config->lpBinaryPathName + sizeof("\\SystemRoot\\")-1);
440     }
441   else if (wcsncmp(service_config->lpBinaryPathName, L"\\??\\UNC\\", sizeof("\\??\\UNC\\")-1) == 0 ||
442            wcsncmp(service_config->lpBinaryPathName, L"\\??\\\\UNC\\", sizeof("\\??\\\\UNC\\")-1) == 0)
443     {
444       /* ImagePath is in NT UNC namespace, convert to Win32 UNC path via "\\\\" prefix. */
445       service_image_path = pci_malloc(a, sizeof(WCHAR) * (sizeof("\\\\") + wcslen(service_config->lpBinaryPathName) - (sizeof("\\??\\UNC\\")-1)));
446       /* Namespace separator may be single or double backslash. */
447       driver_path_len = sizeof("\\??\\")-1;
448       if (service_config->lpBinaryPathName[driver_path_len] == L'\\')
449         driver_path_len++;
450       driver_path_len += sizeof("UNC\\")-1;
451       wcscpy(service_image_path, L"\\\\");
452       wcscpy(service_image_path + sizeof("\\\\")-1, service_config->lpBinaryPathName + driver_path_len);
453     }
454   else if (wcsncmp(service_config->lpBinaryPathName, L"\\??\\", sizeof("\\??\\")-1) == 0)
455     {
456       /* ImagePath is in NT Global?? namespace, root of the Win32 file namespace, so just remove "\\??\\" prefix to get Win32 path. */
457       service_image_path = pci_malloc(a, sizeof(WCHAR) * (wcslen(service_config->lpBinaryPathName) - (sizeof("\\??\\")-1)));
458       /* Namespace separator may be single or double backslash. */
459       driver_path_len = sizeof("\\??\\")-1;
460       if (service_config->lpBinaryPathName[driver_path_len] == L'\\')
461         driver_path_len++;
462       wcscpy(service_image_path, service_config->lpBinaryPathName + driver_path_len);
463     }
464   else if (service_config->lpBinaryPathName[0] != L'\\')
465     {
466       /* ImagePath is relative to the NT SystemRoot namespace, convert to Win32 path via GetSystemWindowsDirectoryW()/GetSystemDirectoryW(). */
467       systemroot_len = get_system_root_path(NULL, 0); /* Returns number of WCHARs plus 1 for nul-term. */
468       service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + sizeof("\\")-1 + wcslen(service_config->lpBinaryPathName)));
469       systemroot_len = get_system_root_path(service_image_path, systemroot_len); /* Now it returns number of WCHARs without nul-term. */
470       if (trim_system32 && systemroot_len && (trim_ptr = wcsrchr(service_image_path, L'\\')) != NULL)
471         systemroot_len = trim_ptr - service_image_path;
472       if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
473         service_image_path[systemroot_len++] = L'\\';
474       wcscpy(service_image_path + systemroot_len, service_config->lpBinaryPathName);
475     }
476   else
477     {
478       /* ImagePath is in some unhandled NT namespace, copy it as is. It cannot be used in Win32 API but libpci user can be still interested in it. */
479       service_image_path = pci_malloc(a, sizeof(WCHAR) * wcslen(service_config->lpBinaryPathName));
480       wcscpy(service_image_path, service_config->lpBinaryPathName);
481     }
482
483   /* Calculate len of buffer needed for conversion from LPWSTR to char*. */
484   driver_path_len = WideCharToMultiByte(CP_ACP, 0, service_image_path, -1, NULL, 0, NULL, NULL);
485   if (driver_path_len <= 0)
486     {
487       error = GetLastError();
488       a->warning("Cannot convert kernel driver path from wide string to 8-bit string: %s.", win32_strerror(error));
489       goto out;
490     }
491
492   driver_path = pci_malloc(a, driver_path_len);
493   driver_path_len = WideCharToMultiByte(CP_ACP, 0, service_image_path, -1, driver_path, driver_path_len, NULL, NULL);
494   if (driver_path_len <= 0)
495     {
496       error = GetLastError();
497       a->warning("Cannot convert kernel driver path from wide string to 8-bit string: %s.", win32_strerror(error));
498       pci_mfree(driver_path);
499       driver_path = NULL;
500       goto out;
501     }
502
503 out:
504   if (service_image_path)
505     pci_mfree(service_image_path);
506   if (service_config)
507     pci_mfree(service_config);
508   if (service)
509     CloseServiceHandle(service);
510   return driver_path;
511 }
512
513 static HKEY
514 get_device_driver_devreg(struct pci_access *a, DEVINST devinst, DEVINSTID_A devinst_id)
515 {
516   CONFIGRET cr;
517   HKEY key;
518
519   cr = CM_Open_DevNode_Key(devinst, KEY_READ, 0, RegDisposition_OpenExisting, &key, CM_REGISTRY_SOFTWARE);
520   if (cr != CR_SUCCESS)
521     {
522       if (cr != CR_NO_SUCH_VALUE)
523         a->warning("Cannot retrieve driver key for device %s: %s.", devinst_id, cr_strerror(cr));
524       return NULL;
525     }
526
527   return key;
528 }
529
530 static char*
531 read_reg_key_string_value(struct pci_access *a, HKEY key, const char *name, DWORD *unkn_reg_type)
532 {
533   DWORD reg_type, reg_size, reg_len;
534   char *value;
535   LONG error;
536
537   reg_size = 0;
538   error = RegQueryValueExA(key, name, NULL, &reg_type, NULL, &reg_size);
539   if (error != ERROR_SUCCESS &&
540       error != ERROR_MORE_DATA)
541     {
542       SetLastError(error);
543       return NULL;
544     }
545   else if (reg_type != REG_SZ)
546     {
547       SetLastError(0);
548       *unkn_reg_type = reg_type;
549       return NULL;
550     }
551
552 retry:
553   value = pci_malloc(a, reg_size + 1);
554   reg_len = reg_size;
555   error = RegQueryValueExA(key, name, NULL, &reg_type, (PBYTE)value, &reg_len);
556   if (error != ERROR_SUCCESS)
557     {
558       pci_mfree(value);
559       if (error == ERROR_MORE_DATA)
560         {
561           reg_size = reg_len;
562           goto retry;
563         }
564       SetLastError(error);
565       return NULL;
566     }
567   else if (reg_type != REG_SZ)
568     {
569       pci_mfree(value);
570       SetLastError(0);
571       *unkn_reg_type = reg_type;
572       return NULL;
573     }
574   value[reg_len] = '\0';
575
576   return value;
577 }
578
579 static int
580 driver_cmp(const char *driver, const char *match)
581 {
582   int len = strlen(driver);
583   if (driver[0] == '*')
584     driver++;
585   if (len >= 4 && strcasecmp(driver + len - 4, ".vxd") == 0)
586     len -= 4;
587   return strncasecmp(driver, match, len);
588 }
589
590 static char*
591 get_driver_path_for_regkey(struct pci_access *a, DEVINSTID_A devinst_id, HKEY key)
592 {
593   char *driver_list, *driver, *driver_next;
594   char *subdriver, *subname;
595   char *driver_ptr;
596   char *driver_path;
597   DWORD unkn_reg_type;
598   UINT systemdir_len;
599   HKEY subkey;
600   LONG error;
601   BOOL vmm32;
602   BOOL noext;
603   int len;
604
605   driver_list = read_reg_key_string_value(a, key, "DevLoader", &unkn_reg_type);
606   if (!driver_list)
607     {
608       error = GetLastError();
609       if (error == 0)
610         a->warning("Cannot read driver DevLoader key for PCI device %s: DevLoader key is stored as unknown type 0x%lx.", devinst_id, unkn_reg_type);
611       else if (error != ERROR_FILE_NOT_FOUND)
612         a->warning("Cannot read driver DevLoader key for PCI device %s: %s.", devinst_id, win32_strerror(error));
613       return NULL;
614     }
615
616   subdriver = NULL;
617   driver = driver_list;
618   while (*driver)
619     {
620       driver_next = strchr(driver, ',');
621       if (driver_next)
622           *(driver_next++) = '\0';
623
624       if (driver_cmp(driver, "ios") == 0 ||
625           driver_cmp(driver, "vcomm") == 0)
626         subname = "PortDriver";
627       else if (driver_cmp(driver, "ntkern") == 0)
628         subname = "NTMPDriver";
629       else if (driver_cmp(driver, "ndis") == 0)
630         subname = "DeviceVxDs";
631       else if (driver_cmp(driver, "vdd") == 0)
632         subname = "minivdd";
633       else
634         subname = NULL;
635
636       subkey = key;
637       if (subname && strcmp(subname, "minivdd") == 0)
638         {
639           error = RegOpenKeyA(key, "Default", &subkey);
640           if (error != ERROR_SUCCESS)
641             {
642               a->warning("Cannot open driver subkey Default for PCI device %s: %s.", devinst_id, win32_strerror(error));
643               subkey = NULL;
644             }
645         }
646
647       if (!subname)
648         break;
649
650       if (subkey)
651         {
652 retry_subname:
653           subdriver = read_reg_key_string_value(a, subkey, subname, &unkn_reg_type);
654           if (!subdriver)
655             {
656               error = GetLastError();
657               if (error == 0)
658                 a->warning("Cannot read driver %s key for PCI device %s: %s key is stored as unknown type 0x%lx.", subname, devinst_id, subname, unkn_reg_type);
659               else if (error != ERROR_FILE_NOT_FOUND)
660                 a->warning("Cannot read driver %s key for PCI device %s: %s.", subname, devinst_id, win32_strerror(error));
661               else if (strcmp(subname, "minivdd") == 0)
662                 {
663                   subname = "drv";
664                   goto retry_subname;
665                 }
666               else if (strcmp(subname, "drv") == 0)
667                 {
668                   subname = "vdd";
669                   goto retry_subname;
670                 }
671             }
672
673           if (subkey != key)
674             RegCloseKey(subkey);
675
676           if (subdriver)
677             {
678               char *endptr = strchr(subdriver, ',');
679               if (endptr)
680                 *endptr = '\0';
681               break;
682             }
683         }
684
685       driver = driver_next;
686     }
687
688   if (subdriver && subdriver[0])
689     driver_ptr = subdriver;
690   else if (driver[0])
691     driver_ptr = driver;
692   else
693     driver_ptr = NULL;
694
695   if (driver_ptr && driver_ptr[0] == '*')
696     {
697       vmm32 = TRUE;
698       driver_ptr++;
699     }
700   else
701     vmm32 = FALSE;
702
703   if (!driver_ptr[0])
704     driver_ptr = NULL;
705
706   len = driver_ptr ? strlen(driver_ptr) : 0;
707   noext = driver_ptr && (len < 4 || driver_ptr[len-4] != '.');
708
709   if (!driver_ptr)
710     driver_path = NULL;
711   else
712     {
713       if (tolower(driver_ptr[0]) >= 'a' && tolower(driver_ptr[0]) <= 'z' && driver_ptr[1] == ':')
714         {
715           /* Driver is already with absolute path. */
716           driver_path = pci_strdup(a, driver_ptr);
717         }
718       else if (driver_cmp(driver, "ntkern") == 0 && subdriver)
719         {
720           /* Driver is relative to system32\drivers\ directory which is relative to windows directory. */
721           systemdir_len = GetWindowsDirectoryA(NULL, 0);
722           driver_path = pci_malloc(a, systemdir_len + 1 + sizeof("system32\\drivers\\")-1 + strlen(driver_ptr) + 4 + 1);
723           systemdir_len = GetWindowsDirectoryA(driver_path, systemdir_len + 1);
724           if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
725             driver_path[systemdir_len++] = '\\';
726           sprintf(driver_path + systemdir_len, "system32\\drivers\\%s%s", driver_ptr, noext ? ".sys" : "");
727         }
728       else if (vmm32)
729         {
730           /* Driver is packed in vmm32.vxd which is stored in system directory. */
731           systemdir_len = GetSystemDirectoryA(NULL, 0);
732           driver_path = pci_malloc(a, systemdir_len + 1 + sizeof("vmm32.vxd ()")-1 + strlen(driver_ptr) + 4 + 1);
733           systemdir_len = GetSystemDirectoryA(driver_path, systemdir_len + 1);
734           if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
735             driver_path[systemdir_len++] = '\\';
736           sprintf(driver_path + systemdir_len, "vmm32.vxd (%s%s)", driver_ptr, noext ? ".vxd" : "");
737         }
738       else
739         {
740           /* Otherwise driver is relative to system directory. */
741           systemdir_len = GetSystemDirectoryA(NULL, 0);
742           driver_path = pci_malloc(a, systemdir_len + 1 + strlen(driver_ptr) + 4 + 1);
743           systemdir_len = GetSystemDirectoryA(driver_path, systemdir_len + 1);
744           if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
745             driver_path[systemdir_len++] = '\\';
746           sprintf(driver_path + systemdir_len, "%s%s", driver_ptr, noext ? ".vxd" : "");
747         }
748     }
749
750   if (subdriver)
751     pci_mfree(subdriver);
752   pci_mfree(driver_list);
753   return driver_path;
754 }
755
756 static char *
757 get_device_driver_path(struct pci_dev *d, SC_HANDLE manager, BOOL manager_supported)
758 {
759   struct pci_access *a = d->access;
760   BOOL service_supported = TRUE;
761   DEVINSTID_A devinst_id = NULL;
762   LPWSTR service_name = NULL;
763   ULONG devinst_id_len = 0;
764   char *driver_path = NULL;
765   DEVINST devinst = (DEVINST)d->backend_data;
766   ULONG problem = 0;
767   ULONG status = 0;
768   HKEY key = NULL;
769
770   if (CM_Get_DevNode_Status(&status, &problem, devinst, 0) != CR_SUCCESS || !(status & DN_DRIVER_LOADED))
771     return NULL;
772
773   if (CM_Get_Device_ID_Size(&devinst_id_len, devinst, 0) == CR_SUCCESS)
774     {
775       devinst_id = pci_malloc(a, devinst_id_len + 1);
776       if (CM_Get_Device_IDA(devinst, devinst_id, devinst_id_len + 1, 0) != CR_SUCCESS)
777         {
778           pci_mfree(devinst_id);
779           devinst_id = pci_strdup(a, "UNKNOWN");
780         }
781     }
782   else
783     devinst_id = pci_strdup(a, "UNKNOWN");
784
785   service_name = get_device_service_name(d->access, devinst, devinst_id, &service_supported);
786   if ((!service_name || !manager) && service_supported && manager_supported)
787     goto out;
788   else if (service_name && manager)
789     {
790       driver_path = get_driver_path_for_service(d->access, service_name, manager);
791       goto out;
792     }
793
794   key = get_device_driver_devreg(d->access, devinst, devinst_id);
795   if (key)
796     {
797       driver_path = get_driver_path_for_regkey(d->access, devinst_id, key);
798       goto out;
799     }
800
801 out:
802   if (key)
803     RegCloseKey(key);
804   if (service_name)
805     pci_mfree(service_name);
806   pci_mfree(devinst_id);
807   return driver_path;
808 }
809
810 static void
811 fill_drivers(struct pci_access *a)
812 {
813   BOOL manager_supported;
814   SC_HANDLE manager;
815   struct pci_dev *d;
816   char *driver;
817   DWORD error;
818
819   /* ERROR_CALL_NOT_IMPLEMENTED is returned on systems without Service Manager support. */
820   manager_supported = TRUE;
821   manager = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
822   if (!manager)
823     {
824       error = GetLastError();
825       if (error != ERROR_CALL_NOT_IMPLEMENTED)
826         a->warning("Cannot open Service Manager with connect right: %s.", win32_strerror(error));
827       else
828         manager_supported = FALSE;
829     }
830
831   for (d = a->devices; d; d = d->next)
832     {
833       driver = get_device_driver_path(d, manager, manager_supported);
834       if (driver)
835         {
836           pci_set_property(d, PCI_FILL_DRIVER, driver);
837           pci_mfree(driver);
838         }
839       d->known_fields |= PCI_FILL_DRIVER;
840     }
841
842   if (manager)
843     CloseServiceHandle(manager);
844 }
845
846 static const char *
847 res_id_to_str(RESOURCEID res_id)
848 {
849   static char hex_res_id[sizeof("0xffffffff")];
850
851   if (res_id == ResType_IO)
852     return "IO";
853   else if (res_id == ResType_Mem)
854     return "MEM";
855   else if (res_id == ResType_IRQ)
856     return "IRQ";
857
858   sprintf(hex_res_id, "0x%lx", res_id);
859   return hex_res_id;
860 }
861
862 static void
863 fill_resources(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
864 {
865   struct pci_access *a = d->access;
866
867   CONFIGRET cr;
868
869   LOG_CONF config;
870   ULONG problem;
871   ULONG status;
872
873   RES_DES prev_res_des;
874   RES_DES res_des;
875   RESOURCEID res_id;
876   DWORD bar_res_count;
877
878   BOOL is_bar_res;
879   BOOL non_nt_system;
880
881   int last_irq = -1;
882   int last_shared_irq = -1;
883
884   cr = CM_Get_DevNode_Status(&status, &problem, devinst, 0);
885   if (cr != CR_SUCCESS)
886     {
887       a->warning("Cannot retrieve status of PCI device %s: %s.", devinst_id, cr_strerror(cr));
888       return;
889     }
890
891   cr = CR_NO_MORE_LOG_CONF;
892
893   /*
894    * If the device is running then retrieve allocated configuration by PnP
895    * manager which is currently in use by a device.
896    */
897   if (!(status & DN_HAS_PROBLEM))
898     cr = CM_Get_First_Log_Conf(&config, devinst, ALLOC_LOG_CONF);
899
900   /*
901    * If the device is not running or it does not have allocated configuration by
902    * PnP manager then retrieve forced configuration which prevents PnP manager
903    * from assigning resources.
904    */
905   if (cr == CR_NO_MORE_LOG_CONF)
906     cr = CM_Get_First_Log_Conf(&config, devinst, FORCED_LOG_CONF);
907
908   /*
909    * If the device does not have neither allocated configuration by PnP manager
910    * nor forced configuration and it is not disabled in the BIOS then retrieve
911    * boot configuration supplied by the BIOS.
912    */
913   if (cr == CR_NO_MORE_LOG_CONF &&
914       (!(status & DN_HAS_PROBLEM) || problem != CM_PROB_HARDWARE_DISABLED))
915     cr = CM_Get_First_Log_Conf(&config, devinst, BOOT_LOG_CONF);
916
917   if (cr != CR_SUCCESS)
918     {
919       /*
920        * Note: Starting with Windows 8, CM_Get_First_Log_Conf returns
921        * CR_CALL_NOT_IMPLEMENTED when used in a Wow64 scenario.
922        * To request information about the hardware resources on a local machine
923        * it is necessary implement an architecture-native version of the
924        * application using the hardware resource APIs. For example: An AMD64
925        * application for AMD64 systems.
926        */
927       if (cr == CR_CALL_NOT_IMPLEMENTED && win32_is_32bit_on_win8_64bit_system())
928         {
929           static BOOL warn_once = FALSE;
930           if (!warn_once)
931             {
932               warn_once = TRUE;
933               a->warning("Cannot retrieve resources of PCI devices from 32-bit application on 64-bit system.");
934             }
935         }
936       else if (cr != CR_NO_MORE_LOG_CONF)
937         a->warning("Cannot retrieve resources of PCI device %s: %s.", devinst_id, cr_strerror(cr));
938       return;
939     }
940
941   bar_res_count = 0;
942   non_nt_system = win32_is_non_nt_system();
943
944   is_bar_res = TRUE;
945   if (non_nt_system)
946     {
947       BOOL has_child;
948       DEVINST child;
949       ULONG child_name_len;
950       PSTR child_name;
951       BOOL is_bridge;
952
953       if (CM_Get_Child(&child, devinst, 0) != CR_SUCCESS)
954         has_child = FALSE;
955       else if (CM_Get_Device_ID_Size(&child_name_len, child, 0) != CR_SUCCESS)
956         has_child = FALSE;
957       else
958         {
959           child_name_len++;
960           child_name = pci_malloc(a, child_name_len);
961           if (CM_Get_Device_IDA(child, child_name, child_name_len, 0) != CR_SUCCESS)
962             has_child = FALSE;
963           else if (strncmp(child_name, "PCI\\", 4) != 0)
964             has_child = FALSE;
965           else
966             has_child = TRUE;
967           pci_mfree(child_name);
968         }
969
970       if (has_child || d->device_class == PCI_CLASS_BRIDGE_PCI || d->device_class == PCI_CLASS_BRIDGE_CARDBUS)
971         is_bridge = TRUE;
972       else
973         is_bridge = FALSE;
974
975       if (is_bridge)
976         is_bar_res = FALSE;
977     }
978
979   prev_res_des = (RES_DES)config;
980   while ((cr = CM_Get_Next_Res_Des(&res_des, prev_res_des, ResType_All, &res_id, 0)) == CR_SUCCESS)
981     {
982       pciaddr_t start, end, size, flags;
983       ULONG res_des_data_size;
984       PBYTE res_des_data;
985
986       if (prev_res_des != config)
987         CM_Free_Res_Des_Handle(prev_res_des);
988
989       prev_res_des = res_des;
990
991       /* Skip other resources early */
992       if (res_id != ResType_IO && res_id != ResType_Mem && res_id != ResType_IRQ)
993         continue;
994
995       cr = CM_Get_Res_Des_Data_Size(&res_des_data_size, res_des, 0);
996       if (cr != CR_SUCCESS)
997         {
998           a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, cr_strerror(cr));
999           continue;
1000         }
1001
1002       if (!res_des_data_size)
1003         {
1004           a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, "Empty data");
1005           continue;
1006         }
1007
1008       res_des_data = pci_malloc(a, res_des_data_size);
1009       cr = CM_Get_Res_Des_Data(res_des, res_des_data, res_des_data_size, 0);
1010       if (cr != CR_SUCCESS)
1011         {
1012           a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, cr_strerror(cr));
1013           pci_mfree(res_des_data);
1014           continue;
1015         }
1016
1017       /*
1018        * There can be more resources with the same id. In this case we are
1019        * interested in the last one in the list as at the beginning of the list
1020        * can be some virtual resources (which are not set in PCI config space).
1021        */
1022
1023       if (res_id == ResType_IO)
1024         {
1025           PIO_RESOURCE io_data = (PIO_RESOURCE)res_des_data;
1026
1027           start = io_data->IO_Header.IOD_Alloc_Base;
1028           end = io_data->IO_Header.IOD_Alloc_End;
1029           size = (end > start) ? (end - start + 1) : 0;
1030           flags = PCI_IORESOURCE_IO;
1031
1032           /*
1033            * If neither 10-bit, 12-bit, nor 16-bit support is presented then
1034            * expects that this is 32-bit I/O resource. If resource does not fit
1035            * into 16-bit space then it must be 32-bit. If PCI I/O resource is
1036            * not 32-bit then it is 16-bit.
1037            */
1038           if (end <= 0xffff && (io_data->IO_Header.IOD_DesFlags & (fIOD_10_BIT_DECODE|fIOD_12_BIT_DECODE|fIOD_16_BIT_DECODE)))
1039             flags |= PCI_IORESOURCE_IO_16BIT_ADDR;
1040
1041           /*
1042            * 16/32-bit non-NT systems do not support these two flags.
1043            * Most NT-based Windows versions support only the fIOD_WINDOW_DECODE
1044            * flag and put all BAR resources before window resources in this
1045            * resource list. So use this fIOD_WINDOW_DECODE flag as separator
1046            * between IO/MEM windows and IO/MEM BARs of PCI Bridges.
1047            */
1048           if (io_data->IO_Header.IOD_DesFlags & fIOD_WINDOW_DECODE)
1049             is_bar_res = FALSE;
1050           else if (io_data->IO_Header.IOD_DesFlags & fIOD_PORT_BAR)
1051             is_bar_res = TRUE;
1052
1053           if (is_bar_res && bar_res_count < 6)
1054             {
1055               d->flags[bar_res_count] = flags;
1056               d->base_addr[bar_res_count] = start;
1057               d->size[bar_res_count] = size;
1058               bar_res_count++;
1059             }
1060           else if (!is_bar_res)
1061             {
1062               d->bridge_flags[0] = flags;
1063               d->bridge_base_addr[0] = start;
1064               d->bridge_size[0] = size;
1065               d->known_fields |= PCI_FILL_BRIDGE_BASES;
1066             }
1067         }
1068       else if (res_id == ResType_Mem)
1069         {
1070           PMEM_RESOURCE mem_data = (PMEM_RESOURCE)res_des_data;
1071
1072           start = mem_data->MEM_Header.MD_Alloc_Base;
1073           end = mem_data->MEM_Header.MD_Alloc_End;
1074           size = (end > start) ? (end - start + 1) : 0;
1075           flags = PCI_IORESOURCE_MEM;
1076
1077           /*
1078            * If fMD_PrefetchAllowed flag is set then this is
1079            * PCI Prefetchable Memory resource.
1080            */
1081           if ((mem_data->MEM_Header.MD_Flags & mMD_Prefetchable) == fMD_PrefetchAllowed)
1082             flags |= PCI_IORESOURCE_PREFETCH;
1083
1084           /* If resource does not fit into 32-bit space then it must be 64-bit. */
1085           if (is_bar_res && end > 0xffffffff)
1086             flags |= PCI_IORESOURCE_MEM_64;
1087
1088           /*
1089            * These two flags (fMD_WINDOW_DECODE and fMD_MEMORY_BAR) are
1090            * unsupported on most Windows versions, so distinguish between
1091            * window and BAR based on previous resource type.
1092            */
1093           if (mem_data->MEM_Header.MD_Flags & fMD_WINDOW_DECODE)
1094             is_bar_res = FALSE;
1095           else if (mem_data->MEM_Header.MD_Flags & fMD_MEMORY_BAR)
1096             is_bar_res = TRUE;
1097
1098           /* 64-bit BAR resource must be at even position. */
1099           if (is_bar_res && (flags & PCI_IORESOURCE_MEM_64) && bar_res_count % 2)
1100             bar_res_count++;
1101
1102           if (is_bar_res && bar_res_count < 6)
1103             {
1104               d->flags[bar_res_count] = flags;
1105               d->base_addr[bar_res_count] = start;
1106               d->size[bar_res_count] = size;
1107               bar_res_count++;
1108               /* 64-bit BAR resource occupies two slots. */
1109               if (flags & PCI_IORESOURCE_MEM_64)
1110                 bar_res_count++;
1111             }
1112           else if (!is_bar_res && !(flags & PCI_IORESOURCE_PREFETCH))
1113             {
1114               d->bridge_flags[1] = flags;
1115               d->bridge_base_addr[1] = start;
1116               d->bridge_size[1] = size;
1117               d->known_fields |= PCI_FILL_BRIDGE_BASES;
1118             }
1119           else if (!is_bar_res && (flags & PCI_IORESOURCE_PREFETCH))
1120             {
1121               d->bridge_flags[2] = flags;
1122               d->bridge_base_addr[2] = start;
1123               d->bridge_size[2] = size;
1124               d->known_fields |= PCI_FILL_BRIDGE_BASES;
1125             }
1126         }
1127       else if (res_id == ResType_IRQ)
1128         {
1129           PIRQ_RESOURCE irq_data = (PIRQ_RESOURCE)res_des_data;
1130
1131           /*
1132            * libpci's d->irq should be set to the non-MSI PCI IRQ and therefore
1133            * it should be level IRQ which may be shared with other PCI devices
1134            * and drivers in the system. As always we want to retrieve the last
1135            * IRQ number from the resource list.
1136            *
1137            * On 16/32-bit non-NT systems is fIRQD_Level set to 2 but on NT
1138            * systems to 0. Moreover it looks like that different PCI drivers
1139            * on both NT and non-NT systems set bits 0 and 1 to wrong values
1140            * and so reported value in this list may be incorrect.
1141            *
1142            * Therefore take the last level-shared IRQ number from the resource
1143            * list and if there is none of this type then take the last IRQ
1144            * number from the list.
1145            */
1146           last_irq = irq_data->IRQ_Header.IRQD_Alloc_Num;
1147           if ((irq_data->IRQ_Header.IRQD_Flags & (mIRQD_Share|mIRQD_Edge_Level)) == (fIRQD_Share|fIRQD_Level))
1148             last_shared_irq = irq_data->IRQ_Header.IRQD_Alloc_Num;
1149
1150           /*
1151            * IRQ resource on 16/32-bit non-NT systems is separator between
1152            * IO/MEM windows and IO/MEM BARs of PCI Bridges. After the IRQ
1153            * resource are IO/MEM BAR resources.
1154            */
1155           if (!is_bar_res && non_nt_system)
1156             is_bar_res = TRUE;
1157         }
1158
1159       pci_mfree(res_des_data);
1160     }
1161   if (cr != CR_NO_MORE_RES_DES)
1162     a->warning("Cannot retrieve resources of PCI device %s: %s.", devinst_id, cr_strerror(cr));
1163
1164   if (prev_res_des != config)
1165     CM_Free_Res_Des_Handle(prev_res_des);
1166
1167   CM_Free_Log_Conf_Handle(config);
1168
1169   /* Set the last IRQ from the resource list to pci_dev. */
1170   if (last_shared_irq >= 0)
1171     d->irq = last_shared_irq;
1172   else if (last_irq >= 0)
1173     d->irq = last_irq;
1174   if (last_shared_irq >= 0 || last_irq >= 0)
1175     d->known_fields |= PCI_FILL_IRQ;
1176
1177   if (bar_res_count > 0)
1178     d->known_fields |= PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS;
1179 }
1180
1181 static BOOL
1182 get_device_location(struct pci_access *a, DEVINST devinst, DEVINSTID_A devinst_id, unsigned int *domain, unsigned int *bus, unsigned int *dev, unsigned int *func)
1183 {
1184   ULONG reg_type, reg_len;
1185   CONFIGRET cr;
1186   BOOL have_bus, have_devfunc;
1187   DWORD drp_bus_num, drp_address;
1188
1189   *domain = 0;
1190   have_bus = FALSE;
1191   have_devfunc = FALSE;
1192
1193   /*
1194    * DRP_BUSNUMBER consists of PCI domain number in high 24 bits
1195    * and PCI bus number in low 8 bits.
1196    */
1197   reg_len = sizeof(drp_bus_num);
1198   cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_BUSNUMBER, &reg_type, &drp_bus_num, &reg_len, 0);
1199   if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_bus_num))
1200     {
1201       *domain = drp_bus_num >> 8;
1202       *bus = drp_bus_num & 0xff;
1203       have_bus = TRUE;
1204     }
1205
1206   /*
1207    * DRP_ADDRESS consists of PCI device number in high 16 bits
1208    * and PCI function number in low 16 bits.
1209    */
1210   reg_len = sizeof(drp_address);
1211   cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_ADDRESS, &reg_type, &drp_address, &reg_len, 0);
1212   if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_address))
1213     {
1214       *dev = drp_address >> 16;
1215       *func = drp_address & 0xffff;
1216       have_devfunc = TRUE;
1217     }
1218
1219   /*
1220    * Device Instance Id for PCI devices is of format:
1221    *  "<enumerator>\\<device_id>\\<instance_id>"
1222    * where:
1223    *  "<enumerator>" is "PCI"
1224    *  "<device_id>" is "VEN_####&DEV_####&SUBSYS_########&REV_##"
1225    * and "<instance_id>" for PCI devices is at least in one of following format:
1226    *  "BUS_##&DEV_##&FUNC_##"
1227    *  "##.." (sequence of devfn hex bytes, where bytes represents tree path to the root)
1228    *  "#..&#..&#..&#.." (four hex numbers separated by "&"; meaning is unknown yet)
1229    *
1230    * First two formats are used only on systems without support for multiple
1231    * domains. The second format uses intel-conf encoding of device and function
1232    * number: Low 3 bits is function number and high 5 bits is device number.
1233    * Bus number is not really encoded in second format!
1234    *
1235    * The third format is used on systems with support for multiple domains but
1236    * format is variable length and currently its meaning is unknown. Apparently
1237    * it looks like that DRP_BUSNUMBER and DRP_ADDRESS registry properties are
1238    * supported on these systems.
1239    *
1240    * If DRP_BUSNUMBER or DRP_ADDRESS failed then try to parse PCI bus, device
1241    * and function numbers from Instance Id part.
1242    */
1243   if (!have_bus || !have_devfunc)
1244     {
1245       const char *device_id0 = strchr(devinst_id, '\\');
1246       const char *instance_id0 = device_id0 ? strchr(device_id0 + 1, '\\') : NULL;
1247       const char *instance_id = instance_id0 ? instance_id0 + 1 : NULL;
1248       unsigned int devfn;
1249
1250       if (instance_id)
1251         {
1252           if (fmt_validate(instance_id, strlen(instance_id), "BUS_##&DEV_##&FUNC_##") &&
1253               sscanf(instance_id, "BUS_%x&DEV_%x&FUNC_%x", bus, dev, func) == 3)
1254             {
1255               have_bus = TRUE;
1256               have_devfunc = TRUE;
1257             }
1258           else if (seq_xdigit_validate(instance_id, 2, 2) &&
1259                    sscanf(instance_id, "%2x", &devfn) == 1)
1260             {
1261               *dev = devfn >> 3;
1262               *func = devfn & 0x7;
1263               have_devfunc = TRUE;
1264             }
1265         }
1266     }
1267
1268   /*
1269    * Virtual IRQ holder devices do not have assigned any bus/dev/func number and
1270    * have "IRQHOLDER" in their Device Id part. So skip them.
1271    */
1272   if (!have_bus && !have_devfunc && strncmp(devinst_id, "PCI\\IRQHOLDER\\", 14) == 0)
1273     return FALSE;
1274
1275   /*
1276    * When some numbers cannot be retrieved via cfgmgr32 then set them to zeros
1277    * to have structure initialized. It makes sense to report via libpci also
1278    * such "incomplete" device as cfgmgr32 can provide additional information
1279    * like device/vendor ids or assigned resources.
1280    */
1281   if (!have_bus && !have_devfunc)
1282     {
1283       *bus = *dev = *func = 0;
1284       a->warning("Cannot retrieve bus, device and function numbers for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1285     }
1286   else if (!have_bus)
1287     {
1288       *bus = 0;
1289       a->warning("Cannot retrieve bus number for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1290     }
1291   else if (!have_devfunc)
1292     {
1293       *dev = *func = 0;
1294       a->warning("Cannot retrieve device and function numbers for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1295     }
1296
1297   return TRUE;
1298 }
1299
1300 static void
1301 fill_data_from_string(struct pci_dev *d, const char *str)
1302 {
1303   BOOL have_device_id;
1304   BOOL have_vendor_id;
1305   BOOL have_prog_if;
1306   BOOL have_rev_id;
1307   const char *endptr, *endptr2;
1308   unsigned int hex;
1309   int len;
1310
1311   have_device_id = have_vendor_id = (d->known_fields & PCI_FILL_IDENT);
1312   have_prog_if = have_rev_id = (d->known_fields & PCI_FILL_CLASS_EXT);
1313
1314   while (1)
1315     {
1316       endptr = strchr(str, '&');
1317       endptr2 = strchr(str, '\\');
1318       if (endptr2 && (!endptr || endptr > endptr2))
1319         endptr = endptr2;
1320       len = endptr ? endptr-str : (int)strlen(str);
1321
1322       if (!have_vendor_id &&
1323           fmt_validate(str, len, "VEN_####") &&
1324           sscanf(str, "VEN_%x", &hex) == 1)
1325         {
1326           d->vendor_id = hex;
1327           have_vendor_id = TRUE;
1328         }
1329       else if (!have_device_id &&
1330                fmt_validate(str, len, "DEV_####") &&
1331                sscanf(str, "DEV_%x", &hex) == 1)
1332         {
1333           d->device_id = hex;
1334           have_device_id = TRUE;
1335         }
1336       else if (!(d->known_fields & PCI_FILL_SUBSYS) &&
1337                fmt_validate(str, len, "SUBSYS_########") &&
1338                sscanf(str, "SUBSYS_%x", &hex) == 1)
1339         {
1340           d->subsys_vendor_id = hex & 0xffff;
1341           d->subsys_id = hex >> 16;
1342           d->known_fields |= PCI_FILL_SUBSYS;
1343         }
1344       else if (!have_rev_id &&
1345                fmt_validate(str, len, "REV_##") &&
1346                sscanf(str, "REV_%x", &hex) == 1)
1347         {
1348           d->rev_id = hex;
1349           have_rev_id = TRUE;
1350         }
1351       else if (!((d->known_fields & PCI_FILL_CLASS) && have_prog_if) &&
1352                (fmt_validate(str, len, "CC_####") || fmt_validate(str, len, "CC_######")) &&
1353                sscanf(str, "CC_%x", &hex) == 1)
1354         {
1355           if (len == 9)
1356             {
1357               if (!have_prog_if)
1358                 {
1359                   d->prog_if = hex & 0xff;
1360                   have_prog_if = TRUE;
1361                 }
1362               hex >>= 8;
1363             }
1364           if (!(d->known_fields & PCI_FILL_CLASS))
1365             {
1366               d->device_class = hex;
1367               d->known_fields |= PCI_FILL_CLASS;
1368             }
1369         }
1370
1371       if (!endptr || endptr == endptr2)
1372         break;
1373
1374       str = endptr + 1;
1375     }
1376
1377   if ((have_device_id || d->device_id) && (have_vendor_id || d->vendor_id))
1378     d->known_fields |= PCI_FILL_IDENT;
1379
1380   if ((have_prog_if || d->prog_if) && (have_rev_id || d->rev_id))
1381     d->known_fields |= PCI_FILL_CLASS_EXT;
1382 }
1383
1384 static void
1385 fill_data_from_devinst_id(struct pci_dev *d, DEVINSTID_A devinst_id)
1386 {
1387   const char *device_id;
1388
1389   device_id = strchr(devinst_id, '\\');
1390   if (!device_id)
1391     return;
1392   device_id++;
1393
1394   /*
1395    * Device Id part of Device Instance Id is in format:
1396    *  "VEN_####&DEV_####&SUBSYS_########&REV_##"
1397    */
1398   fill_data_from_string(d, device_id);
1399 }
1400
1401 static void
1402 fill_data_from_hardware_ids(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
1403 {
1404   ULONG reg_type, reg_size, reg_len;
1405   struct pci_access *a = d->access;
1406   char *hardware_ids = NULL;
1407   const char *str;
1408   CONFIGRET cr;
1409
1410   reg_size = 0;
1411   cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, &reg_type, NULL, &reg_size, 0);
1412   if (cr != CR_SUCCESS && cr != CR_BUFFER_SMALL)
1413     {
1414       a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1415       return;
1416     }
1417   else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1418     {
1419       a->warning("Cannot retrieve hardware ids for PCI device %s: Hardware ids are stored as unknown type 0x%lx.", devinst_id, reg_type);
1420       return;
1421     }
1422
1423 retry:
1424   /*
1425    * Returned size is on older Windows versions without nul-term char.
1426    * So explicitly increase size and fill nul-term byte.
1427    */
1428   reg_size++;
1429   hardware_ids = pci_malloc(a, reg_size);
1430   reg_len = reg_size;
1431   cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, &reg_type, hardware_ids, &reg_len, 0);
1432   hardware_ids[reg_size - 1] = 0;
1433   if (reg_len > reg_size)
1434     {
1435       pci_mfree(hardware_ids);
1436       reg_size = reg_len;
1437       goto retry;
1438     }
1439   else if (cr != CR_SUCCESS)
1440     {
1441       a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1442       pci_mfree(hardware_ids);
1443       return;
1444     }
1445   else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1446     {
1447       a->warning("Cannot retrieve hardware ids for PCI device %s: Hardware ids are stored as unknown type 0x%lx.", devinst_id, reg_type);
1448       pci_mfree(hardware_ids);
1449       return;
1450     }
1451
1452   /*
1453    * Hardware ids is nul-separated nul-term string list where each string has
1454    * one of the following format:
1455    *  "PCI\\VEN_####&DEV_####&SUBSYS_########&REV_##"
1456    *  "PCI\\VEN_####&DEV_####&SUBSYS_########"
1457    *  "PCI\\VEN_####&DEV_####&REV_##&CC_####"
1458    *  "PCI\\VEN_####&DEV_####&CC_######"
1459    *  "PCI\\VEN_####&DEV_####&CC_####"
1460    *  "PCI\\VEN_####&DEV_####&REV_##"
1461    *  "PCI\\VEN_####&DEV_####"
1462    */
1463   for (str = hardware_ids; *str != '\0'; str += strlen(str) + 1)
1464     {
1465       if (strncmp(str, "PCI\\", 4) != 0)
1466         continue;
1467       str += 4;
1468       fill_data_from_string(d, str);
1469     }
1470
1471   pci_mfree(hardware_ids);
1472 }
1473
1474 static void
1475 scan_devinst_id(struct pci_access *a, DEVINSTID_A devinst_id)
1476 {
1477   unsigned int domain, bus, dev, func;
1478   struct pci_dev *d;
1479   DEVINST devinst;
1480   CONFIGRET cr;
1481
1482   cr = CM_Locate_DevNodeA(&devinst, devinst_id, CM_LOCATE_DEVNODE_NORMAL);
1483   if (cr != CR_SUCCESS)
1484     {
1485       /* Do not show warning when device is not present (= does not match NORMAL flag). */
1486       if (cr != CR_NO_SUCH_DEVNODE)
1487         a->warning("Cannot retrieve handle for device %s: %s.", devinst_id, cr_strerror(cr));
1488       return;
1489     }
1490
1491   /* get_device_location() returns FALSE if devinst is not real PCI device. */
1492   if (!get_device_location(a, devinst, devinst_id, &domain, &bus, &dev, &func))
1493     return;
1494
1495   d = pci_get_dev(a, domain, bus, dev, func);
1496   pci_link_dev(a, d);
1497   if (!d->access->backend_data)
1498     d->no_config_access = 1;
1499   d->backend_data = (void *)devinst;
1500
1501   /* Parse device id part of devinst id and fill details into pci_dev. */
1502   if (!a->buscentric)
1503     fill_data_from_devinst_id(d, devinst_id);
1504
1505   /* Retrieve hardware ids of devinst, parse them and fill details into pci_dev. */
1506   if (!a->buscentric)
1507     fill_data_from_hardware_ids(d, devinst, devinst_id);
1508
1509   if (!a->buscentric)
1510     fill_resources(d, devinst, devinst_id);
1511
1512   /*
1513    * Set parent field to cfgmgr32 parent devinst handle and backend_data field to current
1514    * devinst handle. At later stage in win32_cfgmgr32_scan() when all pci_dev
1515    * devices are linked, change every devinst handle by pci_dev.
1516    */
1517   if (!a->buscentric)
1518     {
1519       DEVINST parent_devinst;
1520       if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS)
1521         {
1522           parent_devinst = 0;
1523           a->warning("Cannot retrieve parent handle for device %s: %s.", devinst_id, cr_strerror(cr));
1524         }
1525       d->parent = (void *)parent_devinst;
1526     }
1527 }
1528
1529 static void
1530 win32_cfgmgr32_scan(struct pci_access *a)
1531 {
1532   ULONG devinst_id_list_size;
1533   PCHAR devinst_id_list;
1534   DEVINSTID_A devinst_id;
1535   struct pci_dev *d;
1536   CONFIGRET cr;
1537
1538   if (!resolve_cfgmgr32_functions())
1539     {
1540       a->warning("Required cfgmgr32.dll functions are unavailable.");
1541       return;
1542     }
1543
1544   /*
1545    * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1546    * support this API but returns CR_SUCCESS without touching size argument.
1547    */
1548   devinst_id_list_size = 0;
1549   cr = CM_Get_Device_ID_List_SizeA(&devinst_id_list_size, "PCI", CM_GETIDLIST_FILTER_ENUMERATOR);
1550   if (cr != CR_SUCCESS)
1551     {
1552       a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1553       return;
1554     }
1555   else if (devinst_id_list_size <= 1)
1556     {
1557       a->warning("Cannot retrieve list of PCI devices: No device was found.");
1558       return;
1559     }
1560
1561   devinst_id_list = pci_malloc(a, devinst_id_list_size);
1562   cr = CM_Get_Device_ID_ListA("PCI", devinst_id_list, devinst_id_list_size, CM_GETIDLIST_FILTER_ENUMERATOR);
1563   if (cr != CR_SUCCESS)
1564     {
1565       a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1566       pci_mfree(devinst_id_list);
1567       return;
1568     }
1569
1570   /* Register pci_dev for each cfgmgr32 devinst handle. */
1571   for (devinst_id = devinst_id_list; *devinst_id; devinst_id += strlen(devinst_id) + 1)
1572     scan_devinst_id(a, devinst_id);
1573
1574   /* Fill all drivers. */
1575   if (!a->buscentric)
1576     fill_drivers(a);
1577
1578   /* Switch parent fields from cfgmgr32 devinst handle to pci_dev. */
1579   if (!a->buscentric)
1580     {
1581       struct pci_dev *d1, *d2;
1582       for (d1 = a->devices; d1; d1 = d1->next)
1583         {
1584           for (d2 = a->devices; d2; d2 = d2->next)
1585             if ((DEVINST)d1->parent == (DEVINST)d2->backend_data)
1586               break;
1587           d1->parent = d2;
1588           if (d1->parent)
1589             d1->known_fields |= PCI_FILL_PARENT;
1590         }
1591     }
1592
1593   /* devinst stored in ->backend_data is not needed anymore, clear it. */
1594   for (d = a->devices; d; d = d->next)
1595     d->backend_data = NULL;
1596
1597   pci_mfree(devinst_id_list);
1598 }
1599
1600 static void
1601 win32_cfgmgr32_config(struct pci_access *a)
1602 {
1603   pci_define_param(a, "win32.cfgmethod", "auto", "PCI config space access method");
1604 }
1605
1606 static int
1607 win32_cfgmgr32_detect(struct pci_access *a)
1608 {
1609   ULONG devinst_id_list_size;
1610   CONFIGRET cr;
1611
1612   if (!resolve_cfgmgr32_functions())
1613     {
1614       a->debug("Required cfgmgr32.dll functions are unavailable.");
1615       return 0;
1616     }
1617
1618   /*
1619    * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1620    * support this API but returns CR_SUCCESS without touching size argument.
1621    */
1622   devinst_id_list_size = 0;
1623   cr = CM_Get_Device_ID_List_SizeA(&devinst_id_list_size, "PCI", CM_GETIDLIST_FILTER_ENUMERATOR);
1624   if (cr != CR_SUCCESS)
1625     {
1626       a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): %s.", cr_strerror(cr));
1627       return 0;
1628     }
1629   else if (devinst_id_list_size <= 1)
1630     {
1631       a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): No device was found.");
1632       return 0;
1633     }
1634
1635   return 1;
1636 }
1637
1638 static void
1639 win32_cfgmgr32_fill_info(struct pci_dev *d, unsigned int flags)
1640 {
1641   /*
1642    * All available flags were filled by win32_cfgmgr32_scan().
1643    * Filling more flags is possible only from config space.
1644    */
1645   if (!d->access->backend_data)
1646     return;
1647
1648   pci_generic_fill_info(d, flags);
1649 }
1650
1651 static int
1652 win32_cfgmgr32_read(struct pci_dev *d, int pos, byte *buf, int len)
1653 {
1654   struct pci_access *a = d->access;
1655   struct pci_access *acfg = a->backend_data;
1656   struct pci_dev *dcfg = d->backend_data;
1657
1658   if (!acfg)
1659     return pci_emulated_read(d, pos, buf, len);
1660
1661   if (!dcfg)
1662     d->backend_data = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
1663
1664   return pci_read_block(dcfg, pos, buf, len);
1665 }
1666
1667 static int
1668 win32_cfgmgr32_write(struct pci_dev *d, int pos, byte *buf, int len)
1669 {
1670   struct pci_access *a = d->access;
1671   struct pci_access *acfg = a->backend_data;
1672   struct pci_dev *dcfg = d->backend_data;
1673
1674   if (!acfg)
1675     return 0;
1676
1677   if (!dcfg)
1678     d->backend_data = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
1679
1680   return pci_write_block(dcfg, pos, buf, len);
1681 }
1682
1683 static void
1684 win32_cfgmgr32_cleanup_dev(struct pci_dev *d)
1685 {
1686   struct pci_dev *dcfg = d->backend_data;
1687
1688   if (dcfg)
1689     pci_free_dev(dcfg);
1690 }
1691
1692 static void
1693 win32_cfgmgr32_init(struct pci_access *a)
1694 {
1695   char *cfgmethod = pci_get_param(a, "win32.cfgmethod");
1696   struct pci_access *acfg;
1697
1698   if (strcmp(cfgmethod, "") == 0 ||
1699       strcmp(cfgmethod, "auto") == 0)
1700     {
1701       acfg = pci_clone_access(a);
1702       acfg->method = PCI_ACCESS_AUTO;
1703     }
1704   else if (strcmp(cfgmethod, "none") == 0 ||
1705            strcmp(cfgmethod, "win32-cfgmgr32") == 0)
1706     {
1707       if (a->writeable)
1708         a->error("Write access requested but option win32.cfgmethod was not set.");
1709       return;
1710     }
1711   else
1712     {
1713       int m = pci_lookup_method(cfgmethod);
1714       if (m < 0)
1715         a->error("Option win32.cfgmethod is set to an unknown access method \"%s\".", cfgmethod);
1716       acfg = pci_clone_access(a);
1717       acfg->method = m;
1718     }
1719
1720   a->debug("Loading config space access method...\n");
1721   if (!pci_init_internal(acfg, PCI_ACCESS_WIN32_CFGMGR32))
1722     {
1723       pci_cleanup(acfg);
1724       a->debug("Cannot find any working config space access method.\n");
1725       if (a->writeable)
1726         a->error("Write access requested but no usable access method found.");
1727       return;
1728     }
1729
1730   a->backend_data = acfg;
1731 }
1732
1733 static void
1734 win32_cfgmgr32_cleanup(struct pci_access *a)
1735 {
1736   struct pci_access *acfg = a->backend_data;
1737
1738   if (acfg)
1739     pci_cleanup(acfg);
1740 }
1741
1742 struct pci_methods pm_win32_cfgmgr32 = {
1743   "win32-cfgmgr32",
1744   "Win32 device listing via Configuration Manager",
1745   win32_cfgmgr32_config,
1746   win32_cfgmgr32_detect,
1747   win32_cfgmgr32_init,
1748   win32_cfgmgr32_cleanup,
1749   win32_cfgmgr32_scan,
1750   win32_cfgmgr32_fill_info,
1751   win32_cfgmgr32_read,
1752   win32_cfgmgr32_write,
1753   NULL,                                 /* read_vpd */
1754   NULL,                                 /* init_dev */
1755   win32_cfgmgr32_cleanup_dev,
1756 };