]> mj.ucw.cz Git - pciutils.git/blob - lib/win32-cfgmgr32.c
61901d2451d89e8df6f5f3bddeaa45df82ba7410
[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   UINT systemroot_len;
407   int driver_path_len;
408   HMODULE kernel32;
409   DWORD error;
410
411   service = OpenServiceW(manager, service_name, SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS);
412   if (!service)
413     {
414       error = GetLastError();
415       if (error != ERROR_SERVICE_DOES_NOT_EXIST)
416         a->warning("Cannot open service %ls with query rights: %s.", service_name, win32_strerror(error));
417       goto out;
418     }
419
420   if (!QueryServiceStatus(service, &service_status))
421     {
422       error = GetLastError();
423       a->warning("Cannot query status of service %ls: %s.", service_name, win32_strerror(error));
424       goto out;
425     }
426
427   if (service_status.dwCurrentState == SERVICE_STOPPED)
428     goto out;
429
430   if (service_status.dwServiceType != SERVICE_KERNEL_DRIVER)
431     goto out;
432
433   if (!QueryServiceConfigW(service, NULL, 0, &service_config_size))
434     {
435       error = GetLastError();
436       if (error != ERROR_INSUFFICIENT_BUFFER)
437       {
438         a->warning("Cannot query config of service %ls: %s.", service_name, win32_strerror(error));
439         goto out;
440       }
441     }
442
443 retry_service_config:
444   service_config = pci_malloc(a, service_config_size);
445   if (!QueryServiceConfigW(service, service_config, service_config_size, &service_config_len))
446     {
447       error = GetLastError();
448       if (error == ERROR_INSUFFICIENT_BUFFER)
449         {
450           pci_mfree(service_config);
451           service_config_size = service_config_len;
452           goto retry_service_config;
453         }
454       a->warning("Cannot query config of service %ls: %s.", service_name, win32_strerror(error));
455       goto out;
456     }
457
458   if (service_config->dwServiceType != SERVICE_KERNEL_DRIVER)
459     goto out;
460
461   /*
462    * Despite QueryServiceConfig() is Win32 API, it returns lpBinaryPathName
463    * (ImagePath registry) in NT format. Unfortunately there is no Win32
464    * function for converting NT paths to Win32 paths. So do it manually and
465    * convert this NT format to human-readable Win32 path format.
466    */
467
468   /*
469    * Old Windows versions return path to NT SystemRoot namespace via
470    * GetWindowsDirectoryW() function. New Windows versions via
471    * GetSystemWindowsDirectoryW(). GetSystemWindowsDirectoryW() is not
472    * provided in old Windows versions, so use GetProcAddress() for
473    * compatibility with all Windows versions.
474    */
475   kernel32 = GetModuleHandleW(L"kernel32.dll");
476   if (kernel32)
477     get_system_root_path = (void *)GetProcAddress(kernel32, "GetSystemWindowsDirectoryW");
478   if (!get_system_root_path)
479     get_system_root_path = &GetWindowsDirectoryW;
480
481   systemroot_len = get_system_root_path(NULL, 0);
482
483   if (!service_config->lpBinaryPathName || !service_config->lpBinaryPathName[0])
484     {
485       /* No ImagePath is specified, NT kernel assumes implicit kernel driver path by service name. */
486       service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + sizeof("\\System32\\drivers\\")-1 + wcslen(service_name) + sizeof(".sys")-1 + 1));
487       systemroot_len = get_system_root_path(service_image_path, systemroot_len+1);
488       if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
489         service_image_path[systemroot_len++] = L'\\';
490       wcscpy(service_image_path + systemroot_len, L"System32\\drivers\\");
491       wcscpy(service_image_path + systemroot_len + sizeof("System32\\drivers\\")-1, service_name);
492       wcscpy(service_image_path + systemroot_len + sizeof("System32\\drivers\\")-1 + wcslen(service_name), L".sys");
493     }
494   else if (wcsncmp(service_config->lpBinaryPathName, L"\\SystemRoot\\", sizeof("\\SystemRoot\\")-1) == 0)
495     {
496       /* ImagePath is in NT SystemRoot namespace, convert to Win32 path via GetSystemWindowsDirectoryW()/GetWindowsDirectoryW(). */
497       service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + wcslen(service_config->lpBinaryPathName) - (sizeof("\\SystemRoot")-1)));
498       systemroot_len = get_system_root_path(service_image_path, systemroot_len+1);
499       if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
500         service_image_path[systemroot_len++] = L'\\';
501       wcscpy(service_image_path + systemroot_len, service_config->lpBinaryPathName + sizeof("\\SystemRoot\\")-1);
502     }
503   else if (wcsncmp(service_config->lpBinaryPathName, L"\\??\\UNC\\", sizeof("\\??\\UNC\\")-1) == 0 ||
504            wcsncmp(service_config->lpBinaryPathName, L"\\??\\\\UNC\\", sizeof("\\??\\\\UNC\\")-1) == 0)
505     {
506       /* ImagePath is in NT UNC namespace, convert to Win32 UNC path via "\\\\" prefix. */
507       service_image_path = pci_malloc(a, sizeof(WCHAR) * (sizeof("\\\\") + wcslen(service_config->lpBinaryPathName) - (sizeof("\\??\\UNC\\")-1)));
508       /* Namespace separator may be single or double backslash. */
509       driver_path_len = sizeof("\\??\\")-1;
510       if (service_config->lpBinaryPathName[driver_path_len] == L'\\')
511         driver_path_len++;
512       driver_path_len += sizeof("UNC\\")-1;
513       wcscpy(service_image_path, L"\\\\");
514       wcscpy(service_image_path + sizeof("\\\\")-1, service_config->lpBinaryPathName + driver_path_len);
515     }
516   else if (wcsncmp(service_config->lpBinaryPathName, L"\\??\\", sizeof("\\??\\")-1) == 0)
517     {
518       /* ImagePath is in NT Global?? namespace, root of the Win32 file namespace, so just remove "\\??\\" prefix to get Win32 path. */
519       service_image_path = pci_malloc(a, sizeof(WCHAR) * (wcslen(service_config->lpBinaryPathName) - (sizeof("\\??\\")-1)));
520       /* Namespace separator may be single or double backslash. */
521       driver_path_len = sizeof("\\??\\")-1;
522       if (service_config->lpBinaryPathName[driver_path_len] == L'\\')
523         driver_path_len++;
524       wcscpy(service_image_path, service_config->lpBinaryPathName + driver_path_len);
525     }
526   else if (service_config->lpBinaryPathName[0] != L'\\')
527     {
528       /* ImagePath is relative to the NT SystemRoot namespace, convert to Win32 path via GetSystemWindowsDirectoryW()/GetWindowsDirectoryW(). */
529       service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + sizeof("\\") + wcslen(service_config->lpBinaryPathName)));
530       systemroot_len = get_system_root_path(service_image_path, systemroot_len+1);
531       if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
532         service_image_path[systemroot_len++] = L'\\';
533       wcscpy(service_image_path + systemroot_len, service_config->lpBinaryPathName);
534     }
535   else
536     {
537       /* 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. */
538       service_image_path = pci_malloc(a, sizeof(WCHAR) * wcslen(service_config->lpBinaryPathName));
539       wcscpy(service_image_path, service_config->lpBinaryPathName);
540     }
541
542   /* Calculate len of buffer needed for conversion from LPWSTR to char*. */
543   driver_path_len = WideCharToMultiByte(CP_ACP, 0, service_image_path, -1, NULL, 0, NULL, NULL);
544   if (driver_path_len <= 0)
545     {
546       error = GetLastError();
547       a->warning("Cannot convert kernel driver path from wide string to 8-bit string: %s.", win32_strerror(error));
548       goto out;
549     }
550
551   driver_path = pci_malloc(a, driver_path_len);
552   driver_path_len = WideCharToMultiByte(CP_ACP, 0, service_image_path, -1, driver_path, driver_path_len, NULL, NULL);
553   if (driver_path_len <= 0)
554     {
555       error = GetLastError();
556       a->warning("Cannot convert kernel driver path from wide string to 8-bit string: %s.", win32_strerror(error));
557       pci_mfree(driver_path);
558       driver_path = NULL;
559       goto out;
560     }
561
562 out:
563   if (service_image_path)
564     pci_mfree(service_image_path);
565   if (service_config)
566     pci_mfree(service_config);
567   if (service)
568     CloseServiceHandle(service);
569   return driver_path;
570 }
571
572 static HKEY
573 get_device_driver_devreg(struct pci_access *a, DEVINST devinst, DEVINSTID_A devinst_id)
574 {
575   CONFIGRET cr;
576   HKEY key;
577
578   cr = CM_Open_DevNode_Key(devinst, KEY_READ, 0, RegDisposition_OpenExisting, &key, CM_REGISTRY_SOFTWARE);
579   if (cr != CR_SUCCESS)
580     {
581       if (cr != CR_NO_SUCH_VALUE)
582         a->warning("Cannot retrieve driver key for device %s: %s.", devinst_id, cr_strerror(cr));
583       return NULL;
584     }
585
586   return key;
587 }
588
589 static char*
590 read_reg_key_string_value(struct pci_access *a, HKEY key, const char *name, DWORD *unkn_reg_type)
591 {
592   DWORD reg_type, reg_size, reg_len;
593   char *value;
594   LONG error;
595
596   reg_size = 0;
597   error = RegQueryValueExA(key, name, NULL, &reg_type, NULL, &reg_size);
598   if (error != ERROR_SUCCESS &&
599       error != ERROR_MORE_DATA)
600     {
601       SetLastError(error);
602       return NULL;
603     }
604   else if (reg_type != REG_SZ)
605     {
606       SetLastError(0);
607       *unkn_reg_type = reg_type;
608       return NULL;
609     }
610
611 retry:
612   value = pci_malloc(a, reg_size + 1);
613   reg_len = reg_size;
614   error = RegQueryValueExA(key, name, NULL, &reg_type, (PBYTE)value, &reg_len);
615   if (error != ERROR_SUCCESS)
616     {
617       pci_mfree(value);
618       if (error == ERROR_MORE_DATA)
619         {
620           reg_size = reg_len;
621           goto retry;
622         }
623       SetLastError(error);
624       return NULL;
625     }
626   else if (reg_type != REG_SZ)
627     {
628       pci_mfree(value);
629       SetLastError(0);
630       *unkn_reg_type = reg_type;
631       return NULL;
632     }
633   value[reg_len] = '\0';
634
635   return value;
636 }
637
638 static int
639 driver_cmp(const char *driver, const char *match)
640 {
641   int len = strlen(driver);
642   if (driver[0] == '*')
643     driver++;
644   if (len >= 4 && strcasecmp(driver + len - 4, ".vxd") == 0)
645     len -= 4;
646   return strncasecmp(driver, match, len);
647 }
648
649 static char*
650 get_driver_path_for_regkey(struct pci_access *a, DEVINSTID_A devinst_id, HKEY key)
651 {
652   char *driver_list, *driver, *driver_next;
653   char *subdriver, *subname;
654   char *driver_ptr;
655   char *driver_path;
656   DWORD unkn_reg_type;
657   UINT systemdir_len;
658   HKEY subkey;
659   LONG error;
660   BOOL vmm32;
661   BOOL noext;
662   int len;
663
664   driver_list = read_reg_key_string_value(a, key, "DevLoader", &unkn_reg_type);
665   if (!driver_list)
666     {
667       error = GetLastError();
668       if (error == 0)
669         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);
670       else if (error != ERROR_FILE_NOT_FOUND)
671         a->warning("Cannot read driver DevLoader key for PCI device %s: %s.", devinst_id, win32_strerror(error));
672       return NULL;
673     }
674
675   subdriver = NULL;
676   driver = driver_list;
677   while (*driver)
678     {
679       driver_next = strchr(driver, ',');
680       if (driver_next)
681           *(driver_next++) = '\0';
682
683       if (driver_cmp(driver, "ios") == 0 ||
684           driver_cmp(driver, "vcomm") == 0)
685         subname = "PortDriver";
686       else if (driver_cmp(driver, "ntkern") == 0)
687         subname = "NTMPDriver";
688       else if (driver_cmp(driver, "ndis") == 0)
689         subname = "DeviceVxDs";
690       else if (driver_cmp(driver, "vdd") == 0)
691         subname = "minivdd";
692       else
693         subname = NULL;
694
695       subkey = key;
696       if (subname && strcmp(subname, "minivdd") == 0)
697         {
698           error = RegOpenKeyA(key, "Default", &subkey);
699           if (error != ERROR_SUCCESS)
700             {
701               a->warning("Cannot open driver subkey Default for PCI device %s: %s.", devinst_id, win32_strerror(error));
702               subkey = NULL;
703             }
704         }
705
706       if (!subname)
707         break;
708
709       if (subkey)
710         {
711 retry_subname:
712           subdriver = read_reg_key_string_value(a, subkey, subname, &unkn_reg_type);
713           if (!subdriver)
714             {
715               error = GetLastError();
716               if (error == 0)
717                 a->warning("Cannot read driver %s key for PCI device %s: DevLoader key is stored as unknown type 0x%lx.", subname, devinst_id, unkn_reg_type);
718               else if (error != ERROR_FILE_NOT_FOUND)
719                 a->warning("Cannot read driver %s key for PCI device %s: %s.", subname, devinst_id, win32_strerror(error));
720               else if (strcmp(subname, "minivdd") == 0)
721                 {
722                   subname = "drv";
723                   goto retry_subname;
724                 }
725               else if (strcmp(subname, "drv") == 0)
726                 {
727                   subname = "vdd";
728                   goto retry_subname;
729                 }
730             }
731
732           if (subkey != key)
733             RegCloseKey(subkey);
734
735           if (subdriver)
736             {
737               char *endptr = strchr(subdriver, ',');
738               if (endptr)
739                 *endptr = '\0';
740               break;
741             }
742         }
743
744       driver = driver_next;
745     }
746
747   if (subdriver && subdriver[0])
748     driver_ptr = subdriver;
749   else if (driver[0])
750     driver_ptr = driver;
751   else
752     driver_ptr = NULL;
753
754   if (driver_ptr && driver_ptr[0] == '*')
755     {
756       vmm32 = TRUE;
757       driver_ptr++;
758     }
759   else
760     vmm32 = FALSE;
761
762   if (!driver_ptr[0])
763     driver_ptr = NULL;
764
765   len = driver_ptr ? strlen(driver_ptr) : 0;
766   noext = driver_ptr && (len < 4 || driver_ptr[len-4] != '.');
767
768   if (!driver_ptr)
769     driver_path = NULL;
770   else
771     {
772       if (tolower(driver_ptr[0]) >= 'a' && tolower(driver_ptr[0]) <= 'z' && driver_ptr[1] == ':')
773         {
774           /* Driver is already with absolute path. */
775           driver_path = pci_strdup(a, driver_ptr);
776         }
777       else if (driver_cmp(driver, "ntkern") == 0 && subdriver)
778         {
779           /* Driver is relative to system32\drivers\ directory which is relative to windows directory. */
780           systemdir_len = GetWindowsDirectoryA(NULL, 0);
781           driver_path = pci_malloc(a, systemdir_len + 1 + sizeof("system32\\drivers\\")-1 + strlen(driver_ptr) + 4 + 1);
782           systemdir_len = GetWindowsDirectoryA(driver_path, systemdir_len + 1);
783           if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
784             driver_path[systemdir_len++] = '\\';
785           sprintf(driver_path + systemdir_len, "system32\\drivers\\%s%s", driver_ptr, noext ? ".sys" : "");
786         }
787       else if (vmm32)
788         {
789           /* Driver is packed in vmm32.vxd which is stored in system directory. */
790           systemdir_len = GetSystemDirectoryA(NULL, 0);
791           driver_path = pci_malloc(a, systemdir_len + 1 + sizeof("vmm32.vxd ()")-1 + strlen(driver_ptr) + 4 + 1);
792           systemdir_len = GetSystemDirectoryA(driver_path, systemdir_len + 1);
793           if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
794             driver_path[systemdir_len++] = '\\';
795           sprintf(driver_path + systemdir_len, "vmm32.vxd (%s%s)", driver_ptr, noext ? ".vxd" : "");
796         }
797       else
798         {
799           /* Otherwise driver is relative to system directory. */
800           systemdir_len = GetSystemDirectoryA(NULL, 0);
801           driver_path = pci_malloc(a, systemdir_len + 1 + strlen(driver_ptr) + 4 + 1);
802           systemdir_len = GetSystemDirectoryA(driver_path, systemdir_len + 1);
803           if (systemdir_len && driver_path[systemdir_len - 1] != '\\')
804             driver_path[systemdir_len++] = '\\';
805           sprintf(driver_path + systemdir_len, "%s%s", driver_ptr, noext ? ".vxd" : "");
806         }
807     }
808
809   if (subdriver)
810     pci_mfree(subdriver);
811   pci_mfree(driver_list);
812   return driver_path;
813 }
814
815 static char *
816 get_device_driver_path(struct pci_dev *d, SC_HANDLE manager, BOOL manager_supported)
817 {
818   struct pci_access *a = d->access;
819   BOOL service_supported = TRUE;
820   DEVINSTID_A devinst_id = NULL;
821   LPWSTR service_name = NULL;
822   ULONG devinst_id_len = 0;
823   char *driver_path = NULL;
824   DEVINST devinst = (DEVINST)d->aux;
825   ULONG problem = 0;
826   ULONG status = 0;
827   HKEY key = NULL;
828
829   if (CM_Get_DevNode_Status(&status, &problem, devinst, 0) != CR_SUCCESS || !(status & DN_DRIVER_LOADED))
830     return NULL;
831
832   if (CM_Get_Device_ID_Size(&devinst_id_len, devinst, 0) == CR_SUCCESS)
833     {
834       devinst_id = pci_malloc(a, devinst_id_len + 1);
835       if (CM_Get_Device_IDA(devinst, devinst_id, devinst_id_len + 1, 0) != CR_SUCCESS)
836         {
837           pci_mfree(devinst_id);
838           devinst_id = pci_strdup(a, "UNKNOWN");
839         }
840     }
841   else
842     devinst_id = pci_strdup(a, "UNKNOWN");
843
844   service_name = get_device_service_name(d->access, devinst, devinst_id, &service_supported);
845   if ((!service_name || !manager) && service_supported && manager_supported)
846     goto out;
847   else if (service_name && manager)
848     {
849       driver_path = get_driver_path_for_service(d->access, service_name, manager);
850       goto out;
851     }
852
853   key = get_device_driver_devreg(d->access, devinst, devinst_id);
854   if (key)
855     {
856       driver_path = get_driver_path_for_regkey(d->access, devinst_id, key);
857       goto out;
858     }
859
860 out:
861   if (key)
862     RegCloseKey(key);
863   if (service_name)
864     pci_mfree(service_name);
865   pci_mfree(devinst_id);
866   return driver_path;
867 }
868
869 static void
870 fill_drivers(struct pci_access *a)
871 {
872   BOOL manager_supported;
873   SC_HANDLE manager;
874   struct pci_dev *d;
875   char *driver;
876   DWORD error;
877
878   /* ERROR_CALL_NOT_IMPLEMENTED is returned on systems without Service Manager support. */
879   manager_supported = TRUE;
880   manager = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
881   if (!manager)
882     {
883       error = GetLastError();
884       if (error != ERROR_CALL_NOT_IMPLEMENTED)
885         a->warning("Cannot open Service Manager with connect right: %s.", win32_strerror(error));
886       else
887         manager_supported = FALSE;
888     }
889
890   for (d = a->devices; d; d = d->next)
891     {
892       driver = get_device_driver_path(d, manager, manager_supported);
893       if (driver)
894         {
895           pci_set_property(d, PCI_FILL_DRIVER, driver);
896           pci_mfree(driver);
897         }
898       d->known_fields |= PCI_FILL_DRIVER;
899     }
900
901   if (manager)
902     CloseServiceHandle(manager);
903 }
904
905 static const char *
906 res_id_to_str(RESOURCEID res_id)
907 {
908   static char hex_res_id[sizeof("0xffffffff")];
909
910   if (res_id == ResType_IO)
911     return "IO";
912   else if (res_id == ResType_Mem)
913     return "MEM";
914   else if (res_id == ResType_IRQ)
915     return "IRQ";
916
917   sprintf(hex_res_id, "0x%lx", res_id);
918   return hex_res_id;
919 }
920
921 static void
922 fill_resources(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
923 {
924   struct pci_access *a = d->access;
925
926   CONFIGRET cr;
927
928   LOG_CONF config;
929   ULONG problem;
930   ULONG status;
931
932   RES_DES prev_res_des;
933   RES_DES res_des;
934   RESOURCEID res_id;
935   DWORD bar_res_count;
936
937   BOOL is_bar_res;
938   BOOL non_nt_system;
939
940   int last_irq = -1;
941   int last_shared_irq = -1;
942
943   cr = CM_Get_DevNode_Status(&status, &problem, devinst, 0);
944   if (cr != CR_SUCCESS)
945     {
946       a->warning("Cannot retrieve status of PCI device %s: %s.", devinst_id, cr_strerror(cr));
947       return;
948     }
949
950   cr = CR_NO_MORE_LOG_CONF;
951
952   /*
953    * If the device is running then retrieve allocated configuration by PnP
954    * manager which is currently in use by a device.
955    */
956   if (!(status & DN_HAS_PROBLEM))
957     cr = CM_Get_First_Log_Conf(&config, devinst, ALLOC_LOG_CONF);
958
959   /*
960    * If the device is not running or it does not have allocated configuration by
961    * PnP manager then retrieve forced configuration which prevents PnP manager
962    * from assigning resources.
963    */
964   if (cr == CR_NO_MORE_LOG_CONF)
965     cr = CM_Get_First_Log_Conf(&config, devinst, FORCED_LOG_CONF);
966
967   /*
968    * If the device does not have neither allocated configuration by PnP manager
969    * nor forced configuration and it is not disabled in the BIOS then retrieve
970    * boot configuration supplied by the BIOS.
971    */
972   if (cr == CR_NO_MORE_LOG_CONF &&
973       (!(status & DN_HAS_PROBLEM) || problem != CM_PROB_HARDWARE_DISABLED))
974     cr = CM_Get_First_Log_Conf(&config, devinst, BOOT_LOG_CONF);
975
976   if (cr != CR_SUCCESS)
977     {
978       /*
979        * Note: Starting with Windows 8, CM_Get_First_Log_Conf returns
980        * CR_CALL_NOT_IMPLEMENTED when used in a Wow64 scenario.
981        * To request information about the hardware resources on a local machine
982        * it is necessary implement an architecture-native version of the
983        * application using the hardware resource APIs. For example: An AMD64
984        * application for AMD64 systems.
985        */
986       if (cr == CR_CALL_NOT_IMPLEMENTED && is_32bit_on_win8_64bit_system())
987         {
988           static BOOL warn_once = FALSE;
989           if (!warn_once)
990             {
991               warn_once = TRUE;
992               a->warning("Cannot retrieve resources of PCI devices from 32-bit application on 64-bit system.");
993             }
994         }
995       else if (cr != CR_NO_MORE_LOG_CONF)
996         a->warning("Cannot retrieve resources of PCI device %s: %s.", devinst_id, cr_strerror(cr));
997       return;
998     }
999
1000   bar_res_count = 0;
1001   non_nt_system = is_non_nt_system();
1002
1003   is_bar_res = TRUE;
1004   if (non_nt_system)
1005     {
1006       BOOL has_child;
1007       DEVINST child;
1008       ULONG child_name_len;
1009       PSTR child_name;
1010       BOOL is_bridge;
1011
1012       if (CM_Get_Child(&child, devinst, 0) != CR_SUCCESS)
1013         has_child = FALSE;
1014       else if (CM_Get_Device_ID_Size(&child_name_len, child, 0) != CR_SUCCESS)
1015         has_child = FALSE;
1016       else
1017         {
1018           child_name_len++;
1019           child_name = pci_malloc(a, child_name_len);
1020           if (CM_Get_Device_IDA(child, child_name, child_name_len, 0) != CR_SUCCESS)
1021             has_child = FALSE;
1022           else if (strncmp(child_name, "PCI\\", 4) != 0)
1023             has_child = FALSE;
1024           else
1025             has_child = TRUE;
1026           pci_mfree(child_name);
1027         }
1028
1029       if (has_child || d->device_class == PCI_CLASS_BRIDGE_PCI || d->device_class == PCI_CLASS_BRIDGE_CARDBUS)
1030         is_bridge = TRUE;
1031       else
1032         is_bridge = FALSE;
1033
1034       if (is_bridge)
1035         is_bar_res = FALSE;
1036     }
1037
1038   prev_res_des = (RES_DES)config;
1039   while ((cr = CM_Get_Next_Res_Des(&res_des, prev_res_des, ResType_All, &res_id, 0)) == CR_SUCCESS)
1040     {
1041       pciaddr_t start, end, size, flags;
1042       ULONG res_des_data_size;
1043       PBYTE res_des_data;
1044
1045       if (prev_res_des != config)
1046         CM_Free_Res_Des_Handle(prev_res_des);
1047
1048       prev_res_des = res_des;
1049
1050       /* Skip other resources early */
1051       if (res_id != ResType_IO && res_id != ResType_Mem && res_id != ResType_IRQ)
1052         continue;
1053
1054       cr = CM_Get_Res_Des_Data_Size(&res_des_data_size, res_des, 0);
1055       if (cr != CR_SUCCESS)
1056         {
1057           a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, cr_strerror(cr));
1058           continue;
1059         }
1060
1061       if (!res_des_data_size)
1062         {
1063           a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, "Empty data");
1064           continue;
1065         }
1066
1067       res_des_data = pci_malloc(a, res_des_data_size);
1068       cr = CM_Get_Res_Des_Data(res_des, res_des_data, res_des_data_size, 0);
1069       if (cr != CR_SUCCESS)
1070         {
1071           a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, cr_strerror(cr));
1072           pci_mfree(res_des_data);
1073           continue;
1074         }
1075
1076       /*
1077        * There can be more resources with the same id. In this case we are
1078        * interested in the last one in the list as at the beginning of the list
1079        * can be some virtual resources (which are not set in PCI config space).
1080        */
1081
1082       if (res_id == ResType_IO)
1083         {
1084           PIO_RESOURCE io_data = (PIO_RESOURCE)res_des_data;
1085
1086           start = io_data->IO_Header.IOD_Alloc_Base;
1087           end = io_data->IO_Header.IOD_Alloc_End;
1088           size = (end > start) ? (end - start + 1) : 0;
1089           flags = PCI_IORESOURCE_IO;
1090
1091           /*
1092            * If neither 10-bit, 12-bit, nor 16-bit support is presented then
1093            * expects that this is 32-bit I/O resource. If resource does not fit
1094            * into 16-bit space then it must be 32-bit. If PCI I/O resource is
1095            * not 32-bit then it is 16-bit.
1096            */
1097           if (end <= 0xffff && (io_data->IO_Header.IOD_DesFlags & (fIOD_10_BIT_DECODE|fIOD_12_BIT_DECODE|fIOD_16_BIT_DECODE)))
1098             flags |= PCI_IORESOURCE_IO_16BIT_ADDR;
1099
1100           /*
1101            * 16/32-bit non-NT systems do not support these two flags.
1102            * Most NT-based Windows versions support only the fIOD_WINDOW_DECODE
1103            * flag and put all BAR resources before window resources in this
1104            * resource list. So use this fIOD_WINDOW_DECODE flag as separator
1105            * between IO/MEM windows and IO/MEM BARs of PCI Bridges.
1106            */
1107           if (io_data->IO_Header.IOD_DesFlags & fIOD_WINDOW_DECODE)
1108             is_bar_res = FALSE;
1109           else if (io_data->IO_Header.IOD_DesFlags & fIOD_PORT_BAR)
1110             is_bar_res = TRUE;
1111
1112           if (is_bar_res && bar_res_count < 6)
1113             {
1114               d->flags[bar_res_count] = flags;
1115               d->base_addr[bar_res_count] = start;
1116               d->size[bar_res_count] = size;
1117               bar_res_count++;
1118             }
1119           else if (!is_bar_res)
1120             {
1121               d->bridge_flags[0] = flags;
1122               d->bridge_base_addr[0] = start;
1123               d->bridge_size[0] = size;
1124               d->known_fields |= PCI_FILL_BRIDGE_BASES;
1125             }
1126         }
1127       else if (res_id == ResType_Mem)
1128         {
1129           PMEM_RESOURCE mem_data = (PMEM_RESOURCE)res_des_data;
1130
1131           start = mem_data->MEM_Header.MD_Alloc_Base;
1132           end = mem_data->MEM_Header.MD_Alloc_End;
1133           size = (end > start) ? (end - start + 1) : 0;
1134           flags = PCI_IORESOURCE_MEM;
1135
1136           /*
1137            * If fMD_PrefetchAllowed flag is set then this is
1138            * PCI Prefetchable Memory resource.
1139            */
1140           if ((mem_data->MEM_Header.MD_Flags & mMD_Prefetchable) == fMD_PrefetchAllowed)
1141             flags |= PCI_IORESOURCE_PREFETCH;
1142
1143           /* If resource does not fit into 32-bit space then it must be 64-bit. */
1144           if (is_bar_res && end > 0xffffffff)
1145             flags |= PCI_IORESOURCE_MEM_64;
1146
1147           /*
1148            * These two flags (fMD_WINDOW_DECODE and fMD_MEMORY_BAR) are
1149            * unsupported on most Windows versions, so distinguish between
1150            * window and BAR based on previous resource type.
1151            */
1152           if (mem_data->MEM_Header.MD_Flags & fMD_WINDOW_DECODE)
1153             is_bar_res = FALSE;
1154           else if (mem_data->MEM_Header.MD_Flags & fMD_MEMORY_BAR)
1155             is_bar_res = TRUE;
1156
1157           /* 64-bit BAR resource must be at even position. */
1158           if (is_bar_res && (flags & PCI_IORESOURCE_MEM_64) && bar_res_count % 2)
1159             bar_res_count++;
1160
1161           if (is_bar_res && bar_res_count < 6)
1162             {
1163               d->flags[bar_res_count] = flags;
1164               d->base_addr[bar_res_count] = start;
1165               d->size[bar_res_count] = size;
1166               bar_res_count++;
1167               /* 64-bit BAR resource occupies two slots. */
1168               if (flags & PCI_IORESOURCE_MEM_64)
1169                 bar_res_count++;
1170             }
1171           else if (!is_bar_res && !(flags & PCI_IORESOURCE_PREFETCH))
1172             {
1173               d->bridge_flags[1] = flags;
1174               d->bridge_base_addr[1] = start;
1175               d->bridge_size[1] = size;
1176               d->known_fields |= PCI_FILL_BRIDGE_BASES;
1177             }
1178           else if (!is_bar_res && (flags & PCI_IORESOURCE_PREFETCH))
1179             {
1180               d->bridge_flags[2] = flags;
1181               d->bridge_base_addr[2] = start;
1182               d->bridge_size[2] = size;
1183               d->known_fields |= PCI_FILL_BRIDGE_BASES;
1184             }
1185         }
1186       else if (res_id == ResType_IRQ)
1187         {
1188           PIRQ_RESOURCE irq_data = (PIRQ_RESOURCE)res_des_data;
1189
1190           /*
1191            * libpci's d->irq should be set to the non-MSI PCI IRQ and therefore
1192            * it should be level IRQ which may be shared with other PCI devices
1193            * and drivers in the system. As always we want to retrieve the last
1194            * IRQ number from the resource list.
1195            *
1196            * On 16/32-bit non-NT systems is fIRQD_Level set to 2 but on NT
1197            * systems to 0. Moreover it looks like that different PCI drivers
1198            * on both NT and non-NT systems set bits 0 and 1 to wrong values
1199            * and so reported value in this list may be incorrect.
1200            *
1201            * Therefore take the last level-shared IRQ number from the resource
1202            * list and if there is none of this type then take the last IRQ
1203            * number from the list.
1204            */
1205           last_irq = irq_data->IRQ_Header.IRQD_Alloc_Num;
1206           if ((irq_data->IRQ_Header.IRQD_Flags & (mIRQD_Share|mIRQD_Edge_Level)) == (fIRQD_Share|fIRQD_Level))
1207             last_shared_irq = irq_data->IRQ_Header.IRQD_Alloc_Num;
1208
1209           /*
1210            * IRQ resource on 16/32-bit non-NT systems is separator between
1211            * IO/MEM windows and IO/MEM BARs of PCI Bridges. After the IRQ
1212            * resource are IO/MEM BAR resources.
1213            */
1214           if (!is_bar_res && non_nt_system)
1215             is_bar_res = TRUE;
1216         }
1217
1218       pci_mfree(res_des_data);
1219     }
1220   if (cr != CR_NO_MORE_RES_DES)
1221     a->warning("Cannot retrieve resources of PCI device %s: %s.", devinst_id, cr_strerror(cr));
1222
1223   if (prev_res_des != config)
1224     CM_Free_Res_Des_Handle(prev_res_des);
1225
1226   CM_Free_Log_Conf_Handle(config);
1227
1228   /* Set the last IRQ from the resource list to pci_dev. */
1229   if (last_shared_irq >= 0)
1230     d->irq = last_shared_irq;
1231   else if (last_irq >= 0)
1232     d->irq = last_irq;
1233   if (last_shared_irq >= 0 || last_irq >= 0)
1234     d->known_fields |= PCI_FILL_IRQ;
1235
1236   if (bar_res_count > 0)
1237     d->known_fields |= PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS;
1238 }
1239
1240 static BOOL
1241 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)
1242 {
1243   ULONG reg_type, reg_len;
1244   CONFIGRET cr;
1245   BOOL have_bus, have_devfunc;
1246   DWORD drp_bus_num, drp_address;
1247
1248   *domain = 0;
1249   have_bus = FALSE;
1250   have_devfunc = FALSE;
1251
1252   /*
1253    * DRP_BUSNUMBER consists of PCI domain number in high 24 bits
1254    * and PCI bus number in low 8 bits.
1255    */
1256   reg_len = sizeof(drp_bus_num);
1257   cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_BUSNUMBER, &reg_type, &drp_bus_num, &reg_len, 0);
1258   if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_bus_num))
1259     {
1260       *domain = drp_bus_num >> 8;
1261       *bus = drp_bus_num & 0xff;
1262       have_bus = TRUE;
1263     }
1264
1265   /*
1266    * DRP_ADDRESS consists of PCI device number in high 16 bits
1267    * and PCI function number in low 16 bits.
1268    */
1269   reg_len = sizeof(drp_address);
1270   cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_ADDRESS, &reg_type, &drp_address, &reg_len, 0);
1271   if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_address))
1272     {
1273       *dev = drp_address >> 16;
1274       *func = drp_address & 0xffff;
1275       have_devfunc = TRUE;
1276     }
1277
1278   /*
1279    * Device Instance Id for PCI devices is of format:
1280    *  "<enumerator>\\<device_id>\\<instance_id>"
1281    * where:
1282    *  "<enumerator>" is "PCI"
1283    *  "<device_id>" is "VEN_####&DEV_####&SUBSYS_########&REV_##"
1284    * and "<instance_id>" for PCI devices is at least in one of following format:
1285    *  "BUS_##&DEV_##&FUNC_##"
1286    *  "##.." (sequence of devfn hex bytes, where bytes represents tree path to the root)
1287    *  "#..&#..&#..&#.." (four hex numbers separated by "&"; meaning is unknown yet)
1288    *
1289    * First two formats are used only on systems without support for multiple
1290    * domains. The second format uses intel-conf encoding of device and function
1291    * number: Low 3 bits is function number and high 5 bits is device number.
1292    * Bus number is not really encoded in second format!
1293    *
1294    * The third format is used on systems with support for multiple domains but
1295    * format is variable length and currently its meaning is unknown. Apparently
1296    * it looks like that DRP_BUSNUMBER and DRP_ADDRESS registry properties are
1297    * supported on these systems.
1298    *
1299    * If DRP_BUSNUMBER or DRP_ADDRESS failed then try to parse PCI bus, device
1300    * and function numbers from Instance Id part.
1301    */
1302   if (!have_bus || !have_devfunc)
1303     {
1304       const char *device_id0 = strchr(devinst_id, '\\');
1305       const char *instance_id0 = device_id0 ? strchr(device_id0 + 1, '\\') : NULL;
1306       const char *instance_id = instance_id0 ? instance_id0 + 1 : NULL;
1307       unsigned int devfn;
1308
1309       if (instance_id)
1310         {
1311           if (fmt_validate(instance_id, strlen(instance_id), "BUS_##&DEV_##&FUNC_##") &&
1312               sscanf(instance_id, "BUS_%x&DEV_%x&FUNC_%x", bus, dev, func) == 3)
1313             {
1314               have_bus = TRUE;
1315               have_devfunc = TRUE;
1316             }
1317           else if (seq_xdigit_validate(instance_id, 2, 2) &&
1318                    sscanf(instance_id, "%2x", &devfn) == 1)
1319             {
1320               *dev = devfn >> 3;
1321               *func = devfn & 0x7;
1322               have_devfunc = TRUE;
1323             }
1324         }
1325     }
1326
1327   /*
1328    * Virtual IRQ holder devices do not have assigned any bus/dev/func number and
1329    * have "IRQHOLDER" in their Device Id part. So skip them.
1330    */
1331   if (!have_bus && !have_devfunc && strncmp(devinst_id, "PCI\\IRQHOLDER\\", 14) == 0)
1332     return FALSE;
1333
1334   /*
1335    * When some numbers cannot be retrieved via cfgmgr32 then set them to zeros
1336    * to have structure initialized. It makes sense to report via libpci also
1337    * such "incomplete" device as cfgmgr32 can provide additional information
1338    * like device/vendor ids or assigned resources.
1339    */
1340   if (!have_bus && !have_devfunc)
1341     {
1342       *bus = *dev = *func = 0;
1343       a->warning("Cannot retrieve bus, device and function numbers for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1344     }
1345   else if (!have_bus)
1346     {
1347       *bus = 0;
1348       a->warning("Cannot retrieve bus number for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1349     }
1350   else if (!have_devfunc)
1351     {
1352       *dev = *func = 0;
1353       a->warning("Cannot retrieve device and function numbers for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1354     }
1355
1356   return TRUE;
1357 }
1358
1359 static void
1360 fill_data_from_string(struct pci_dev *d, const char *str)
1361 {
1362   BOOL have_device_id;
1363   BOOL have_vendor_id;
1364   BOOL have_prog_if;
1365   BOOL have_rev_id;
1366   const char *endptr, *endptr2;
1367   unsigned int hex;
1368   int len;
1369
1370   have_device_id = have_vendor_id = (d->known_fields & PCI_FILL_IDENT);
1371   have_prog_if = have_rev_id = (d->known_fields & PCI_FILL_CLASS_EXT);
1372
1373   while (1)
1374     {
1375       endptr = strchr(str, '&');
1376       endptr2 = strchr(str, '\\');
1377       if (endptr2 && (!endptr || endptr > endptr2))
1378         endptr = endptr2;
1379       len = endptr ? endptr-str : (int)strlen(str);
1380
1381       if (!have_vendor_id &&
1382           fmt_validate(str, len, "VEN_####") &&
1383           sscanf(str, "VEN_%x", &hex) == 1)
1384         {
1385           d->vendor_id = hex;
1386           have_vendor_id = TRUE;
1387         }
1388       else if (!have_device_id &&
1389                fmt_validate(str, len, "DEV_####") &&
1390                sscanf(str, "DEV_%x", &hex) == 1)
1391         {
1392           d->device_id = hex;
1393           have_device_id = TRUE;
1394         }
1395       else if (!(d->known_fields & PCI_FILL_SUBSYS) &&
1396                fmt_validate(str, len, "SUBSYS_########") &&
1397                sscanf(str, "SUBSYS_%x", &hex) == 1)
1398         {
1399           d->subsys_vendor_id = hex & 0xffff;
1400           d->subsys_id = hex >> 16;
1401           d->known_fields |= PCI_FILL_SUBSYS;
1402         }
1403       else if (!have_rev_id &&
1404                fmt_validate(str, len, "REV_##") &&
1405                sscanf(str, "REV_%x", &hex) == 1)
1406         {
1407           d->rev_id = hex;
1408           have_rev_id = TRUE;
1409         }
1410       else if (!((d->known_fields & PCI_FILL_CLASS) && have_prog_if) &&
1411                (fmt_validate(str, len, "CC_####") || fmt_validate(str, len, "CC_######")) &&
1412                sscanf(str, "CC_%x", &hex) == 1)
1413         {
1414           if (len == 9)
1415             {
1416               if (!have_prog_if)
1417                 {
1418                   d->prog_if = hex & 0xff;
1419                   have_prog_if = TRUE;
1420                 }
1421               hex >>= 8;
1422             }
1423           if (!(d->known_fields & PCI_FILL_CLASS))
1424             {
1425               d->device_class = hex;
1426               d->known_fields |= PCI_FILL_CLASS;
1427             }
1428         }
1429
1430       if (!endptr || endptr == endptr2)
1431         break;
1432
1433       str = endptr + 1;
1434     }
1435
1436   if ((have_device_id || d->device_id) && (have_vendor_id || d->vendor_id))
1437     d->known_fields |= PCI_FILL_IDENT;
1438
1439   if ((have_prog_if || d->prog_if) && (have_rev_id || d->rev_id))
1440     d->known_fields |= PCI_FILL_CLASS_EXT;
1441 }
1442
1443 static void
1444 fill_data_from_devinst_id(struct pci_dev *d, DEVINSTID_A devinst_id)
1445 {
1446   const char *device_id;
1447
1448   device_id = strchr(devinst_id, '\\');
1449   if (!device_id)
1450     return;
1451   device_id++;
1452
1453   /*
1454    * Device Id part of Device Instance Id is in format:
1455    *  "VEN_####&DEV_####&SUBSYS_########&REV_##"
1456    */
1457   fill_data_from_string(d, device_id);
1458 }
1459
1460 static void
1461 fill_data_from_hardware_ids(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
1462 {
1463   ULONG reg_type, reg_size, reg_len;
1464   struct pci_access *a = d->access;
1465   char *hardware_ids = NULL;
1466   const char *str;
1467   CONFIGRET cr;
1468
1469   reg_size = 0;
1470   cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, &reg_type, NULL, &reg_size, 0);
1471   if (cr != CR_SUCCESS && cr != CR_BUFFER_SMALL)
1472     {
1473       a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1474       return;
1475     }
1476   else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1477     {
1478       a->warning("Cannot retrieve hardware ids for PCI device %s: Hardware ids are stored as unknown type 0x%lx.", devinst_id, reg_type);
1479       return;
1480     }
1481
1482 retry:
1483   /*
1484    * Returned size is on older Windows versions without nul-term char.
1485    * So explicitly increase size and fill nul-term byte.
1486    */
1487   reg_size++;
1488   hardware_ids = pci_malloc(a, reg_size);
1489   reg_len = reg_size;
1490   cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, &reg_type, hardware_ids, &reg_len, 0);
1491   hardware_ids[reg_size - 1] = 0;
1492   if (reg_len > reg_size)
1493     {
1494       pci_mfree(hardware_ids);
1495       reg_size = reg_len;
1496       goto retry;
1497     }
1498   else if (cr != CR_SUCCESS)
1499     {
1500       a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1501       pci_mfree(hardware_ids);
1502       return;
1503     }
1504   else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1505     {
1506       a->warning("Cannot retrieve hardware ids for PCI device %s: Hardware ids are stored as unknown type 0x%lx.", devinst_id, reg_type);
1507       pci_mfree(hardware_ids);
1508       return;
1509     }
1510
1511   /*
1512    * Hardware ids is nul-separated nul-term string list where each string has
1513    * one of the following format:
1514    *  "PCI\\VEN_####&DEV_####&SUBSYS_########&REV_##"
1515    *  "PCI\\VEN_####&DEV_####&SUBSYS_########"
1516    *  "PCI\\VEN_####&DEV_####&REV_##&CC_####"
1517    *  "PCI\\VEN_####&DEV_####&CC_######"
1518    *  "PCI\\VEN_####&DEV_####&CC_####"
1519    *  "PCI\\VEN_####&DEV_####&REV_##"
1520    *  "PCI\\VEN_####&DEV_####"
1521    */
1522   for (str = hardware_ids; *str != '\0'; str += strlen(str) + 1)
1523     {
1524       if (strncmp(str, "PCI\\", 4) != 0)
1525         continue;
1526       str += 4;
1527       fill_data_from_string(d, str);
1528     }
1529
1530   pci_mfree(hardware_ids);
1531 }
1532
1533 static void
1534 scan_devinst_id(struct pci_access *a, DEVINSTID_A devinst_id)
1535 {
1536   unsigned int domain, bus, dev, func;
1537   struct pci_dev *d;
1538   DEVINST devinst;
1539   CONFIGRET cr;
1540
1541   cr = CM_Locate_DevNodeA(&devinst, devinst_id, CM_LOCATE_DEVNODE_NORMAL);
1542   if (cr != CR_SUCCESS)
1543     {
1544       /* Do not show warning when device is not present (= does not match NORMAL flag). */
1545       if (cr != CR_NO_SUCH_DEVNODE)
1546         a->warning("Cannot retrieve handle for device %s: %s.", devinst_id, cr_strerror(cr));
1547       return;
1548     }
1549
1550   /* get_device_location() returns FALSE if devinst is not real PCI device. */
1551   if (!get_device_location(a, devinst, devinst_id, &domain, &bus, &dev, &func))
1552     return;
1553
1554   d = pci_get_dev(a, domain, bus, dev, func);
1555   pci_link_dev(a, d);
1556   if (!d->access->aux)
1557     d->no_config_access = 1;
1558   d->aux = (void *)devinst;
1559
1560   /* Parse device id part of devinst id and fill details into pci_dev. */
1561   if (!a->buscentric)
1562     fill_data_from_devinst_id(d, devinst_id);
1563
1564   /* Retrieve hardware ids of devinst, parse them and fill details into pci_dev. */
1565   if (!a->buscentric)
1566     fill_data_from_hardware_ids(d, devinst, devinst_id);
1567
1568   if (!a->buscentric)
1569     fill_resources(d, devinst, devinst_id);
1570
1571   /*
1572    * Set parent field to cfgmgr32 parent devinst handle and aux field to current
1573    * devinst handle. At later stage in win32_cfgmgr32_scan() when all pci_dev
1574    * devices are linked, change every devinst handle by pci_dev.
1575    */
1576   if (!a->buscentric)
1577     {
1578       DEVINST parent_devinst;
1579       if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS)
1580         {
1581           parent_devinst = 0;
1582           a->warning("Cannot retrieve parent handle for device %s: %s.", devinst_id, cr_strerror(cr));
1583         }
1584       d->parent = (void *)parent_devinst;
1585     }
1586 }
1587
1588 static void
1589 win32_cfgmgr32_scan(struct pci_access *a)
1590 {
1591   ULONG devinst_id_list_size;
1592   PCHAR devinst_id_list;
1593   DEVINSTID_A devinst_id;
1594   struct pci_dev *d;
1595   CONFIGRET cr;
1596
1597   if (!resolve_cfgmgr32_functions())
1598     {
1599       a->warning("Required cfgmgr32.dll functions are unavailable.");
1600       return;
1601     }
1602
1603   /*
1604    * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1605    * support this API but returns CR_SUCCESS without touching size argument.
1606    */
1607   devinst_id_list_size = 0;
1608   cr = CM_Get_Device_ID_List_SizeA(&devinst_id_list_size, "PCI", CM_GETIDLIST_FILTER_ENUMERATOR);
1609   if (cr != CR_SUCCESS)
1610     {
1611       a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1612       return;
1613     }
1614   else if (devinst_id_list_size <= 1)
1615     {
1616       a->warning("Cannot retrieve list of PCI devices: No device was found.");
1617       return;
1618     }
1619
1620   devinst_id_list = pci_malloc(a, devinst_id_list_size);
1621   cr = CM_Get_Device_ID_ListA("PCI", devinst_id_list, devinst_id_list_size, CM_GETIDLIST_FILTER_ENUMERATOR);
1622   if (cr != CR_SUCCESS)
1623     {
1624       a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1625       pci_mfree(devinst_id_list);
1626       return;
1627     }
1628
1629   /* Register pci_dev for each cfgmgr32 devinst handle. */
1630   for (devinst_id = devinst_id_list; *devinst_id; devinst_id += strlen(devinst_id) + 1)
1631     scan_devinst_id(a, devinst_id);
1632
1633   /* Fill all drivers. */
1634   if (!a->buscentric)
1635     fill_drivers(a);
1636
1637   /* Switch parent fields from cfgmgr32 devinst handle to pci_dev. */
1638   if (!a->buscentric)
1639     {
1640       struct pci_dev *d1, *d2;
1641       for (d1 = a->devices; d1; d1 = d1->next)
1642         {
1643           for (d2 = a->devices; d2; d2 = d2->next)
1644             if ((DEVINST)d1->parent == (DEVINST)d2->aux)
1645               break;
1646           d1->parent = d2;
1647           if (d1->parent)
1648             d1->known_fields |= PCI_FILL_PARENT;
1649         }
1650     }
1651
1652   /* devinst stored in ->aux is not needed anymore, clear it. */
1653   for (d = a->devices; d; d = d->next)
1654     d->aux = NULL;
1655
1656   pci_mfree(devinst_id_list);
1657 }
1658
1659 static void
1660 win32_cfgmgr32_config(struct pci_access *a)
1661 {
1662   pci_define_param(a, "win32.cfgmethod", "auto", "PCI config space access method");
1663 }
1664
1665 static int
1666 win32_cfgmgr32_detect(struct pci_access *a)
1667 {
1668   ULONG devinst_id_list_size;
1669   CONFIGRET cr;
1670
1671   if (!resolve_cfgmgr32_functions())
1672     {
1673       a->debug("Required cfgmgr32.dll functions are unavailable.");
1674       return 0;
1675     }
1676
1677   /*
1678    * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1679    * support this API but returns CR_SUCCESS without touching size argument.
1680    */
1681   devinst_id_list_size = 0;
1682   cr = CM_Get_Device_ID_List_SizeA(&devinst_id_list_size, "PCI", CM_GETIDLIST_FILTER_ENUMERATOR);
1683   if (cr != CR_SUCCESS)
1684     {
1685       a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): %s.", cr_strerror(cr));
1686       return 0;
1687     }
1688   else if (devinst_id_list_size <= 1)
1689     {
1690       a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): No device was found.");
1691       return 0;
1692     }
1693
1694   return 1;
1695 }
1696
1697 static void
1698 win32_cfgmgr32_fill_info(struct pci_dev *d, unsigned int flags)
1699 {
1700   /*
1701    * All available flags were filled by win32_cfgmgr32_scan().
1702    * Filling more flags is possible only from config space.
1703    */
1704   if (!d->access->aux)
1705     return;
1706
1707   pci_generic_fill_info(d, flags);
1708 }
1709
1710 static int
1711 win32_cfgmgr32_read(struct pci_dev *d, int pos, byte *buf, int len)
1712 {
1713   struct pci_access *a = d->access;
1714   struct pci_access *acfg = a->aux;
1715   struct pci_dev *dcfg = d->aux;
1716
1717   if (!acfg)
1718     return pci_emulated_read(d, pos, buf, len);
1719
1720   if (!dcfg)
1721     d->aux = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
1722
1723   return pci_read_block(dcfg, pos, buf, len);
1724 }
1725
1726 static int
1727 win32_cfgmgr32_write(struct pci_dev *d, int pos, byte *buf, int len)
1728 {
1729   struct pci_access *a = d->access;
1730   struct pci_access *acfg = a->aux;
1731   struct pci_dev *dcfg = d->aux;
1732
1733   if (!acfg)
1734     return 0;
1735
1736   if (!dcfg)
1737     d->aux = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
1738
1739   return pci_write_block(dcfg, pos, buf, len);
1740 }
1741
1742 static void
1743 win32_cfgmgr32_cleanup_dev(struct pci_dev *d)
1744 {
1745   struct pci_dev *dcfg = d->aux;
1746
1747   if (dcfg)
1748     pci_free_dev(dcfg);
1749 }
1750
1751 static void
1752 win32_cfgmgr32_init(struct pci_access *a)
1753 {
1754   char *cfgmethod = pci_get_param(a, "win32.cfgmethod");
1755   struct pci_access *acfg;
1756
1757   if (strcmp(cfgmethod, "") == 0 ||
1758       strcmp(cfgmethod, "auto") == 0)
1759     {
1760       acfg = pci_clone_access(a);
1761       acfg->method = PCI_ACCESS_AUTO;
1762     }
1763   else if (strcmp(cfgmethod, "none") == 0 ||
1764            strcmp(cfgmethod, "win32-cfgmgr32") == 0)
1765     {
1766       if (a->writeable)
1767         a->error("Write access requested but option win32.cfgmethod was not set.");
1768       return;
1769     }
1770   else
1771     {
1772       int m = pci_lookup_method(cfgmethod);
1773       if (m < 0)
1774         a->error("Option win32.cfgmethod is set to an unknown access method \"%s\".", cfgmethod);
1775       acfg = pci_clone_access(a);
1776       acfg->method = m;
1777     }
1778
1779   a->debug("Loading config space access method...\n");
1780   if (!pci_init_internal(acfg, PCI_ACCESS_WIN32_CFGMGR32))
1781     {
1782       pci_cleanup(acfg);
1783       a->debug("Cannot find any working config space access method.\n");
1784       if (a->writeable)
1785         a->error("Write access requested but no usable access method found.");
1786       return;
1787     }
1788
1789   a->aux = acfg;
1790 }
1791
1792 static void
1793 win32_cfgmgr32_cleanup(struct pci_access *a)
1794 {
1795   struct pci_access *acfg = a->aux;
1796
1797   if (acfg)
1798     pci_cleanup(acfg);
1799 }
1800
1801 struct pci_methods pm_win32_cfgmgr32 = {
1802   "win32-cfgmgr32",
1803   "Win32 device listing via Configuration Manager",
1804   win32_cfgmgr32_config,
1805   win32_cfgmgr32_detect,
1806   win32_cfgmgr32_init,
1807   win32_cfgmgr32_cleanup,
1808   win32_cfgmgr32_scan,
1809   win32_cfgmgr32_fill_info,
1810   win32_cfgmgr32_read,
1811   win32_cfgmgr32_write,
1812   NULL,                                 /* read_vpd */
1813   NULL,                                 /* init_dev */
1814   win32_cfgmgr32_cleanup_dev,
1815 };