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