]> mj.ucw.cz Git - pciutils.git/blobdiff - lib/i386-io-windows.h
cxl: Rename caps to be device caps
[pciutils.git] / lib / i386-io-windows.h
index 772c6f26f791af151e1a50edfcffd5ed59f83596..ac2a55dfb7ba337f41cf712de86c3dcfc69a167e 100644 (file)
 #define _inp(x) __inbyte(x)
 #define _inpw(x) __inword(x)
 #define _inpd(x) __indword(x)
-#elif defined(__CRTDLL__)
+#elif defined(__CRTDLL__) || (defined(__MSVCRT_VERSION__) && __MSVCRT_VERSION__ < 0x400)
 /*
- * Old CRTDLL library does not provide I/O port functions. Even it is the oldest
- * CRT library it exists also in 64-bit variant. Implement I/O port functions
- * via inline assembly just for 32-bit mode as 64-bit mode uses above <intrin.h>
- * header.
+ * Old 32-bit CRTDLL library and pre-4.00 MSVCRT library do not provide I/O
+ * port functions. As these libraries exist only in 32-bit mode variant,
+ * implement I/O port functions via 32-bit inline assembly.
  */
 static inline int _outp(unsigned short port, int databyte)
 {
@@ -777,10 +776,13 @@ find_and_open_process_for_query(LPCSTR exe_file)
   EnumProcessesProt MyEnumProcesses;
   HMODULE kernel32, psapi;
   UINT prev_error_mode;
-  WCHAR path[MAX_PATH];
+  DWORD partial_retry;
+  BOOL found_process;
   DWORD size, length;
   DWORD *processes;
   HANDLE process;
+  LPWSTR path;
+  DWORD error;
   DWORD count;
   DWORD i;
 
@@ -874,11 +876,72 @@ retry:
       if (!process)
         continue;
 
+      /*
+       * Set initial buffer size to 256 (wide) characters.
+       * Final path length on the modern NT-based systems can be also larger.
+       */
+      size = 256;
+      found_process = FALSE;
+      partial_retry = 0;
+
+retry_path:
+      path = (LPWSTR)LocalAlloc(LPTR, size * sizeof(*path));
+      if (!path)
+        goto end_path;
+
       if (MyGetProcessImageFileNameW)
-        length = MyGetProcessImageFileNameW(process, path, sizeof(path)/sizeof(*path));
+        length = MyGetProcessImageFileNameW(process, path, size);
       else
-        length = MyGetModuleFileNameExW(process, NULL, path, sizeof(path)/sizeof(*path));
+        length = MyGetModuleFileNameExW(process, NULL, path, size);
+
+      error = GetLastError();
+
+      /*
+       * GetModuleFileNameEx() returns zero and signal error ERROR_PARTIAL_COPY
+       * when remote process is in the middle of updating its module table.
+       * Sleep 10 ms and try again, max 10 attempts.
+       */
+      if (!MyGetProcessImageFileNameW)
+        {
+          if (length == 0 && error == ERROR_PARTIAL_COPY && partial_retry++ < 10)
+            {
+              Sleep(10);
+              goto retry_path;
+            }
+          partial_retry = 0;
+        }
+
+      /*
+       * When buffer is too small then function GetModuleFileNameEx() returns
+       * its size argument on older systems (Windows XP) or its size minus
+       * argument one on new systems (Windows 10) without signalling any error.
+       * Function GetProcessImageFileNameW() on the other hand returns zero
+       * value and signals error ERROR_INSUFFICIENT_BUFFER. So in all these
+       * cases call function again with larger buffer.
+       */
+
+      if (MyGetProcessImageFileNameW && length == 0 && error != ERROR_INSUFFICIENT_BUFFER)
+        goto end_path;
+
+      if ((MyGetProcessImageFileNameW && length == 0) ||
+          (!MyGetProcessImageFileNameW && (length == size || length == size-1)))
+        {
+          LocalFree(path);
+          size *= 2;
+          goto retry_path;
+        }
+
       if (length && check_process_name(path, length, exe_file))
+        found_process = TRUE;
+
+end_path:
+      if (path)
+        {
+          LocalFree(path);
+          path = NULL;
+        }
+
+      if (found_process)
         break;
 
       CloseHandle(process);
@@ -1031,6 +1094,7 @@ SetProcessUserModeIOPL(VOID)
   impersonate_privilege_enabled = FALSE;
   revert_to_old_token = FALSE;
   lsass_token = NULL;
+  old_token = NULL;
 
   /* Fast path when ProcessUserModeIOPL was already called. */
   if (read_iopl() == 3)