]> mj.ucw.cz Git - pciutils.git/blobdiff - lib/win32-cfgmgr32.c
libpci: Do not build physmem-posix.c when not needed
[pciutils.git] / lib / win32-cfgmgr32.c
index 6a268856417785956557338cb4fee83d84c49ac2..a001187901486ec88fe559d63d93d94739f22d9b 100644 (file)
@@ -17,6 +17,7 @@
 #include <wchar.h> /* for wcslen(), wcscpy() */
 
 #include "internal.h"
+#include "win32-helpers.h"
 
 /* Unfortunately MinGW32 toolchain does not provide these cfgmgr32 constants. */
 
@@ -213,32 +214,6 @@ cr_strerror(CONFIGRET cr_error_id)
   return cr_errors[cr_error_id];
 }
 
-static const char *
-win32_strerror(DWORD win32_error_id)
-{
-  /*
-   * Use static buffer which is large enough.
-   * Hopefully no Win32 API error message string is longer than 4 kB.
-   */
-  static char buffer[4096];
-  DWORD len;
-
-  len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, win32_error_id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, sizeof(buffer), NULL);
-
-  /* FormatMessage() automatically appends ".\r\n" to the error message. */
-  if (len && buffer[len-1] == '\n')
-    buffer[--len] = '\0';
-  if (len && buffer[len-1] == '\r')
-    buffer[--len] = '\0';
-  if (len && buffer[len-1] == '.')
-    buffer[--len] = '\0';
-
-  if (!len)
-    sprintf(buffer, "Unknown Win32 error %lu", win32_error_id);
-
-  return buffer;
-}
-
 static int
 fmt_validate(const char *s, int len, const char *fmt)
 {
@@ -267,56 +242,6 @@ seq_xdigit_validate(const char *s, int mult, int min)
   return 1;
 }
 
