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