kernel32: Implement QueryFullProcessImageFileNameW.
This commit is contained in:
parent
da6a94cd96
commit
9c9532265d
|
@ -865,6 +865,8 @@
|
||||||
@ stdcall QueryDepthSList(ptr) ntdll.RtlQueryDepthSList
|
@ stdcall QueryDepthSList(ptr) ntdll.RtlQueryDepthSList
|
||||||
@ stdcall QueryDosDeviceA(str ptr long)
|
@ stdcall QueryDosDeviceA(str ptr long)
|
||||||
@ stdcall QueryDosDeviceW(wstr ptr long)
|
@ stdcall QueryDosDeviceW(wstr ptr long)
|
||||||
|
@ stub QueryFullProcessImageNameA
|
||||||
|
@ stdcall QueryFullProcessImageNameW(ptr long wstr ptr)
|
||||||
@ stdcall QueryInformationJobObject(long long ptr long ptr)
|
@ stdcall QueryInformationJobObject(long long ptr long ptr)
|
||||||
# @ stub QueryMemoryResourceNotification
|
# @ stub QueryMemoryResourceNotification
|
||||||
@ stub QueryNumberOfEventLogRecords
|
@ stub QueryNumberOfEventLogRecords
|
||||||
|
|
|
@ -3110,6 +3110,59 @@ BOOL WINAPI GetProcessHandleCount(HANDLE hProcess, DWORD *cnt)
|
||||||
return !status;
|
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.@)
|
* ProcessIdToSessionId (KERNEL32.@)
|
||||||
* This function is available on Terminal Server 4SP4 and Windows 2000
|
* This function is available on Terminal Server 4SP4 and Windows 2000
|
||||||
|
|
|
@ -35,9 +35,40 @@
|
||||||
|
|
||||||
#include "wine/test.h"
|
#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 HINSTANCE hkernel32;
|
||||||
static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
|
static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
|
||||||
static BOOL (WINAPI *pVirtualFreeEx)(HANDLE, LPVOID, SIZE_T, 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];
|
static char base[MAX_PATH];
|
||||||
|
@ -175,6 +206,7 @@ static int init(void)
|
||||||
hkernel32 = GetModuleHandleA("kernel32");
|
hkernel32 = GetModuleHandleA("kernel32");
|
||||||
pVirtualAllocEx = (void *) GetProcAddress(hkernel32, "VirtualAllocEx");
|
pVirtualAllocEx = (void *) GetProcAddress(hkernel32, "VirtualAllocEx");
|
||||||
pVirtualFreeEx = (void *) GetProcAddress(hkernel32, "VirtualFreeEx");
|
pVirtualFreeEx = (void *) GetProcAddress(hkernel32, "VirtualFreeEx");
|
||||||
|
pQueryFullProcessImageNameW = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameW");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1520,6 +1552,76 @@ static void test_GetProcessVersion(void)
|
||||||
CloseHandle(pi.hThread);
|
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)
|
static void test_Handles(void)
|
||||||
{
|
{
|
||||||
HANDLE handle = GetCurrentProcess();
|
HANDLE handle = GetCurrentProcess();
|
||||||
|
@ -1573,6 +1675,7 @@ START_TEST(process)
|
||||||
test_ExitCode();
|
test_ExitCode();
|
||||||
test_OpenProcess();
|
test_OpenProcess();
|
||||||
test_GetProcessVersion();
|
test_GetProcessVersion();
|
||||||
|
test_ProcessName();
|
||||||
test_Handles();
|
test_Handles();
|
||||||
/* things that can be tested:
|
/* things that can be tested:
|
||||||
* lookup: check the way program to be executed is searched
|
* lookup: check the way program to be executed is searched
|
||||||
|
|
|
@ -313,6 +313,8 @@ NTSTATUS WINAPI NtQueryInformationProcess(
|
||||||
else ret = STATUS_INFO_LENGTH_MISMATCH;
|
else ret = STATUS_INFO_LENGTH_MISMATCH;
|
||||||
break;
|
break;
|
||||||
case ProcessImageFileName:
|
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)
|
SERVER_START_REQ(get_dll_info)
|
||||||
{
|
{
|
||||||
UNICODE_STRING *image_file_name_str = ProcessInformation;
|
UNICODE_STRING *image_file_name_str = ProcessInformation;
|
||||||
|
|
|
@ -818,6 +818,7 @@ static void test_query_process_image_file_name(void)
|
||||||
file_nameA[len] = '\0';
|
file_nameA[len] = '\0';
|
||||||
HeapFree(GetProcessHeap(), 0, buffer);
|
HeapFree(GetProcessHeap(), 0, buffer);
|
||||||
trace("process image file name: %s\n", file_nameA);
|
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);
|
HeapFree(GetProcessHeap(), 0, file_nameA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1181,6 +1181,8 @@ typedef struct tagCOMMTIMEOUTS {
|
||||||
#define SET_TAPE_MEDIA_INFORMATION 0
|
#define SET_TAPE_MEDIA_INFORMATION 0
|
||||||
#define SET_TAPE_DRIVE_INFORMATION 1
|
#define SET_TAPE_DRIVE_INFORMATION 1
|
||||||
|
|
||||||
|
#define PROCESS_NAME_NATIVE 1
|
||||||
|
|
||||||
typedef void (CALLBACK *PAPCFUNC)(ULONG_PTR);
|
typedef void (CALLBACK *PAPCFUNC)(ULONG_PTR);
|
||||||
typedef void (CALLBACK *PTIMERAPCROUTINE)(LPVOID,DWORD,DWORD);
|
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 QueryDosDeviceA(LPCSTR,LPSTR,DWORD);
|
||||||
WINBASEAPI DWORD WINAPI QueryDosDeviceW(LPCWSTR,LPWSTR,DWORD);
|
WINBASEAPI DWORD WINAPI QueryDosDeviceW(LPCWSTR,LPWSTR,DWORD);
|
||||||
#define QueryDosDevice WINELIB_NAME_AW(QueryDosDevice)
|
#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 QueryInformationJobObject(HANDLE,JOBOBJECTINFOCLASS,LPVOID,DWORD,DWORD*);
|
||||||
WINBASEAPI BOOL WINAPI QueryPerformanceCounter(LARGE_INTEGER*);
|
WINBASEAPI BOOL WINAPI QueryPerformanceCounter(LARGE_INTEGER*);
|
||||||
WINBASEAPI BOOL WINAPI QueryPerformanceFrequency(LARGE_INTEGER*);
|
WINBASEAPI BOOL WINAPI QueryPerformanceFrequency(LARGE_INTEGER*);
|
||||||
|
|
Loading…
Reference in New Issue