-static BOOL
-is_non_nt_system(void)
-{
-  OSVERSIONINFOA version;
-  version.dwOSVersionInfoSize = sizeof(version);
-  return GetVersionExA(&version) && version.dwPlatformId < VER_PLATFORM_WIN32_NT;
-}
-
-static BOOL
-is_32bit_on_win8_64bit_system(void)
-{
-#ifdef _WIN64
-  return FALSE;
-#else
-  BOOL (WINAPI *MyIsWow64Process)(HANDLE, PBOOL);
-  OSVERSIONINFOA version;
-  HMODULE kernel32;
-  BOOL is_wow64;
-
-  /* Check for Windows 8 (NT 6.2). */
-  version.dwOSVersionInfoSize = sizeof(version);
-  if (!GetVersionExA(&version) ||
-      version.dwPlatformId != VER_PLATFORM_WIN32_NT ||
-      version.dwMajorVersion < 6 ||
-      (version.dwMajorVersion == 6 && version.dwMinorVersion < 2))
-    return FALSE;
-
-  /*
-   * Check for 64-bit system via IsWow64Process() function exported
-   * from 32-bit kernel32.dll library available on the 64-bit systems.
-   * Resolve pointer to this function at runtime as this code path is
-   * primary running on 32-bit systems where are not available 64-bit
-   * functions.
-   */
-
-  kernel32 = GetModuleHandleA("kernel32.dll");
-  if (!kernel32)
-    return FALSE;
-
-  MyIsWow64Process = (void *)GetProcAddress(kernel32, "IsWow64Process");
-  if (!MyIsWow64Process)
-    return FALSE;
-
-  if (!MyIsWow64Process(GetCurrentProcess(), &is_wow64))
-    return FALSE;
-
-  return is_wow64;
-#endif
-}
-
 static LPWSTR
 get_device_service_name(struct pci_access *a, DEVINST devinst, DEVINSTID_A devinst_id, BOOL *supported)
 {
@@ -403,9 +328,12 @@ get_driver_path_for_service(struct pci_access *a, LPCWSTR service_name, SC_HANDL
   SERVICE_STATUS service_status;
   SC_HANDLE service = NULL;
   char *driver_path = NULL;
+  int trim_system32 = 0;
   UINT systemroot_len;
   int driver_path_len;
+  UINT system32_len;
   HMODULE kernel32;
+  WCHAR *trim_ptr;
   DWORD error;
 
   service = OpenServiceW(manager, service_name, SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS);
@@ -466,36 +394,42 @@ retry_service_config:
    */
 
   /*
-   * Old Windows versions return path to NT SystemRoot namespace via
-   * GetWindowsDirectoryW() function. New Windows versions via
-   * GetSystemWindowsDirectoryW(). GetSystemWindowsDirectoryW() is not
-   * provided in old Windows versions, so use GetProcAddress() for
-   * compatibility with all Windows versions.
+   * GetSystemWindowsDirectoryW() returns path to NT SystemRoot namespace.
+   * Alternativelly path to NT SystemRoot namespace can be constructed by
+   * GetSystemDirectoryW() by trimming "\\system32" from the end of path.
+   * GetSystemWindowsDirectoryW() is not provided in old Windows versions,
+   * so use GetProcAddress() for compatibility with all Windows versions.
    */
   kernel32 = GetModuleHandleW(L"kernel32.dll");
   if (kernel32)
     get_system_root_path = (void *)GetProcAddress(kernel32, "GetSystemWindowsDirectoryW");
-  if (!get_system_root_path)
-    get_system_root_path = &GetWindowsDirectoryW;
-
-  systemroot_len = get_system_root_path(NULL, 0);
+  else
+    {
+      get_system_root_path = &GetSystemDirectoryW;
+      trim_system32 = 1;
+    }
 
   if (!service_config->lpBinaryPathName || !service_config->lpBinaryPathName[0])
     {
-      /* No ImagePath is specified, NT kernel assumes implicit kernel driver path by service name. */
-      service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + sizeof("\\System32\\drivers\\")-1 + wcslen(service_name) + sizeof(".sys")-1 + 1));
-      systemroot_len = get_system_root_path(service_image_path, systemroot_len+1);
-      if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
-        service_image_path[systemroot_len++] = L'\\';
-      wcscpy(service_image_path + systemroot_len, L"System32\\drivers\\");
-      wcscpy(service_image_path + systemroot_len + sizeof("System32\\drivers\\")-1, service_name);
-      wcscpy(service_image_path + systemroot_len + sizeof("System32\\drivers\\")-1 + wcslen(service_name), L".sys");
+      /* No ImagePath is specified, NT kernel assumes implicit kernel driver path by service name, which is relative to "\\system32\\drivers". */
+      /* GetSystemDirectoryW() returns path to "\\system32" directory on all Windows versions. */
+      system32_len = GetSystemDirectoryW(NULL, 0); /* Returns number of WCHARs plus 1 for nul-term. */
+      service_image_path = pci_malloc(a, sizeof(WCHAR) * (system32_len + sizeof("\\drivers\\")-1 + wcslen(service_name) + sizeof(".sys")-1));
+      system32_len = GetSystemDirectoryW(service_image_path, system32_len); /* Now it returns number of WCHARs without nul-term. */
+      if (system32_len && service_image_path[system32_len-1] != L'\\')
+        service_image_path[system32_len++] = L'\\';
+      wcscpy(service_image_path + system32_len, L"drivers\\");
+      wcscpy(service_image_path + system32_len + sizeof("drivers\\")-1, service_name);
+      wcscpy(service_image_path + system32_len + sizeof("drivers\\")-1 + wcslen(service_name), L".sys");
     }
   else if (wcsncmp(service_config->lpBinaryPathName, L"\\SystemRoot\\", sizeof("\\SystemRoot\\")-1) == 0)
     {
-      /* ImagePath is in NT SystemRoot namespace, convert to Win32 path via GetSystemWindowsDirectoryW()/GetWindowsDirectoryW(). */
+      /* ImagePath is in NT SystemRoot namespace, convert to Win32 path via GetSystemWindowsDirectoryW()/GetSystemDirectoryW(). */
+      systemroot_len = get_system_root_path(NULL, 0); /* Returns number of WCHARs plus 1 for nul-term. */
       service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + wcslen(service_config->lpBinaryPathName) - (sizeof("\\SystemRoot")-1)));
