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