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