-      systemroot_len = get_system_root_path(service_image_path, systemroot_len+1);
+      systemroot_len = get_system_root_path(service_image_path, systemroot_len); /* Now it returns number of WCHARs without nul-term. */
+      if (trim_system32 && systemroot_len && (trim_ptr = wcsrchr(service_image_path, L'\\')) != NULL)
+        systemroot_len = trim_ptr - service_image_path;
       if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
         service_image_path[systemroot_len++] = L'\\';
       wcscpy(service_image_path + systemroot_len, service_config->lpBinaryPathName + sizeof("\\SystemRoot\\")-1);
@@ -525,9 +459,12 @@ retry_service_config:
     }
   else if (service_config->lpBinaryPathName[0] != L'\\')
     {
-      /* ImagePath is relative to the NT SystemRoot namespace, convert to Win32 path via GetSystemWindowsDirectoryW()/GetWindowsDirectoryW(). */
-      service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + sizeof("\\") + wcslen(service_config->lpBinaryPathName)));
-      systemroot_len = get_system_root_path(service_image_path, systemroot_len+1);
+      /* ImagePath is relative to the NT SystemRoot namespace, convert to Win32 path via GetSystemWindowsDirectoryW()/GetSystemDirectoryW(). */
+      systemroot_len = get_system_root_path(NULL, 0); /* Returns number of WCHARs plus 1 for nul-term. */
+      service_image_path = pci_malloc(a, sizeof(WCHAR) * (systemroot_len + sizeof("\\")-1 + wcslen(service_config->lpBinaryPathName)));
+      systemroot_len = get_system_root_path(service_image_path, systemroot_len); /* Now it returns number of WCHARs without nul-term. */
+      if (trim_system32 && systemroot_len && (trim_ptr = wcsrchr(service_image_path, L'\\')) != NULL)
+        systemroot_len = trim_ptr - service_image_path;
       if (systemroot_len && service_image_path[systemroot_len-1] != L'\\')
         service_image_path[systemroot_len++] = L'\\';
       wcscpy(service_image_path + systemroot_len, service_config->lpBinaryPathName);
@@ -821,7 +758,7 @@ get_device_driver_path(struct pci_dev *d, SC_HANDLE manager, BOOL manager_suppor
   LPWSTR service_name = NULL;
   ULONG devinst_id_len = 0;
   char *driver_path = NULL;
-  DEVINST devinst = (DEVINST)d->aux;
+  DEVINST devinst = (DEVINST)d->backend_data;
   ULONG problem = 0;
   ULONG status = 0;
   HKEY key = NULL;
@@ -983,7 +920,7 @@ fill_resources(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
        * application using the hardware resource APIs. For example: An AMD64
        * application for AMD64 systems.
        */
-      if (cr == CR_CALL_NOT_IMPLEMENTED && is_32bit_on_win8_64bit_system())
+      if (cr == CR_CALL_NOT_IMPLEMENTED && win32_is_32bit_on_win8_64bit_system())
         {
           static BOOL warn_once = FALSE;
           if (!warn_once)
@@ -998,7 +935,7 @@ fill_resources(struct pci_dev *d, DEVINST devinst, DEVINSTID_A devinst_id)
     }
 
   bar_res_count = 0;
-  non_nt_system = is_non_nt_system();
+  non_nt_system = win32_is_non_nt_system();
 
   is_bar_res = TRUE;
   if (non_nt_system)
@@ -1553,9 +1490,9 @@ scan_devinst_id(struct pci_access *a, DEVINSTID_A devinst_id)
 
   d = pci_get_dev(a, domain, bus, dev, func);
   pci_link_dev(a, d);
-  if (!d->access->aux)
+  if (!d->access->backend_data)
     d->no_config_access = 1;
-  d->aux = (void *)devinst;
+  d->backend_data = (void *)devinst;
 
   /* Parse device id part of devinst id and fill details into pci_dev. */
   if (!a->buscentric)
@@ -1569,7 +1506,7 @@ scan_devinst_id(struct pci_access *a, DEVINSTID_A devinst_id)
     fill_resources(d, devinst, devinst_id);
 
   /*
-   * Set parent field to cfgmgr32 parent devinst handle and aux field to current
+   * Set parent field to cfgmgr32 parent devinst handle and backend_data field to current
    * devinst handle. At later stage in win32_cfgmgr32_scan() when all pci_dev
    * devices are linked, change every devinst handle by pci_dev.
    */
@@ -1641,7 +1578,7 @@ win32_cfgmgr32_scan(struct pci_access *a)
       for (d1 = a->devices; d1; d1 = d1->next)
         {
           for (d2 = a->devices; d2; d2 = d2->next)
-            if ((DEVINST)d1->parent == (DEVINST)d2->aux)
+            if ((DEVINST)d1->parent == (DEVINST)d2->backend_data)
               break;
           d1->parent = d2;
           if (d1->parent)
@@ -1649,9 +1586,9 @@ win32_cfgmgr32_scan(struct pci_access *a)
         }
     }
 
-  /* devinst stored in ->aux is not needed anymore, clear it. */
+  /* devinst stored in ->backend_data is not needed anymore, clear it. */
   for (d = a->devices; d; d = d->next)
-    d->aux = NULL;
+    d->backend_data = NULL;
 
   pci_mfree(devinst_id_list);
 }
