#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)
{
* function conflicts with some MSVC intrinsic.
* MSVC supports inline assembly via __asm keyword in 32-bit mode only.
* GCC version 4.9.0 and higher provides __builtin_ia32_readeflags_uXX()
- * builtin for XX-mode.
+ * builtin for XX-mode. This builtin is also available as __readeflags()
+ * function indirectly via <x86intrin.h> header file.
*/
#if defined(_MSC_VER) && (_MSC_VER >= 1500 || (_MSC_VER >= 1400 && defined(__BUILDMACHINE__)))
#pragma intrinsic(__readeflags)
#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 9) || (__GNUC__ > 4))
-#ifdef __x86_64__
-#define __readeflags() __builtin_ia32_readeflags_u64()
-#else
-#define __readeflags() __builtin_ia32_readeflags_u32()
-#endif
+#include <x86intrin.h>
#elif defined(_MSC_VER) && defined(_M_IX86)
static inline unsigned int
__readeflags(void)
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;
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);
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)
/* On NT-based systems issue ProcessUserModeIOPL syscall which changes IOPL to 3. */
if (!SetProcessUserModeIOPL())
{
- a->warning("NT ProcessUserModeIOPL call failed with error: %lu.", (unsigned long int)GetLastError());
+ DWORD error = GetLastError();
+ a->debug("NT ProcessUserModeIOPL call failed: %s.", error == ERROR_INVALID_FUNCTION ? "Not Implemented" : error == ERROR_PRIVILEGE_NOT_HELD ? "Access Denied" : "Operation Failed");
return 0;
}