]> mj.ucw.cz Git - pciutils.git/commitdiff
libpci: win32-kldbg: Fix driver constructing path
authorPali Rohár <pali@kernel.org>
Thu, 17 Aug 2023 19:15:02 +0000 (21:15 +0200)
committerMartin Mares <mj@ucw.cz>
Fri, 29 Dec 2023 13:30:02 +0000 (14:30 +0100)
Get*Directory() functions have strange API. When called with zero buffer
they return length of the required buffer for storing path including
nul-term in TCHAR units (which is 1 for ANSI builds and 2 for UNICODE
builds). When called with non-zero buffer which can store full path they
return length of the path without nul-term (again in TCHAR units).

GetWindowsDirectory() function returns HOME user folder if application is
running on the Terminal Server. So this function is not suitable.

Fix calculation of path buffer for UNICODE builds and instead of usage
GetWindowsDirectory() function with concatenating "\\system32" string, use
function GetSystemDirectory() which returns path directly to system32
folder and which works correctly also on Terminal Server (per KB281316).

lib/win32-kldbg.c

index 9593a05efd22fcf9ed9a130e066d9f7b26eb94b3..c051f1a63966266681f812ca13be729eafeb5570 100644 (file)
@@ -213,7 +213,7 @@ win32_check_driver(BYTE *driver_data)
 }
 
 static int
-win32_kldbg_unpack_driver(struct pci_access *a, void *driver_path)
+win32_kldbg_unpack_driver(struct pci_access *a, LPTSTR driver_path)
 {
   BOOL use_kd_exe = FALSE;
   HMODULE exe_with_driver = NULL;
@@ -323,58 +323,34 @@ out:
 static int
 win32_kldbg_register_driver(struct pci_access *a, SC_HANDLE manager, SC_HANDLE *service)
 {
-  UINT (WINAPI *get_system_root_path)(void *buffer, UINT size) = NULL;
-  UINT systemroot_len;
-  void *driver_path;
+  UINT system32_len;
+  LPTSTR driver_path;
   HANDLE driver_handle;
-  HMODULE kernel32;
 
   /*
-   * COM library dbgeng.dll unpacks kldbg driver to file \\system32\\kldbgdrv.sys
+   * COM library dbgeng.dll unpacks kldbg driver to file "\\system32\\kldbgdrv.sys"
    * and register this driver with service name kldbgdrv. Implement same behavior.
+   * GetSystemDirectory() returns path to "\\system32" directory on all Windows versions.
    */
 
-  /*
-   * Old Windows versions return path to NT SystemRoot namespace via
-   * GetWindowsDirectory() function. New Windows versions via
-   * GetSystemWindowsDirectory(). GetSystemWindowsDirectory() is not
-   * provided in old Windows versions, so use GetProcAddress() for
-   * compatibility with all Windows versions.
-   */
-
-  kernel32 = GetModuleHandle(TEXT("kernel32.dll"));
-  if (kernel32)
-    get_system_root_path = (void *)GetProcAddress(kernel32, "GetSystemWindowsDirectory"
-#ifdef UNICODE
-      "W"
-#else
-      "A"
-#endif
-    );
-
-  if (!get_system_root_path)
-    get_system_root_path = (void *)&GetWindowsDirectory;
-
-  systemroot_len = get_system_root_path(NULL, 0);
-  if (!systemroot_len)
-    systemroot_len = sizeof(TEXT("C:\\Windows\\"));
+  system32_len = GetSystemDirectory(NULL, 0); /* Returns number of TCHARs plus 1 for nul-term. */
+  if (!system32_len)
+    system32_len = sizeof("C:\\Windows\\System32");
 
-  driver_path = pci_malloc(a, systemroot_len + sizeof(TEXT("\\system32\\kldbgdrv.sys")));
+  driver_path = pci_malloc(a, (system32_len + sizeof("\\kldbgdrv.sys")-1) * sizeof(TCHAR));
 
-  systemroot_len = get_system_root_path(driver_path, systemroot_len + sizeof(TEXT("")));
-  if (!systemroot_len)
+  system32_len = GetSystemDirectory(driver_path, system32_len); /* Now it returns number of TCHARs without nul-term. */
+  if (!system32_len)
     {
-      systemroot_len = sizeof(TEXT("C:\\Windows\\"));
-      memcpy(driver_path, TEXT("C:\\Windows\\"), systemroot_len);
+      system32_len = sizeof("C:\\Windows\\System32")-1;
+      memcpy(driver_path, TEXT("C:\\Windows\\System32"), system32_len);
     }
 
-  if (((char *)driver_path)[systemroot_len-sizeof(TEXT(""))+1] != '\\')
-    {
-      ((char *)driver_path)[systemroot_len-sizeof(TEXT(""))+1] = '\\';
-      systemroot_len += sizeof(TEXT(""));
-    }
+  /* GetSystemDirectory returns path without backslash unless the system directory is the root directory. */
+  if (driver_path[system32_len-1] != '\\')
+    driver_path[system32_len++] = '\\';
 
-  memcpy((char *)driver_path + systemroot_len, TEXT("system32\\kldbgdrv.sys"), sizeof(TEXT("system32\\kldbgdrv.sys")));
+  memcpy(driver_path + system32_len, TEXT("kldbgdrv.sys"), sizeof(TEXT("kldbgdrv.sys")));
 
   driver_handle = CreateFile(driver_path, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
   if (driver_handle != INVALID_HANDLE_VALUE)