@@ -1701,7 +1638,7 @@ win32_cfgmgr32_fill_info(struct pci_dev *d, unsigned int flags)
    * All available flags were filled by win32_cfgmgr32_scan().
    * Filling more flags is possible only from config space.
    */
-  if (!d->access->aux)
+  if (!d->access->backend_data)
     return;
 
   pci_generic_fill_info(d, flags);
@@ -1711,14 +1648,14 @@ static int
 win32_cfgmgr32_read(struct pci_dev *d, int pos, byte *buf, int len)
 {
   struct pci_access *a = d->access;
-  struct pci_access *acfg = a->aux;
-  struct pci_dev *dcfg = d->aux;
+  struct pci_access *acfg = a->backend_data;
+  struct pci_dev *dcfg = d->backend_data;
 
   if (!acfg)
     return pci_emulated_read(d, pos, buf, len);
 
   if (!dcfg)
-    d->aux = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
+    d->backend_data = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
 
   return pci_read_block(dcfg, pos, buf, len);
 }
@@ -1727,14 +1664,14 @@ static int
 win32_cfgmgr32_write(struct pci_dev *d, int pos, byte *buf, int len)
 {
   struct pci_access *a = d->access;
-  struct pci_access *acfg = a->aux;
-  struct pci_dev *dcfg = d->aux;
+  struct pci_access *acfg = a->backend_data;
+  struct pci_dev *dcfg = d->backend_data;
 
   if (!acfg)
     return 0;
 
   if (!dcfg)
-    d->aux = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
+    d->backend_data = dcfg = pci_get_dev(acfg, d->domain, d->bus, d->dev, d->func);
 
   return pci_write_block(dcfg, pos, buf, len);
 }
@@ -1742,7 +1679,7 @@ win32_cfgmgr32_write(struct pci_dev *d, int pos, byte *buf, int len)
 static void
 win32_cfgmgr32_cleanup_dev(struct pci_dev *d)
 {
-  struct pci_dev *dcfg = d->aux;
+  struct pci_dev *dcfg = d->backend_data;
 
   if (dcfg)
     pci_free_dev(dcfg);
@@ -1786,13 +1723,13 @@ win32_cfgmgr32_init(struct pci_access *a)
       return;
     }
 
-  a->aux = acfg;
+  a->backend_data = acfg;
 }
 
 static void
 win32_cfgmgr32_cleanup(struct pci_access *a)
 {
-  struct pci_access *acfg = a->aux;
+  struct pci_access *acfg = a->backend_data;
 
   if (acfg)
     pci_cleanup(acfg);