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