kernel32: Implement QueryFullProcessImageFileNameW.
This commit is contained in:
parent
da6a94cd96
commit
9c9532265d
|
@ -865,6 +865,8 @@
|
|||
@ stdcall QueryDepthSList(ptr) ntdll.RtlQueryDepthSList
|
||||
@ stdcall QueryDosDeviceA(str ptr long)
|
||||
@ stdcall QueryDosDeviceW(wstr ptr long)
|
||||
@ stub QueryFullProcessImageNameA
|
||||
@ stdcall QueryFullProcessImageNameW(ptr long wstr ptr)
|
||||
@ stdcall QueryInformationJobObject(long long ptr long ptr)
|
||||
# @ stub QueryMemoryResourceNotification
|
||||
@ stub QueryNumberOfEventLogRecords
|
||||
|
|
|
@ -3110,6 +3110,59 @@ BOOL WINAPI GetProcessHandleCount(HANDLE hProcess, DWORD *cnt)
|
|||
return !status;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* QueryFullProcessImageNameW (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI QueryFullProcessImageNameW(HANDLE hProcess, DWORD dwFlags, LPWSTR lpExeName, PDWORD pdwSize)
|
||||
{
|
||||
BYTE buffer[sizeof(UNICODE_STRING) + MAX_PATH*sizeof(WCHAR)]; /* this buffer should be enough */
|
||||
UNICODE_STRING *dynamic_buffer = NULL;
|
||||
UNICODE_STRING nt_path;
|
||||
UNICODE_STRING *result = NULL;
|
||||
NTSTATUS status;
|
||||
DWORD needed;
|
||||
|
||||
RtlInitUnicodeStringEx(&nt_path, NULL);
|
||||
/* FIXME: On Windows, ProcessImageFileName return an NT path. We rely that it being a DOS path,
|
||||
* as this is on Wine. */
|
||||
status = NtQueryInformationProcess(hProcess, ProcessImageFileName, buffer, sizeof(buffer), &needed);
|
||||
if (status == STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
dynamic_buffer = HeapAlloc(GetProcessHeap(), 0, needed);
|
||||
status = NtQueryInformationProcess(hProcess, ProcessImageFileName, (LPBYTE)dynamic_buffer, needed, &needed);
|
||||
result = dynamic_buffer;
|
||||
}
|
||||
else
|
||||
result = (PUNICODE_STRING)buffer;
|
||||
|
||||
if (status) goto cleanup;
|
||||
|
||||
if (dwFlags & PROCESS_NAME_NATIVE)
|
||||
{
|
||||
if (!RtlDosPathNameToNtPathName_U(result->Buffer, &nt_path, NULL, NULL))
|
||||
{
|
||||
status = STATUS_OBJECT_PATH_NOT_FOUND;
|
||||
goto cleanup;
|
||||
}
|
||||
result = &nt_path;
|
||||
}
|
||||
|
||||
if (result->Length/sizeof(WCHAR) + 1 > *pdwSize)
|
||||
{
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
lstrcpynW(lpExeName, result->Buffer, result->Length/sizeof(WCHAR) + 1);
|
||||
*pdwSize = result->Length/sizeof(WCHAR);
|
||||
|
||||
cleanup:
|
||||
HeapFree(GetProcessHeap(), 0, dynamic_buffer);
|
||||
RtlFreeUnicodeString(&nt_path);
|
||||
if (status) SetLastError( RtlNtStatusToDosError(status) );
|
||||
return !status;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ProcessIdToSessionId (KERNEL32.@)
|
||||
* This function is available on Terminal Server 4SP4 and Windows 2000
|
||||
|
|
|
@ -35,9 +35,40 @@
|
|||
|
||||
#include "wine/test.h"
|
||||
|
||||
#define expect_eq_d(expected, actual) \
|
||||
do { \
|
||||
int value = (actual); \
|
||||
ok((expected) == value, "Expected " #actual " to be %d (" #expected ") is %d\n", \
|
||||
(expected), value); \
|
||||
} while (0)
|
||||
#define expect_eq_ws_i(expected, actual) \
|
||||
do { \
|
||||
LPCWSTR value = (actual); \
|
||||
ok(lstrcmpiW((expected), value) == 0, "Expected " #actual " to be L\"%s\" (" #expected ") is L\"%s\"\n", \
|
||||
wine_dbgstr_w(expected), wine_dbgstr_w(value)); \
|
||||
} while (0)
|
||||
|
||||
/* A simpler version of wine_dbgstr_w. Note that the returned buffer will be
|
||||
* invalid after 16 calls to this funciton. */
|
||||
static const char *wine_dbgstr_w(LPCWSTR wstr)
|
||||
{
|
||||
static char *buffers[16];
|
||||
static int curr_buffer = 0;
|
||||
|
||||
int size;
|
||||
|
||||
curr_buffer = (curr_buffer + 1) % 16;
|
||||
HeapFree(GetProcessHeap(), 0, buffers[curr_buffer]);
|
||||
size = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
|
||||
buffers[curr_buffer] = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
size = WideCharToMultiByte(CP_ACP, 0, wstr, -1, buffers[curr_buffer], size, NULL, NULL);
|
||||
return buffers[curr_buffer];
|
||||
}
|
||||
|
||||
static HINSTANCE hkernel32;
|
||||
static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
|
||||
static BOOL (WINAPI *pVirtualFreeEx)(HANDLE, LPVOID, SIZE_T, DWORD);
|
||||
static BOOL (WINAPI *pQueryFullProcessImageNameW)(HANDLE hProcess, DWORD dwFlags, LPWSTR lpExeName, PDWORD lpdwSize);
|
||||
|
||||
/* ############################### */
|
||||
static char base[MAX_PATH];
|
||||
|
@ -175,6 +206,7 @@ static int init(void)
|
|||
hkernel32 = GetModuleHandleA("kernel32");
|
||||
pVirtualAllocEx = (void *) GetProcAddress(hkernel32, "VirtualAllocEx");
|
||||
pVirtualFreeEx = (void *) GetProcAddress(hkernel32, "VirtualFreeEx");
|
||||
pQueryFullProcessImageNameW = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameW");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1520,6 +1552,76 @@ static void test_GetProcessVersion(void)
|
|||
CloseHandle(pi.hThread);
|
||||
}
|
||||
|
||||
static void test_ProcessName(void)
|
||||
{
|
||||
HANDLE hSelf;
|
||||
WCHAR module_name[1024];
|
||||
WCHAR deviceW[] = {'\\','D', 'e','v','i','c','e',0};
|
||||
WCHAR buf[1024];
|
||||
DWORD size;
|
||||
|
||||
if (!pQueryFullProcessImageNameW)
|
||||
{
|
||||
win_skip("QueryFullProcessImageNameW unavailable (added in Windows Vista)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ok(GetModuleFileNameW(NULL, module_name, 1024), "GetModuleFileNameW(NULL, ...) failed\n");
|
||||
|
||||
/* GetCurrentProcess pseudo-handle */
|
||||
size = sizeof(buf) / sizeof(buf[0]);
|
||||
expect_eq_d(TRUE, pQueryFullProcessImageNameW(GetCurrentProcess(), 0, buf, &size));
|
||||
expect_eq_d(lstrlenW(buf), size);
|
||||
expect_eq_ws_i(buf, module_name);
|
||||
|
||||
hSelf = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
|
||||
/* Real handle */
|
||||
size = sizeof(buf) / sizeof(buf[0]);
|
||||
expect_eq_d(TRUE, pQueryFullProcessImageNameW(hSelf, 0, buf, &size));
|
||||
expect_eq_d(lstrlenW(buf), size);
|
||||
expect_eq_ws_i(buf, module_name);
|
||||
|
||||
/* Buffer too small */
|
||||
size = lstrlenW(module_name)/2;
|
||||
lstrcpyW(buf, deviceW);
|
||||
SetLastError(0xdeadbeef);
|
||||
expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, 0, buf, &size));
|
||||
expect_eq_d(lstrlenW(module_name)/2, size); /* size not changed(!) */
|
||||
expect_eq_d(ERROR_INSUFFICIENT_BUFFER, GetLastError());
|
||||
expect_eq_ws_i(deviceW, buf); /* buffer not changed */
|
||||
|
||||
/* Too small - not space for NUL terminator */
|
||||
size = lstrlenW(module_name);
|
||||
SetLastError(0xdeadbeef);
|
||||
expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, 0, buf, &size));
|
||||
expect_eq_d(lstrlenW(module_name), size); /* size not changed(!) */
|
||||
expect_eq_d(ERROR_INSUFFICIENT_BUFFER, GetLastError());
|
||||
|
||||
/* NULL buffer */
|
||||
size = 0;
|
||||
expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, 0, NULL, &size));
|
||||
expect_eq_d(0, size);
|
||||
expect_eq_d(ERROR_INSUFFICIENT_BUFFER, GetLastError());
|
||||
|
||||
/* native path */
|
||||
size = sizeof(buf) / sizeof(buf[0]);
|
||||
expect_eq_d(TRUE, pQueryFullProcessImageNameW(hSelf, PROCESS_NAME_NATIVE, buf, &size));
|
||||
expect_eq_d(lstrlenW(buf), size);
|
||||
ok(buf[0] == '\\', "NT path should begin with '\\'\n");
|
||||
todo_wine ok(memcmp(buf, deviceW, sizeof(WCHAR)*lstrlenW(deviceW)) == 0, "NT path should begin with \\Device\n");
|
||||
|
||||
/* Buffer too small */
|
||||
size = lstrlenW(module_name)/2;
|
||||
SetLastError(0xdeadbeef);
|
||||
lstrcpyW(buf, module_name);
|
||||
expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, 0, buf, &size));
|
||||
expect_eq_d(lstrlenW(module_name)/2, size); /* size not changed(!) */
|
||||
expect_eq_d(ERROR_INSUFFICIENT_BUFFER, GetLastError());
|
||||
expect_eq_ws_i(module_name, buf); /* buffer not changed */
|
||||
|
||||
CloseHandle(hSelf);
|
||||
}
|
||||
|
||||
static void test_Handles(void)
|
||||
{
|
||||
HANDLE handle = GetCurrentProcess();
|
||||
|
@ -1573,6 +1675,7 @@ START_TEST(process)
|
|||
test_ExitCode();
|
||||
test_OpenProcess();
|
||||
test_GetProcessVersion();
|
||||
test_ProcessName();
|
||||
test_Handles();
|
||||
/* things that can be tested:
|
||||
* lookup: check the way program to be executed is searched
|
||||
|
|
|
@ -313,6 +313,8 @@ NTSTATUS WINAPI NtQueryInformationProcess(
|
|||
else ret = STATUS_INFO_LENGTH_MISMATCH;
|
||||
break;
|
||||
case ProcessImageFileName:
|
||||
/* FIXME: this will return a DOS path. Windows returns an NT path. Changing this would require also changing kernel32.QueryFullProcessImageName.
|
||||
* The latter may be harder because of the lack of RtlNtPathNameToDosPathName. */
|
||||
SERVER_START_REQ(get_dll_info)
|
||||
{
|
||||
UNICODE_STRING *image_file_name_str = ProcessInformation;
|
||||
|
|
|
@ -818,6 +818,7 @@ static void test_query_process_image_file_name(void)
|
|||
file_nameA[len] = '\0';
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
trace("process image file name: %s\n", file_nameA);
|
||||
todo_wine ok(strncmp(file_nameA, "\\Device\\", 8) == 0, "Process image name should be an NT path beginning with \\Device\\ (is %s)", file_nameA);
|
||||
HeapFree(GetProcessHeap(), 0, file_nameA);
|
||||
}
|
||||
|
||||
|
|
|
@ -1181,6 +1181,8 @@ typedef struct tagCOMMTIMEOUTS {
|
|||
#define SET_TAPE_MEDIA_INFORMATION 0
|
||||
#define SET_TAPE_DRIVE_INFORMATION 1
|
||||
|
||||
#define PROCESS_NAME_NATIVE 1
|
||||
|
||||
typedef void (CALLBACK *PAPCFUNC)(ULONG_PTR);
|
||||
typedef void (CALLBACK *PTIMERAPCROUTINE)(LPVOID,DWORD,DWORD);
|
||||
|
||||
|
@ -1962,6 +1964,9 @@ WINBASEAPI USHORT WINAPI QueryDepthSList(PSLIST_HEADER);
|
|||
WINBASEAPI DWORD WINAPI QueryDosDeviceA(LPCSTR,LPSTR,DWORD);
|
||||
WINBASEAPI DWORD WINAPI QueryDosDeviceW(LPCWSTR,LPWSTR,DWORD);
|
||||
#define QueryDosDevice WINELIB_NAME_AW(QueryDosDevice)
|
||||
WINBASEAPI BOOL WINAPI QueryFullProcessImageNameA(HANDLE,DWORD,LPSTR,PDWORD);
|
||||
WINBASEAPI BOOL WINAPI QueryFullProcessImageNameW(HANDLE,DWORD,LPWSTR,PDWORD);
|
||||
#define QueryFullProcessImageName WINELIB_NAME_AW(QueryFullProcessImageName)
|
||||
WINBASEAPI BOOL WINAPI QueryInformationJobObject(HANDLE,JOBOBJECTINFOCLASS,LPVOID,DWORD,DWORD*);
|
||||
WINBASEAPI BOOL WINAPI QueryPerformanceCounter(LARGE_INTEGER*);
|
||||
WINBASEAPI BOOL WINAPI QueryPerformanceFrequency(LARGE_INTEGER*);
|
||||
|
|
Loading…
Reference in New Issue