]> mj.ucw.cz Git - pciutils.git/blob - lib/win32-cfgmgr32.c
libpci: win32-cfgmgr32: Show type of source in warning message
[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       cr = CM_Get_Res_Des_Data_Size(&res_des_data_size, res_des, 0);
1051       if (cr != CR_SUCCESS)
1052         {
1053           a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, cr_strerror(cr));
1054           continue;
1055         }
1056
1057       if (!res_des_data_size)
1058         {
1059           a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, "Empty data");
1060           continue;
1061         }
1062
1063       res_des_data = pci_malloc(a, res_des_data_size);
1064       cr = CM_Get_Res_Des_Data(res_des, res_des_data, res_des_data_size, 0);
1065       if (cr != CR_SUCCESS)
1066         {
1067           a->warning("Cannot retrieve %s resource data of PCI device %s: %s.", res_id_to_str(res_id), devinst_id, cr_strerror(cr));
1068           pci_mfree(res_des_data);
1069           continue;
1070         }
1071
1072       /*
1073        * There can be more resources with the same id. In this case we are
1074        * interested in the last one in the list as at the beginning of the list
1075        * can be some virtual resources (which are not set in PCI config space).
1076        */
1077
1078       if (res_id == ResType_IO)
1079         {
1080           PIO_RESOURCE io_data = (PIO_RESOURCE)res_des_data;
1081
1082           start = io_data->IO_Header.IOD_Alloc_Base;
1083           end = io_data->IO_Header.IOD_Alloc_End;
1084           size = (end > start) ? (end - start + 1) : 0;
1085           flags = PCI_IORESOURCE_IO;
1086
1087           /*
1088            * If neither 10-bit, 12-bit, nor 16-bit support is presented then
1089            * expects that this is 32-bit I/O resource. If resource does not fit
1090            * into 16-bit space then it must be 32-bit. If PCI I/O resource is
1091            * not 32-bit then it is 16-bit.
1092            */
1093           if (end <= 0xffff && (io_data->IO_Header.IOD_DesFlags & (fIOD_10_BIT_DECODE|fIOD_12_BIT_DECODE|fIOD_16_BIT_DECODE)))
1094             flags |= PCI_IORESOURCE_IO_16BIT_ADDR;
1095
1096           /*
1097            * 16/32-bit non-NT systems do not support these two flags.
1098            * Most NT-based Windows versions support only the fIOD_WINDOW_DECODE
1099            * flag and put all BAR resources before window resources in this
1100            * resource list. So use this fIOD_WINDOW_DECODE flag as separator
1101            * between IO/MEM windows and IO/MEM BARs of PCI Bridges.
1102            */
1103           if (io_data->IO_Header.IOD_DesFlags & fIOD_WINDOW_DECODE)
1104             is_bar_res = FALSE;
1105           else if (io_data->IO_Header.IOD_DesFlags & fIOD_PORT_BAR)
1106             is_bar_res = TRUE;
1107
1108           if (is_bar_res && bar_res_count < 6)
1109             {
1110               d->flags[bar_res_count] = flags;
1111               d->base_addr[bar_res_count] = start;
1112               d->size[bar_res_count] = size;
1113               bar_res_count++;
1114             }
1115           else if (!is_bar_res)
1116             {
1117               d->bridge_flags[0] = flags;
1118               d->bridge_base_addr[0] = start;
1119               d->bridge_size[0] = size;
1120               d->known_fields |= PCI_FILL_BRIDGE_BASES;
1121             }
1122         }
1123       else if (res_id == ResType_Mem)
1124         {
1125           PMEM_RESOURCE mem_data = (PMEM_RESOURCE)res_des_data;
1126
1127           start = mem_data->MEM_Header.MD_Alloc_Base;
1128           end = mem_data->MEM_Header.MD_Alloc_End;
1129           size = (end > start) ? (end - start + 1) : 0;
1130           flags = PCI_IORESOURCE_MEM;
1131
1132           /*
1133            * If fMD_PrefetchAllowed flag is set then this is
1134            * PCI Prefetchable Memory resource.
1135            */
1136           if ((mem_data->MEM_Header.MD_Flags & mMD_Prefetchable) == fMD_PrefetchAllowed)
1137             flags |= PCI_IORESOURCE_PREFETCH;
1138
1139           /* If resource does not fit into 32-bit space then it must be 64-bit. */
1140           if (is_bar_res && end > 0xffffffff)
1141             flags |= PCI_IORESOURCE_MEM_64;
1142
1143           /*
1144            * These two flags (fMD_WINDOW_DECODE and fMD_MEMORY_BAR) are
1145            * unsupported on most Windows versions, so distinguish between
1146            * window and BAR based on previous resource type.
1147            */
1148           if (mem_data->MEM_Header.MD_Flags & fMD_WINDOW_DECODE)
1149             is_bar_res = FALSE;
1150           else if (mem_data->MEM_Header.MD_Flags & fMD_MEMORY_BAR)
1151             is_bar_res = TRUE;
1152
1153           /* 64-bit BAR resource must be at even position. */
1154           if (is_bar_res && (flags & PCI_IORESOURCE_MEM_64) && bar_res_count % 2)
1155             bar_res_count++;
1156
1157           if (is_bar_res && bar_res_count < 6)
1158             {
1159               d->flags[bar_res_count] = flags;
1160               d->base_addr[bar_res_count] = start;
1161               d->size[bar_res_count] = size;
1162               bar_res_count++;
1163               /* 64-bit BAR resource occupies two slots. */
1164               if (flags & PCI_IORESOURCE_MEM_64)
1165                 bar_res_count++;
1166             }
1167           else if (!is_bar_res && !(flags & PCI_IORESOURCE_PREFETCH))
1168             {
1169               d->bridge_flags[1] = flags;
1170               d->bridge_base_addr[1] = start;
1171               d->bridge_size[1] = size;
1172               d->known_fields |= PCI_FILL_BRIDGE_BASES;
1173             }
1174           else if (!is_bar_res && (flags & PCI_IORESOURCE_PREFETCH))
1175             {
1176               d->bridge_flags[2] = flags;
1177               d->bridge_base_addr[2] = start;
1178               d->bridge_size[2] = size;
1179               d->known_fields |= PCI_FILL_BRIDGE_BASES;
1180             }
1181         }
1182       else if (res_id == ResType_IRQ)
1183         {
1184           PIRQ_RESOURCE irq_data = (PIRQ_RESOURCE)res_des_data;
1185
1186           /*
1187            * libpci's d->irq should be set to the non-MSI PCI IRQ and therefore
1188            * it should be level IRQ which may be shared with other PCI devices
1189            * and drivers in the system. As always we want to retrieve the last
1190            * IRQ number from the resource list.
1191            *
1192            * On 16/32-bit non-NT systems is fIRQD_Level set to 2 but on NT
1193            * systems to 0. Moreover it looks like that different PCI drivers
1194            * on both NT and non-NT systems set bits 0 and 1 to wrong values
1195            * and so reported value in this list may be incorrect.
1196            *
1197            * Therefore take the last level-shared IRQ number from the resource
1198            * list and if there is none of this type then take the last IRQ
1199            * number from the list.
1200            */
1201           last_irq = irq_data->IRQ_Header.IRQD_Alloc_Num;
1202           if ((irq_data->IRQ_Header.IRQD_Flags & (mIRQD_Share|mIRQD_Edge_Level)) == (fIRQD_Share|fIRQD_Level))
1203             last_shared_irq = irq_data->IRQ_Header.IRQD_Alloc_Num;
1204
1205           /*
1206            * IRQ resource on 16/32-bit non-NT systems is separator between
1207            * IO/MEM windows and IO/MEM BARs of PCI Bridges. After the IRQ
1208            * resource are IO/MEM BAR resources.
1209            */
1210           if (!is_bar_res && non_nt_system)
1211             is_bar_res = TRUE;
1212         }
1213
1214       pci_mfree(res_des_data);
1215     }
1216   if (cr != CR_NO_MORE_RES_DES)
1217     a->warning("Cannot retrieve resources of PCI device %s: %s.", devinst_id, cr_strerror(cr));
1218
1219   if (prev_res_des != config)
1220     CM_Free_Res_Des_Handle(prev_res_des);
1221
1222   CM_Free_Log_Conf_Handle(config);
1223
1224   /* Set the last IRQ from the resource list to pci_dev. */
1225   if (last_shared_irq >= 0)
1226     d->irq = last_shared_irq;
1227   else if (last_irq >= 0)
1228     d->irq = last_irq;
1229   if (last_shared_irq >= 0 || last_irq >= 0)
1230     d->known_fields |= PCI_FILL_IRQ;
1231
1232   if (bar_res_count > 0)
1233     d->known_fields |= PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS;
1234 }
1235
1236 static BOOL
1237 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)
1238 {
1239   ULONG reg_type, reg_len;
1240   CONFIGRET cr;
1241   BOOL have_bus, have_devfunc;
1242   DWORD drp_bus_num, drp_address;
1243
1244   *domain = 0;
1245   have_bus = FALSE;
1246   have_devfunc = FALSE;
1247
1248   /*
1249    * DRP_BUSNUMBER consists of PCI domain number in high 24 bits
1250    * and PCI bus number in low 8 bits.
1251    */
1252   reg_len = sizeof(drp_bus_num);
1253   cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_BUSNUMBER, &reg_type, &drp_bus_num, &reg_len, 0);
1254   if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_bus_num))
1255     {
1256       *domain = drp_bus_num >> 8;
1257       *bus = drp_bus_num & 0xff;
1258       have_bus = TRUE;
1259     }
1260
1261   /*
1262    * DRP_ADDRESS consists of PCI device number in high 16 bits
1263    * and PCI function number in low 16 bits.
1264    */
1265   reg_len = sizeof(drp_address);
1266   cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_ADDRESS, &reg_type, &drp_address, &reg_len, 0);
1267   if (cr == CR_SUCCESS && reg_type == REG_DWORD && reg_len == sizeof(drp_address))
1268     {
1269       *dev = drp_address >> 16;
1270       *func = drp_address & 0xffff;
1271       have_devfunc = TRUE;
1272     }
1273
1274   /*
1275    * Device Instance Id for PCI devices is of format:
1276    *  "<enumerator>\\<device_id>\\<instance_id>"
1277    * where:
1278    *  "<enumerator>" is "PCI"
1279    *  "<device_id>" is "VEN_####&DEV_####&SUBSYS_########&REV_##"
1280    * and "<instance_id>" for PCI devices is at least in one of following format:
1281    *  "BUS_##&DEV_##&FUNC_##"
1282    *  "##.." (sequence of devfn hex bytes, where bytes represents tree path to the root)
1283    *  "#..&#..&#..&#.." (four hex numbers separated by "&"; meaning is unknown yet)
1284    *
1285    * First two formats are used only on systems without support for multiple
1286    * domains. The second format uses intel-conf encoding of device and function
1287    * number: Low 3 bits is function number and high 5 bits is device number.
1288    * Bus number is not really encoded in second format!
1289    *
1290    * The third format is used on systems with support for multiple domains but
1291    * format is variable length and currently its meaning is unknown. Apparently
1292    * it looks like that DRP_BUSNUMBER and DRP_ADDRESS registry properties are
1293    * supported on these systems.
1294    *
1295    * If DRP_BUSNUMBER or DRP_ADDRESS failed then try to parse PCI bus, device
1296    * and function numbers from Instance Id part.
1297    */
1298   if (!have_bus || !have_devfunc)
1299     {
1300       const char *device_id0 = strchr(devinst_id, '\\');
1301       const char *instance_id0 = device_id0 ? strchr(device_id0 + 1, '\\') : NULL;
1302       const char *instance_id = instance_id0 ? instance_id0 + 1 : NULL;
1303       unsigned int devfn;
1304
1305       if (instance_id)
1306         {
1307           if (fmt_validate(instance_id, strlen(instance_id), "BUS_##&DEV_##&FUNC_##") &&
1308               sscanf(instance_id, "BUS_%x&DEV_%x&FUNC_%x", bus, dev, func) == 3)
1309             {
1310               have_bus = TRUE;
1311               have_devfunc = TRUE;
1312             }
1313           else if (seq_xdigit_validate(instance_id, 2, 2) &&
1314                    sscanf(instance_id, "%2x", &devfn) == 1)
1315             {
1316               *dev = devfn >> 3;
1317               *func = devfn & 0x7;
1318               have_devfunc = TRUE;
1319             }
1320         }
1321     }
1322
1323   /*
1324    * Virtual IRQ holder devices do not have assigned any bus/dev/func number and
1325    * have "IRQHOLDER" in their Device Id part. So skip them.
1326    */
1327   if (!have_bus && !have_devfunc && strncmp(devinst_id, "PCI\\IRQHOLDER\\", 14) == 0)
1328     return FALSE;
1329
1330   /*
1331    * When some numbers cannot be retrieved via cfgmgr32 then set them to zeros
1332    * to have structure initialized. It makes sense to report via libpci also
1333    * such "incomplete" device as cfgmgr32 can provide additional information
1334    * like device/vendor ids or assigned resources.
1335    */
1336   if (!have_bus && !have_devfunc)
1337     {
1338       *bus = *dev = *func = 0;
1339       a->warning("Cannot retrieve bus, device and function numbers for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1340     }
1341   else if (!have_bus)
1342     {
1343       *bus = 0;
1344       a->warning("Cannot retrieve bus number for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1345     }
1346   else if (!have_devfunc)
1347     {
1348       *dev = *func = 0;
1349       a->warning("Cannot retrieve device and function numbers for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1350     }
1351
1352   return TRUE;
1353 }
1354
1355 static void
1356 fill_data_from_string(struct pci_dev *d, const char *str)
1357 {
1358   BOOL have_device_id;
1359   BOOL have_vendor_id;
1360   BOOL have_prog_if;
1361   BOOL have_rev_id;
1362   const char *endptr, *endptr2;
1363   unsigned int hex;
1364   int len;
1365
1366   have_device_id = have_vendor_id = (d->known_fields & PCI_FILL_IDENT);
1367   have_prog_if = have_rev_id = (d->known_fields & PCI_FILL_CLASS_EXT);
1368
1369   while (1)
1370     {
1371       endptr = strchr(str, '&');
1372       endptr2 = strchr(str, '\\');
1373       if (endptr2 && (!endptr || endptr > endptr2))
1374         endptr = endptr2;
1375       len = endptr ? endptr-str : (int)strlen(str);
1376
1377       if (!have_vendor_id &&
1378           fmt_validate(str, len, "VEN_####") &&
1379           sscanf(str, "VEN_%x", &hex) == 1)
1380         {
1381           d->vendor_id = hex;
1382           have_vendor_id = TRUE;
1383         }
1384       else if (!have_device_id &&
1385                fmt_validate(str, len, "DEV_####") &&
1386                sscanf(str, "DEV_%x", &hex) == 1)
1387         {
1388           d->device_id = hex;
1389           have_device_id = TRUE;
1390         }
1391       else if (!(d->known_fields & PCI_FILL_SUBSYS) &&
1392                fmt_validate(str, len, "SUBSYS_########") &&
1393                sscanf(str, "SUBSYS_%x", &hex) == 1)
1394         {
1395           d->subsys_vendor_id = hex & 0xffff;
1396           d->subsys_id = hex >> 16;
1397           d->known_fields |= PCI_FILL_SUBSYS;
1398         }
1399       else if (!have_rev_id &&
1400                fmt_validate(str, len, "REV_##") &&
1401                sscanf(str, "REV_%x", &hex) == 1)
1402         {
1403           d->rev_id = hex;
1404           have_rev_id = TRUE;
1405         }
1406       else if (!((d->known_fields & PCI_FILL_CLASS) && have_prog_if) &&
1407                (fmt_validate(str, len, "CC_####") || fmt_validate(str, len, "CC_######")) &&
1408                sscanf(str, "CC_%x", &hex) == 1)
1409         {
1410           if (len == 9)
1411             {
1412               if (!have_prog_if)
1413                 {
1414                   d->prog_if = hex & 0xff;
1415                   have_prog_if = TRUE;
1416                 }
1417               hex >>= 8;
1418             }
1419           if (!(d->known_fields & PCI_FILL_CLASS))
1420             {
1421               d->device_class = hex;
1422               d->known_fields |= PCI_FILL_CLASS;
1423             }
1424         }
1425
1426       if (!endptr || endptr == endptr2)
1427         break;
1428
1429       str = endptr + 1;
1430     }
1431
1432   if ((have_device_id || d->device_id) && (have_vendor_id || d->vendor_id))
1433     d->known_fields |= PCI_FILL_IDENT;
1434
1435   if ((have_prog_if || d->prog_if) && (have_rev_id || d->rev_id))
1436     d->known_fields |= PCI_FILL_CLASS_EXT;
1437 }
1438
1439 static void
1440 fill_data_from_devinst_id(struct pci_dev *d, DEVINSTID_A devinst_id)
1441 {
1442   const char *device_id;
1443
1444   device_id = strchr(devinst_id, '\\');
1445   if (!device_id)
1446     return;
1447   device_id++;
1448
1449   /*
1450    * Device Id part of Device Instance Id is in format:
1451    *  "VEN_####&DEV_####&SUBSYS_########&REV_##"
1452    */
1453   fill_data_from_string(d, device_id);
1454 }
1455
1456 static void
1457 fill_data_from_hardware_ids(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
1458 {
1459   ULONG reg_type, reg_size, reg_len;
1460   struct pci_access *a = d->access;
1461   char *hardware_ids = NULL;
1462   const char *str;
1463   CONFIGRET cr;
1464
1465   reg_size = 0;
1466   cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, &reg_type, NULL, &reg_size, 0);
1467   if (cr != CR_SUCCESS && cr != CR_BUFFER_SMALL)
1468     {
1469       a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1470       return;
1471     }
1472   else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1473     {
1474       a->warning("Cannot retrieve hardware ids for PCI device %s: Hardware ids are stored as unknown type 0x%lx.", devinst_id, reg_type);
1475       return;
1476     }
1477
1478 retry:
1479   /*
1480    * Returned size is on older Windows versions without nul-term char.
1481    * So explicitly increase size and fill nul-term byte.
1482    */
1483   reg_size++;
1484   hardware_ids = pci_malloc(a, reg_size);
1485   reg_len = reg_size;
1486   cr = CM_Get_DevNode_Registry_PropertyA(devinst, CM_DRP_HARDWAREID, &reg_type, hardware_ids, &reg_len, 0);
1487   hardware_ids[reg_size - 1] = 0;
1488   if (reg_len > reg_size)
1489     {
1490       pci_mfree(hardware_ids);
1491       reg_size = reg_len;
1492       goto retry;
1493     }
1494   else if (cr != CR_SUCCESS)
1495     {
1496       a->warning("Cannot retrieve hardware ids for PCI device %s: %s.", devinst_id, cr_strerror(cr));
1497       pci_mfree(hardware_ids);
1498       return;
1499     }
1500   else if (reg_type != REG_MULTI_SZ && reg_type != REG_SZ) /* Older Windows versions return REG_SZ and new versions REG_MULTI_SZ. */
1501     {
1502       a->warning("Cannot retrieve hardware ids for PCI device %s: Hardware ids are stored as unknown type 0x%lx.", devinst_id, reg_type);
1503       pci_mfree(hardware_ids);
1504       return;
1505     }
1506
1507   /*
1508    * Hardware ids is nul-separated nul-term string list where each string has
1509    * one of the following format:
1510    *  "PCI\\VEN_####&DEV_####&SUBSYS_########&REV_##"
1511    *  "PCI\\VEN_####&DEV_####&SUBSYS_########"
1512    *  "PCI\\VEN_####&DEV_####&REV_##&CC_####"
1513    *  "PCI\\VEN_####&DEV_####&CC_######"
1514    *  "PCI\\VEN_####&DEV_####&CC_####"
1515    *  "PCI\\VEN_####&DEV_####&REV_##"
1516    *  "PCI\\VEN_####&DEV_####"
1517    */
1518   for (str = hardware_ids; *str != '\0'; str += strlen(str) + 1)
1519     {
1520       if (strncmp(str, "PCI\\", 4) != 0)
1521         continue;
1522       str += 4;
1523       fill_data_from_string(d, str);
1524     }
1525
1526   pci_mfree(hardware_ids);
1527 }
1528
1529 static void
1530 scan_devinst_id(struct pci_access *a, DEVINSTID_A devinst_id)
1531 {
1532   unsigned int domain, bus, dev, func;
1533   struct pci_dev *d;
1534   DEVINST devinst;
1535   CONFIGRET cr;
1536
1537   cr = CM_Locate_DevNodeA(&devinst, devinst_id, CM_LOCATE_DEVNODE_NORMAL);
1538   if (cr != CR_SUCCESS)
1539     {
1540       /* Do not show warning when device is not present (= does not match NORMAL flag). */
1541       if (cr != CR_NO_SUCH_DEVNODE)
1542         a->warning("Cannot retrieve handle for device %s: %s.", devinst_id, cr_strerror(cr));
1543       return;
1544     }
1545
1546   /* get_device_location() returns FALSE if devinst is not real PCI device. */
1547   if (!get_device_location(a, devinst, devinst_id, &domain, &bus, &dev, &func))
1548     return;
1549
1550   d = pci_get_dev(a, domain, bus, dev, func);
1551   pci_link_dev(a, d);
1552   if (!d->access->aux)
1553     d->no_config_access = 1;
1554   d->aux = (void *)devinst;
1555
1556   /* Parse device id part of devinst id and fill details into pci_dev. */
1557   if (!a->buscentric)
1558     fill_data_from_devinst_id(d, devinst_id);
1559
1560   /* Retrieve hardware ids of devinst, parse them and fill details into pci_dev. */
1561   if (!a->buscentric)
1562     fill_data_from_hardware_ids(d, devinst, devinst_id);
1563
1564   if (!a->buscentric)
1565     fill_resources(d, devinst, devinst_id);
1566
1567   /*
1568    * Set parent field to cfgmgr32 parent devinst handle and aux field to current
1569    * devinst handle. At later stage in win32_cfgmgr32_scan() when all pci_dev
1570    * devices are linked, change every devinst handle by pci_dev.
1571    */
1572   if (!a->buscentric)
1573     {
1574       DEVINST parent_devinst;
1575       if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS)
1576         {
1577           parent_devinst = 0;
1578           a->warning("Cannot retrieve parent handle for device %s: %s.", devinst_id, cr_strerror(cr));
1579         }
1580       d->parent = (void *)parent_devinst;
1581     }
1582 }
1583
1584 static void
1585 win32_cfgmgr32_scan(struct pci_access *a)
1586 {
1587   ULONG devinst_id_list_size;
1588   PCHAR devinst_id_list;
1589   DEVINSTID_A devinst_id;
1590   struct pci_dev *d;
1591   CONFIGRET cr;
1592
1593   if (!resolve_cfgmgr32_functions())
1594     {
1595       a->warning("Required cfgmgr32.dll functions are unavailable.");
1596       return;
1597     }
1598
1599   /*
1600    * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1601    * support this API but returns CR_SUCCESS without touching size argument.
1602    */
1603   devinst_id_list_size = 0;
1604   cr = CM_Get_Device_ID_List_SizeA(&devinst_id_list_size, "PCI", CM_GETIDLIST_FILTER_ENUMERATOR);
1605   if (cr != CR_SUCCESS)
1606     {
1607       a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1608       return;
1609     }
1610   else if (devinst_id_list_size <= 1)
1611     {
1612       a->warning("Cannot retrieve list of PCI devices: No device was found.");
1613       return;
1614     }
1615
1616   devinst_id_list = pci_malloc(a, devinst_id_list_size);
1617   cr = CM_Get_Device_ID_ListA("PCI", devinst_id_list, devinst_id_list_size, CM_GETIDLIST_FILTER_ENUMERATOR);
1618   if (cr != CR_SUCCESS)
1619     {
1620       a->warning("Cannot retrieve list of PCI devices: %s.", cr_strerror(cr));
1621       pci_mfree(devinst_id_list);
1622       return;
1623     }
1624
1625   /* Register pci_dev for each cfgmgr32 devinst handle. */
1626   for (devinst_id = devinst_id_list; *devinst_id; devinst_id += strlen(devinst_id) + 1)
1627     scan_devinst_id(a, devinst_id);
1628
1629   /* Fill all drivers. */
1630   if (!a->buscentric)
1631     fill_drivers(a);
1632
1633   /* Switch parent fields from cfgmgr32 devinst handle to pci_dev. */
1634   if (!a->buscentric)
1635     {
1636       struct pci_dev *d1, *d2;
1637       for (d1 = a->devices; d1; d1 = d1->next)
1638         {
1639           for (d2 = a->devices; d2; d2 = d2->next)
1640             if ((DEVINST)d1->parent == (DEVINST)d2->aux)
1641               break;
1642           d1->parent = d2;
1643           if (d1->parent)
1644             d1->known_fields |= PCI_FILL_PARENT;
1645         }
1646     }
1647
1648   /* devinst stored in ->aux is not needed anymore, clear it. */
1649   for (d = a->devices; d; d = d->next)
1650     d->aux = NULL;
1651
1652   pci_mfree(devinst_id_list);
1653 }
1654
1655 static void
1656 win32_cfgmgr32_config(struct pci_access *a)
1657 {
1658   pci_define_param(a, "win32.cfgmethod", "auto", "PCI config space access method");
1659 }
1660
1661 static int
1662 win32_cfgmgr32_detect(struct pci_access *a)
1663 {
1664   ULONG devinst_id_list_size;
1665   CONFIGRET cr;
1666
1667   if (!resolve_cfgmgr32_functions())
1668     {
1669       a->debug("Required cfgmgr32.dll functions are unavailable.");
1670       return 0;
1671     }
1672
1673   /*
1674    * Explicitly initialize size to zero as wine cfgmgr32 implementation does not
1675    * support this API but returns CR_SUCCESS without touching size argument.
1676    */
1677   devinst_id_list_size = 0;
1678   cr = CM_Get_Device_ID_List_SizeA(&devinst_id_list_size, "PCI", CM_GETIDLIST_FILTER_ENUMERATOR);
1679   if (cr != CR_SUCCESS)
1680     {
1681       a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): %s.", cr_strerror(cr));
1682       return 0;
1683     }
1684   else if (devinst_id_list_size <= 1)
1685     {
1686       a->debug("CM_Get_Device_ID_List_SizeA(\"PCI\"): No device was found.");
1687       return 0;
1688     }
1689
1690   return 1;
1691 }
1692
1693 static void
1694 win32_cfgmgr32_fill_info(struct pci_dev *d, unsigned int flags)
1695 {
1696   /*
1697    * All available flags were filled by win32_cfgmgr32_scan().
1698    * Filling more flags is possible only from config space.
1699    */
1700   if (!d->access->aux)
1701     return;
1702
1703   pci_generic_fill_info(d, flags);
1704 }
1705
1706 static int
1707 win32_cfgmgr32_read(struct pci_dev *d, int pos, byte *buf, int len)
1708 {
1709   struct pci_access *a = d->access;
1710   struct pci_access *acfg = a->aux;
1711   struct pci_dev *dcfg = d->aux;
1712
1713   if (!acfg)
1714     return pci_emulated_read(d, pos, buf, len);
1715
1716   if (!dcfg)
1717     d->aux = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
1718
1719   return pci_read_block(dcfg, pos, buf, len);
1720 }
1721
1722 static int
1723 win32_cfgmgr32_write(struct pci_dev *d, int pos, byte *buf, int len)
1724 {
1725   struct pci_access *a = d->access;
1726   struct pci_access *acfg = a->aux;
1727   struct pci_dev *dcfg = d->aux;
1728
1729   if (!acfg)
1730     return 0;
1731
1732   if (!dcfg)
1733     d->aux = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
1734
1735   return pci_write_block(dcfg, pos, buf, len);
1736 }
1737
1738 static void
1739 win32_cfgmgr32_cleanup_dev(struct pci_dev *d)
1740 {
1741   struct pci_dev *dcfg = d->aux;
1742
1743   if (dcfg)
1744     pci_free_dev(dcfg);
1745 }
1746
1747 static void
1748 win32_cfgmgr32_init(struct pci_access *a)
1749 {
1750   char *cfgmethod = pci_get_param(a, "win32.cfgmethod");
1751   struct pci_access *acfg;
1752
1753   if (strcmp(cfgmethod, "") == 0 ||
1754       strcmp(cfgmethod, "auto") == 0)
1755     {
1756       acfg = pci_clone_access(a);
1757       acfg->method = PCI_ACCESS_AUTO;
1758     }
1759   else if (strcmp(cfgmethod, "none") == 0 ||
1760            strcmp(cfgmethod, "win32-cfgmgr32") == 0)
1761     {
1762       if (a->writeable)
1763         a->error("Write access requested but option win32.cfgmethod was not set.");
1764       return;
1765     }
1766   else
1767     {
1768       int m = pci_lookup_method(cfgmethod);
1769       if (m < 0)
1770         a->error("Option win32.cfgmethod is set to an unknown access method \"%s\".", cfgmethod);
1771       acfg = pci_clone_access(a);
1772       acfg->method = m;
1773     }
1774
1775   a->debug("Loading config space access method...\n");
1776   if (!pci_init_internal(acfg, PCI_ACCESS_WIN32_CFGMGR32))
1777     {
1778       pci_cleanup(acfg);
1779       a->debug("Cannot find any working config space access method.\n");
1780       if (a->writeable)
1781         a->error("Write access requested but no usable access method found.");
1782       return;
1783     }
1784
1785   a->aux = acfg;
1786 }
1787
1788 static void
1789 win32_cfgmgr32_cleanup(struct pci_access *a)
1790 {
1791   struct pci_access *acfg = a->aux;
1792
1793   if (acfg)
1794     pci_cleanup(acfg);
1795 }
1796
1797 struct pci_methods pm_win32_cfgmgr32 = {
1798   "win32-cfgmgr32",
1799   "Win32 device listing via Configuration Manager",
1800   win32_cfgmgr32_config,
1801   win32_cfgmgr32_detect,
1802   win32_cfgmgr32_init,
1803   win32_cfgmgr32_cleanup,
1804   win32_cfgmgr32_scan,
1805   win32_cfgmgr32_fill_info,
1806   win32_cfgmgr32_read,
1807   win32_cfgmgr32_write,
1808   NULL,                                 /* read_vpd */
1809   NULL,                                 /* init_dev */
1810   win32_cfgmgr32_cleanup_dev,
1811 };