Commit 9c953226 authored by Mikołaj Zalewski's avatar Mikołaj Zalewski Committed by Alexandre Julliard

kernel32: Implement QueryFullProcessImageFileNameW.

parent da6a94cd
......@@ -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*);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment