mirror of
https://github.com/reactos/reactos.git
synced 2024-07-01 02:10:07 +00:00
[NTDLL_WINETEST]
* Sync with Wine 1.3.29. svn path=/trunk/; revision=53975
This commit is contained in:
parent
421109a7e3
commit
4aec35aa7b
|
@ -16,10 +16,11 @@ list(APPEND SOURCE
|
|||
large_int.c
|
||||
om.c
|
||||
path.c
|
||||
pipe.c
|
||||
port.c
|
||||
reg.c
|
||||
rtlbitmap.c
|
||||
rtl.c
|
||||
rtlbitmap.c
|
||||
rtlstr.c
|
||||
string.c
|
||||
time.c
|
||||
|
|
|
@ -110,7 +110,7 @@ static DWORD WINAPI RtlAtomTestThread(LPVOID Table)
|
|||
|
||||
Len = 64;
|
||||
res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &RefCount, &PinCount, Name, &Len);
|
||||
ok(!res, "Failed with longenough buffer, retval: %x\n", res);
|
||||
ok(!res, "Failed with long enough buffer, retval: %x\n", res);
|
||||
ok(RefCount == 1, "Refcount was not 1 but %x\n", RefCount);
|
||||
ok(PinCount == 1, "Pincount was not 1 but %x\n", PinCount);
|
||||
ok(!lstrcmpW(Name, testAtom2), "We found wrong atom!!\n");
|
||||
|
|
|
@ -27,13 +27,11 @@
|
|||
#include <stdio.h>
|
||||
#include "wine/test.h"
|
||||
|
||||
typedef NTSTATUS (WINAPI *fnNtNotifyChangeDirectoryFile)(
|
||||
static NTSTATUS (WINAPI *pNtNotifyChangeDirectoryFile)(
|
||||
HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,
|
||||
PIO_STATUS_BLOCK,PVOID,ULONG,ULONG,BOOLEAN);
|
||||
fnNtNotifyChangeDirectoryFile pNtNotifyChangeDirectoryFile;
|
||||
|
||||
typedef NTSTATUS (WINAPI *fnNtCancelIoFile)(HANDLE,PIO_STATUS_BLOCK);
|
||||
fnNtCancelIoFile pNtCancelIoFile;
|
||||
static NTSTATUS (WINAPI *pNtCancelIoFile)(HANDLE,PIO_STATUS_BLOCK);
|
||||
|
||||
|
||||
static void test_ntncdf(void)
|
||||
|
@ -321,10 +319,8 @@ START_TEST(change)
|
|||
return;
|
||||
}
|
||||
|
||||
pNtNotifyChangeDirectoryFile = (fnNtNotifyChangeDirectoryFile)
|
||||
GetProcAddress(hntdll, "NtNotifyChangeDirectoryFile");
|
||||
pNtCancelIoFile = (fnNtCancelIoFile)
|
||||
GetProcAddress(hntdll, "NtCancelIoFile");
|
||||
pNtNotifyChangeDirectoryFile = (void *)GetProcAddress(hntdll, "NtNotifyChangeDirectoryFile");
|
||||
pNtCancelIoFile = (void *)GetProcAddress(hntdll, "NtCancelIoFile");
|
||||
|
||||
if (!pNtNotifyChangeDirectoryFile || !pNtCancelIoFile)
|
||||
{
|
||||
|
|
|
@ -50,8 +50,9 @@ static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirection)( BOOLEAN enable );
|
|||
static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirectionEx)( ULONG disable, ULONG *old_value );
|
||||
|
||||
/* The attribute sets to test */
|
||||
struct testfile_s {
|
||||
int todo; /* set if it doesn't work on wine yet */
|
||||
static struct testfile_s {
|
||||
BOOL todo; /* set if it doesn't work on wine yet */
|
||||
BOOL attr_done; /* set if attributes were tested for this file already */
|
||||
const DWORD attr; /* desired attribute */
|
||||
const char *name; /* filename to use */
|
||||
const char *target; /* what to point to (only for reparse pts) */
|
||||
|
@ -59,11 +60,13 @@ struct testfile_s {
|
|||
int nfound; /* How many were found (expect 1) */
|
||||
WCHAR nameW[20]; /* unicode version of name (filled in later) */
|
||||
} testfiles[] = {
|
||||
{ 0, FILE_ATTRIBUTE_NORMAL, "n.tmp", NULL, "normal" },
|
||||
{ 1, FILE_ATTRIBUTE_HIDDEN, "h.tmp", NULL, "hidden" },
|
||||
{ 1, FILE_ATTRIBUTE_SYSTEM, "s.tmp", NULL, "system" },
|
||||
{ 0, FILE_ATTRIBUTE_DIRECTORY, "d.tmp", NULL, "directory" },
|
||||
{ 0, 0, NULL }
|
||||
{ 0, 0, FILE_ATTRIBUTE_NORMAL, "n.tmp", NULL, "normal" },
|
||||
{ 1, 0, FILE_ATTRIBUTE_HIDDEN, "h.tmp", NULL, "hidden" },
|
||||
{ 1, 0, FILE_ATTRIBUTE_SYSTEM, "s.tmp", NULL, "system" },
|
||||
{ 0, 0, FILE_ATTRIBUTE_DIRECTORY, "d.tmp", NULL, "directory" },
|
||||
{ 0, 0, FILE_ATTRIBUTE_DIRECTORY, ".", NULL, ". directory" },
|
||||
{ 0, 0, FILE_ATTRIBUTE_DIRECTORY, "..", NULL, ".. directory" },
|
||||
{ 0, 0, 0, NULL }
|
||||
};
|
||||
static const int max_test_dir_size = 20; /* size of above plus some for .. etc */
|
||||
|
||||
|
@ -71,19 +74,21 @@ static const int max_test_dir_size = 20; /* size of above plus some for .. etc
|
|||
static void set_up_attribute_test(const char *testdirA)
|
||||
{
|
||||
int i;
|
||||
BOOL ret;
|
||||
|
||||
ok(CreateDirectoryA(testdirA, NULL),
|
||||
"couldn't create dir '%s', error %d\n", testdirA, GetLastError());
|
||||
ret = CreateDirectoryA(testdirA, NULL);
|
||||
ok(ret, "couldn't create dir '%s', error %d\n", testdirA, GetLastError());
|
||||
|
||||
for (i=0; testfiles[i].name; i++) {
|
||||
char buf[MAX_PATH];
|
||||
pRtlMultiByteToUnicodeN(testfiles[i].nameW, sizeof(testfiles[i].nameW), NULL, testfiles[i].name, strlen(testfiles[i].name)+1);
|
||||
|
||||
if (strcmp(testfiles[i].name, ".") == 0 || strcmp(testfiles[i].name, "..") == 0)
|
||||
continue;
|
||||
sprintf(buf, "%s\\%s", testdirA, testfiles[i].name);
|
||||
testfiles[i].nfound = 0;
|
||||
if (testfiles[i].attr & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
ok(CreateDirectoryA(buf, NULL),
|
||||
"couldn't create dir '%s', error %d\n", buf, GetLastError());
|
||||
ret = CreateDirectoryA(buf, NULL);
|
||||
ok(ret, "couldn't create dir '%s', error %d\n", buf, GetLastError());
|
||||
} else {
|
||||
HANDLE h = CreateFileA(buf,
|
||||
GENERIC_READ|GENERIC_WRITE,
|
||||
|
@ -95,6 +100,14 @@ static void set_up_attribute_test(const char *testdirA)
|
|||
}
|
||||
}
|
||||
|
||||
static void reset_found_files(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; testfiles[i].name; i++)
|
||||
testfiles[i].nfound = 0;
|
||||
}
|
||||
|
||||
/* Remove the given test directory and the attribute test files, if any */
|
||||
static void tear_down_attribute_test(const char *testdirA)
|
||||
{
|
||||
|
@ -103,6 +116,8 @@ static void tear_down_attribute_test(const char *testdirA)
|
|||
for (i=0; testfiles[i].name; i++) {
|
||||
int ret;
|
||||
char buf[MAX_PATH];
|
||||
if (strcmp(testfiles[i].name, ".") == 0 || strcmp(testfiles[i].name, "..") == 0)
|
||||
continue;
|
||||
sprintf(buf, "%s\\%s", testdirA, testfiles[i].name);
|
||||
if (testfiles[i].attr & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
ret = RemoveDirectory(buf);
|
||||
|
@ -127,18 +142,18 @@ static void tally_test_file(FILE_BOTH_DIRECTORY_INFORMATION *dir_info)
|
|||
WCHAR *nameW = dir_info->FileName;
|
||||
int namelen = dir_info->FileNameLength / sizeof(WCHAR);
|
||||
|
||||
if (nameW[0] == '.')
|
||||
return;
|
||||
|
||||
for (i=0; testfiles[i].name; i++) {
|
||||
int len = strlen(testfiles[i].name);
|
||||
if (namelen != len || memcmp(nameW, testfiles[i].nameW, len*sizeof(WCHAR)))
|
||||
continue;
|
||||
if (testfiles[i].todo) {
|
||||
todo_wine
|
||||
ok (attrib == (testfiles[i].attr & attribmask), "file %s: expected %s (%x), got %x (is your linux new enough?)\n", testfiles[i].name, testfiles[i].description, testfiles[i].attr, attrib);
|
||||
} else {
|
||||
ok (attrib == (testfiles[i].attr & attribmask), "file %s: expected %s (%x), got %x (is your linux new enough?)\n", testfiles[i].name, testfiles[i].description, testfiles[i].attr, attrib);
|
||||
if (!testfiles[i].attr_done) {
|
||||
if (testfiles[i].todo) {
|
||||
todo_wine
|
||||
ok (attrib == (testfiles[i].attr & attribmask), "file %s: expected %s (%x), got %x (is your linux new enough?)\n", testfiles[i].name, testfiles[i].description, testfiles[i].attr, attrib);
|
||||
} else {
|
||||
ok (attrib == (testfiles[i].attr & attribmask), "file %s: expected %s (%x), got %x (is your linux new enough?)\n", testfiles[i].name, testfiles[i].description, testfiles[i].attr, attrib);
|
||||
}
|
||||
testfiles[i].attr_done = TRUE;
|
||||
}
|
||||
testfiles[i].nfound++;
|
||||
break;
|
||||
|
@ -146,12 +161,9 @@ static void tally_test_file(FILE_BOTH_DIRECTORY_INFORMATION *dir_info)
|
|||
ok(testfiles[i].name != NULL, "unexpected file found\n");
|
||||
}
|
||||
|
||||
static void test_NtQueryDirectoryFile(void)
|
||||
static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char *testdirA,
|
||||
BOOLEAN single_entry, BOOLEAN restart_flag)
|
||||
{
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
UNICODE_STRING ntdirname;
|
||||
char testdirA[MAX_PATH];
|
||||
WCHAR testdirW[MAX_PATH];
|
||||
HANDLE dirh;
|
||||
IO_STATUS_BLOCK io;
|
||||
UINT data_pos;
|
||||
|
@ -162,31 +174,19 @@ static void test_NtQueryDirectoryFile(void)
|
|||
int numfiles;
|
||||
int i;
|
||||
|
||||
/* Clean up from prior aborted run, if any, then set up test files */
|
||||
ok(GetTempPathA(MAX_PATH, testdirA), "couldn't get temp dir\n");
|
||||
strcat(testdirA, "NtQueryDirectoryFile.tmp");
|
||||
tear_down_attribute_test(testdirA);
|
||||
set_up_attribute_test(testdirA);
|
||||
reset_found_files();
|
||||
|
||||
/* Read the directory and note which files are found */
|
||||
pRtlMultiByteToUnicodeN(testdirW, sizeof(testdirW), NULL, testdirA, strlen(testdirA)+1);
|
||||
if (!pRtlDosPathNameToNtPathName_U(testdirW, &ntdirname, NULL, NULL))
|
||||
{
|
||||
ok(0,"RtlDosPathNametoNtPathName_U failed\n");
|
||||
goto done;
|
||||
}
|
||||
InitializeObjectAttributes(&attr, &ntdirname, OBJ_CASE_INSENSITIVE, 0, NULL);
|
||||
status = pNtOpenFile( &dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io,
|
||||
FILE_OPEN,
|
||||
status = pNtOpenFile( &dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, attr, &io, FILE_OPEN,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT|FILE_OPEN_FOR_BACKUP_INTENT|FILE_DIRECTORY_FILE);
|
||||
ok (status == STATUS_SUCCESS, "failed to open dir '%s', ret 0x%x, error %d\n", testdirA, status, GetLastError());
|
||||
if (status != STATUS_SUCCESS) {
|
||||
skip("can't test if we can't open the directory\n");
|
||||
goto done;
|
||||
return;
|
||||
}
|
||||
|
||||
pNtQueryDirectoryFile( dirh, NULL, NULL, NULL, &io, data, sizeof(data),
|
||||
FileBothDirectoryInformation, FALSE, NULL, TRUE );
|
||||
FileBothDirectoryInformation, single_entry, NULL, restart_flag );
|
||||
ok (U(io).Status == STATUS_SUCCESS, "filed to query directory; status %x\n", U(io).Status);
|
||||
data_len = io.Information;
|
||||
ok (data_len >= sizeof(FILE_BOTH_DIRECTORY_INFORMATION), "not enough data in directory\n");
|
||||
|
@ -200,7 +200,7 @@ static void test_NtQueryDirectoryFile(void)
|
|||
|
||||
if (dir_info->NextEntryOffset == 0) {
|
||||
pNtQueryDirectoryFile( dirh, 0, NULL, NULL, &io, data, sizeof(data),
|
||||
FileBothDirectoryInformation, FALSE, NULL, FALSE );
|
||||
FileBothDirectoryInformation, single_entry, NULL, FALSE );
|
||||
if (U(io).Status == STATUS_NO_MORE_FILES)
|
||||
break;
|
||||
ok (U(io).Status == STATUS_SUCCESS, "filed to query directory; status %x\n", U(io).Status);
|
||||
|
@ -216,10 +216,38 @@ static void test_NtQueryDirectoryFile(void)
|
|||
ok(numfiles < max_test_dir_size, "too many loops\n");
|
||||
|
||||
for (i=0; testfiles[i].name; i++)
|
||||
ok(testfiles[i].nfound == 1, "Wrong number %d of %s files found\n",
|
||||
testfiles[i].nfound, testfiles[i].description);
|
||||
ok(testfiles[i].nfound == 1, "Wrong number %d of %s files found (ReturnSingleEntry=%d,RestartScan=%d)\n",
|
||||
testfiles[i].nfound, testfiles[i].description, single_entry, restart_flag);
|
||||
|
||||
pNtClose(dirh);
|
||||
}
|
||||
|
||||
static void test_NtQueryDirectoryFile(void)
|
||||
{
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
UNICODE_STRING ntdirname;
|
||||
char testdirA[MAX_PATH];
|
||||
WCHAR testdirW[MAX_PATH];
|
||||
|
||||
/* Clean up from prior aborted run, if any, then set up test files */
|
||||
ok(GetTempPathA(MAX_PATH, testdirA), "couldn't get temp dir\n");
|
||||
strcat(testdirA, "NtQueryDirectoryFile.tmp");
|
||||
tear_down_attribute_test(testdirA);
|
||||
set_up_attribute_test(testdirA);
|
||||
|
||||
pRtlMultiByteToUnicodeN(testdirW, sizeof(testdirW), NULL, testdirA, strlen(testdirA)+1);
|
||||
if (!pRtlDosPathNameToNtPathName_U(testdirW, &ntdirname, NULL, NULL))
|
||||
{
|
||||
ok(0, "RtlDosPathNametoNtPathName_U failed\n");
|
||||
goto done;
|
||||
}
|
||||
InitializeObjectAttributes(&attr, &ntdirname, OBJ_CASE_INSENSITIVE, 0, NULL);
|
||||
|
||||
test_flags_NtQueryDirectoryFile(&attr, testdirA, FALSE, TRUE);
|
||||
test_flags_NtQueryDirectoryFile(&attr, testdirA, FALSE, FALSE);
|
||||
test_flags_NtQueryDirectoryFile(&attr, testdirA, TRUE, TRUE);
|
||||
test_flags_NtQueryDirectoryFile(&attr, testdirA, TRUE, FALSE);
|
||||
|
||||
done:
|
||||
tear_down_attribute_test(testdirA);
|
||||
pRtlFreeUnicodeString(&ntdirname);
|
||||
|
|
|
@ -244,6 +244,7 @@ static void testExpand(void)
|
|||
us_dst.Buffer = NULL;
|
||||
|
||||
nts = pRtlExpandEnvironmentStrings_U(small_env, &us_src, &us_dst, &ul);
|
||||
ok(nts == STATUS_BUFFER_TOO_SMALL, "Call failed (%u)\n", nts);
|
||||
ok(ul == strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR),
|
||||
"Wrong returned length for %s: %u\n", test->src, ul );
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* Unit tests for RtlNtStatusToDosError function
|
||||
*
|
||||
* Copyright (c) 2002 Andriy Palamarchuk
|
||||
* Copyright (c) 2010 André Hentschel
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -156,6 +157,8 @@ static void run_error_tests(void)
|
|||
cmp(STATUS_CHILD_MUST_BE_VOLATILE, ERROR_CHILD_MUST_BE_VOLATILE);
|
||||
cmp(STATUS_REGISTRY_CORRUPT, ERROR_BADDB);
|
||||
cmp(STATUS_DLL_NOT_FOUND, ERROR_MOD_NOT_FOUND);
|
||||
cmp2(STATUS_OPEN_FAILED, ERROR_NET_OPEN_FAILED);
|
||||
cmp2(STATUS_IO_PRIVILEGE_FAILED, ERROR_IO_PRIVILEGE_FAILED);
|
||||
cmp(STATUS_DLL_INIT_FAILED, ERROR_DLL_INIT_FAILED);
|
||||
cmp2(STATUS_INVALID_IMPORT_OF_NON_DLL, ERROR_INVALID_IMPORT_OF_NON_DLL);
|
||||
cmp(STATUS_ORDINAL_NOT_FOUND, ERROR_INVALID_ORDINAL);
|
||||
|
@ -221,7 +224,7 @@ static void run_error_tests(void)
|
|||
cmp(STATUS_WRONG_VOLUME, ERROR_WRONG_DISK);
|
||||
cmp(STATUS_NO_MEDIA, ERROR_NO_MEDIA_IN_DRIVE);
|
||||
cmp(STATUS_NO_MEDIA_IN_DEVICE, ERROR_NOT_READY);
|
||||
cmp(STATUS_VOLUME_DISMOUNTED, ERROR_NOT_READY);
|
||||
cmp2(STATUS_VOLUME_DISMOUNTED, ERROR_NOT_READY);
|
||||
cmp(STATUS_NONEXISTENT_SECTOR, ERROR_SECTOR_NOT_FOUND);
|
||||
cmp(STATUS_WORKING_SET_QUOTA, ERROR_WORKING_SET_QUOTA);
|
||||
cmp(STATUS_NO_MEMORY, ERROR_NOT_ENOUGH_MEMORY);
|
||||
|
@ -329,6 +332,9 @@ static void run_error_tests(void)
|
|||
cmp(STATUS_INVALID_SID, ERROR_INVALID_SID);
|
||||
cmp(STATUS_INVALID_SECURITY_DESCR, ERROR_INVALID_SECURITY_DESCR);
|
||||
cmp(STATUS_PROCEDURE_NOT_FOUND, ERROR_PROC_NOT_FOUND);
|
||||
cmp2(STATUS_INVALID_LDT_SIZE, ERROR_INVALID_LDT_SIZE);
|
||||
cmp2(STATUS_INVALID_LDT_OFFSET, ERROR_INVALID_LDT_OFFSET);
|
||||
cmp2(STATUS_INVALID_LDT_DESCRIPTOR, ERROR_INVALID_LDT_DESCRIPTOR);
|
||||
cmp(STATUS_BAD_INITIAL_PC, ERROR_BAD_EXE_FORMAT);
|
||||
cmp(STATUS_INVALID_FILE_FOR_SECTION, ERROR_BAD_EXE_FORMAT);
|
||||
cmp(STATUS_INVALID_IMAGE_FORMAT, ERROR_BAD_EXE_FORMAT);
|
||||
|
@ -462,6 +468,23 @@ static void run_error_tests(void)
|
|||
cmp(STATUS_NO_QUOTAS_FOR_ACCOUNT, ERROR_NO_QUOTAS_FOR_ACCOUNT);
|
||||
cmp(STATUS_LOCAL_USER_SESSION_KEY, ERROR_LOCAL_USER_SESSION_KEY);
|
||||
cmp(STATUS_NULL_LM_PASSWORD, ERROR_NULL_LM_PASSWORD);
|
||||
cmp2(STATUS_IMAGE_MACHINE_TYPE_MISMATCH, ERROR_IMAGE_MACHINE_TYPE_MISMATCH);
|
||||
cmp2(STATUS_RECEIVE_PARTIAL, ERROR_RECEIVE_PARTIAL);
|
||||
cmp2(STATUS_RECEIVE_EXPEDITED, ERROR_RECEIVE_EXPEDITED);
|
||||
cmp2(STATUS_RECEIVE_PARTIAL_EXPEDITED, ERROR_RECEIVE_PARTIAL_EXPEDITED);
|
||||
cmp2(STATUS_EVENT_DONE, ERROR_EVENT_DONE);
|
||||
cmp2(STATUS_EVENT_PENDING, ERROR_EVENT_PENDING);
|
||||
cmp2(STATUS_CHECKING_FILE_SYSTEM, ERROR_CHECKING_FILE_SYSTEM);
|
||||
cmp2(STATUS_FATAL_APP_EXIT, ERROR_FATAL_APP_EXIT);
|
||||
cmp2(STATUS_PREDEFINED_HANDLE, ERROR_PREDEFINED_HANDLE);
|
||||
cmp2(STATUS_WAS_UNLOCKED, ERROR_WAS_UNLOCKED);
|
||||
cmp2(STATUS_SERVICE_NOTIFICATION, ERROR_SERVICE_NOTIFICATION);
|
||||
cmp2(STATUS_WAS_LOCKED, ERROR_WAS_LOCKED);
|
||||
cmp2(STATUS_LOG_HARD_ERROR, ERROR_LOG_HARD_ERROR);
|
||||
cmp2(STATUS_ALREADY_WIN32, ERROR_ALREADY_WIN32);
|
||||
cmp2(STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE, ERROR_IMAGE_MACHINE_TYPE_MISMATCH_EXE);
|
||||
cmp2(STATUS_NO_YIELD_PERFORMED, ERROR_NO_YIELD_PERFORMED);
|
||||
cmp2(STATUS_TIMER_RESUME_IGNORED, ERROR_TIMER_RESUME_IGNORED);
|
||||
cmp(STATUS_BAD_INHERITANCE_ACL, ERROR_BAD_INHERITANCE_ACL);
|
||||
cmp(STATUS_INVALID_GROUP_ATTRIBUTES, ERROR_INVALID_GROUP_ATTRIBUTES);
|
||||
cmp(STATUS_BAD_IMPERSONATION_LEVEL, ERROR_BAD_IMPERSONATION_LEVEL);
|
||||
|
@ -511,6 +534,7 @@ static void run_error_tests(void)
|
|||
cmp(STATUS_TOO_MANY_SIDS, ERROR_TOO_MANY_SIDS);
|
||||
cmp(STATUS_LM_CROSS_ENCRYPTION_REQUIRED, ERROR_LM_CROSS_ENCRYPTION_REQUIRED);
|
||||
cmp(STATUS_MESSAGE_NOT_FOUND, ERROR_MR_MID_NOT_FOUND);
|
||||
cmp2(STATUS_CONTROL_C_EXIT, ERROR_CONTROL_C_EXIT);
|
||||
cmp(STATUS_LOCAL_DISCONNECT, ERROR_NETNAME_DELETED);
|
||||
cmp(STATUS_REMOTE_DISCONNECT, ERROR_NETNAME_DELETED);
|
||||
cmp(STATUS_REMOTE_RESOURCES, ERROR_REM_NOT_LIST);
|
||||
|
@ -518,6 +542,14 @@ static void run_error_tests(void)
|
|||
cmp(STATUS_LINK_TIMEOUT, ERROR_UNEXP_NET_ERR);
|
||||
cmp(STATUS_INVALID_CONNECTION, ERROR_UNEXP_NET_ERR);
|
||||
cmp(STATUS_INVALID_ADDRESS, ERROR_UNEXP_NET_ERR);
|
||||
cmp2(STATUS_MISSING_SYSTEMFILE, ERROR_MISSING_SYSTEMFILE);
|
||||
cmp2(STATUS_PAGEFILE_CREATE_FAILED, ERROR_PAGEFILE_CREATE_FAILED);
|
||||
cmp2(STATUS_UNHANDLED_EXCEPTION, ERROR_UNHANDLED_EXCEPTION);
|
||||
cmp2(STATUS_APP_INIT_FAILURE, ERROR_APP_INIT_FAILURE);
|
||||
cmp2(STATUS_NO_PAGEFILE, ERROR_NO_PAGEFILE);
|
||||
cmp2(STATUS_ILLEGAL_FLOAT_CONTEXT, ERROR_ILLEGAL_FLOAT_CONTEXT);
|
||||
cmp2(STATUS_NO_EVENT_PAIR, ERROR_NO_EVENT_PAIR);
|
||||
cmp2(STATUS_DOMAIN_CTRLR_CONFIG_ERROR, ERROR_DOMAIN_CTRLR_CONFIG_ERROR);
|
||||
cmp(STATUS_IO_DEVICE_ERROR, ERROR_IO_DEVICE);
|
||||
cmp(STATUS_DEVICE_PROTOCOL_ERROR, ERROR_IO_DEVICE);
|
||||
cmp(STATUS_DRIVER_INTERNAL_ERROR, ERROR_IO_DEVICE);
|
||||
|
@ -904,9 +936,36 @@ static void run_error_tests(void)
|
|||
cmp2(STATUS_SXS_MANIFEST_PARSE_ERROR, ERROR_SXS_MANIFEST_PARSE_ERROR);
|
||||
cmp2(STATUS_SXS_ACTIVATION_CONTEXT_DISABLED, ERROR_SXS_ACTIVATION_CONTEXT_DISABLED);
|
||||
cmp2(STATUS_SXS_KEY_NOT_FOUND, ERROR_SXS_KEY_NOT_FOUND);
|
||||
cmp2(STATUS_SXS_VERSION_CONFLICT, ERROR_SXS_VERSION_CONFLICT);
|
||||
cmp2(STATUS_SXS_WRONG_SECTION_TYPE, ERROR_SXS_WRONG_SECTION_TYPE);
|
||||
cmp2(STATUS_SXS_THREAD_QUERIES_DISABLED, ERROR_SXS_THREAD_QUERIES_DISABLED);
|
||||
cmp2(STATUS_SXS_ASSEMBLY_MISSING, ERROR_SXS_ASSEMBLY_MISSING);
|
||||
cmp2(STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET, ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET);
|
||||
cmp2(STATUS_SXS_EARLY_DEACTIVATION, ERROR_SXS_EARLY_DEACTIVATION);
|
||||
cmp2(STATUS_SXS_INVALID_DEACTIVATION, ERROR_SXS_INVALID_DEACTIVATION);
|
||||
cmp2(STATUS_SXS_MULTIPLE_DEACTIVATION, ERROR_SXS_MULTIPLE_DEACTIVATION);
|
||||
cmp2(STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY, ERROR_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY);
|
||||
cmp2(STATUS_SXS_PROCESS_TERMINATION_REQUESTED, ERROR_SXS_PROCESS_TERMINATION_REQUESTED);
|
||||
cmp2(STATUS_SXS_CORRUPT_ACTIVATION_STACK, ERROR_SXS_CORRUPT_ACTIVATION_STACK);
|
||||
cmp2(STATUS_SXS_CORRUPTION, ERROR_SXS_CORRUPTION);
|
||||
cmp2(STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE, ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE);
|
||||
cmp2(STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME, ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME);
|
||||
cmp2(STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE, ERROR_SXS_IDENTITY_DUPLICATE_ATTRIBUTE);
|
||||
cmp2(STATUS_SXS_IDENTITY_PARSE_ERROR, ERROR_SXS_IDENTITY_PARSE_ERROR);
|
||||
cmp2(STATUS_SXS_COMPONENT_STORE_CORRUPT, ERROR_SXS_COMPONENT_STORE_CORRUPT);
|
||||
cmp2(STATUS_SXS_FILE_HASH_MISMATCH, ERROR_SXS_FILE_HASH_MISMATCH);
|
||||
cmp2(STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT, ERROR_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT);
|
||||
cmp2(STATUS_SXS_IDENTITIES_DIFFERENT, ERROR_SXS_IDENTITIES_DIFFERENT);
|
||||
cmp2(STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT, ERROR_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT);
|
||||
cmp2(STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY, ERROR_SXS_FILE_NOT_PART_OF_ASSEMBLY);
|
||||
cmp2(STATUS_ADVANCED_INSTALLER_FAILED, ERROR_ADVANCED_INSTALLER_FAILED);
|
||||
cmp2(STATUS_XML_ENCODING_MISMATCH, ERROR_XML_ENCODING_MISMATCH);
|
||||
cmp2(STATUS_SXS_MANIFEST_TOO_BIG, ERROR_SXS_MANIFEST_TOO_BIG);
|
||||
cmp2(STATUS_SXS_SETTING_NOT_REGISTERED, ERROR_SXS_SETTING_NOT_REGISTERED);
|
||||
cmp2(STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE, ERROR_SXS_TRANSACTION_CLOSURE_INCOMPLETE);
|
||||
cmp2(STATUS_SXS_PRIMITIVE_INSTALLER_FAILED, ERROR_SMI_PRIMITIVE_INSTALLER_FAILED);
|
||||
cmp2(STATUS_GENERIC_COMMAND_FAILED, ERROR_GENERIC_COMMAND_FAILED);
|
||||
cmp2(STATUS_SXS_FILE_HASH_MISSING, ERROR_SXS_FILE_HASH_MISSING);
|
||||
cmp2(STATUS_REDIRECTOR_STARTED, ERROR_SERVICE_ALREADY_RUNNING);
|
||||
cmp2(STATUS_AUDITING_DISABLED, ERROR_AUDITING_DISABLED);
|
||||
cmp2(STATUS_CLUSTER_NODE_ALREADY_UP, ERROR_CLUSTER_NODE_ALREADY_UP);
|
||||
|
|
|
@ -72,13 +72,16 @@ static BOOL is_wow64;
|
|||
|
||||
static const struct exception
|
||||
{
|
||||
BYTE code[18]; /* asm code */
|
||||
BYTE offset; /* offset of faulting instruction */
|
||||
BYTE length; /* length of faulting instruction */
|
||||
BOOL wow64_broken; /* broken on Wow64, should be skipped */
|
||||
NTSTATUS status; /* expected status code */
|
||||
DWORD nb_params; /* expected number of parameters */
|
||||
DWORD params[4]; /* expected parameters */
|
||||
BYTE code[18]; /* asm code */
|
||||
BYTE offset; /* offset of faulting instruction */
|
||||
BYTE length; /* length of faulting instruction */
|
||||
BOOL wow64_broken; /* broken on Wow64, should be skipped */
|
||||
NTSTATUS status; /* expected status code */
|
||||
DWORD nb_params; /* expected number of parameters */
|
||||
DWORD params[4]; /* expected parameters */
|
||||
NTSTATUS alt_status; /* alternative status code */
|
||||
DWORD alt_nb_params; /* alternative number of parameters */
|
||||
DWORD alt_params[4]; /* alternative parameters */
|
||||
} exceptions[] =
|
||||
{
|
||||
/* 0 */
|
||||
|
@ -137,66 +140,67 @@ static const struct exception
|
|||
6, 6, FALSE, STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffff } },
|
||||
|
||||
/* test moving %cs -> %ss */
|
||||
{ { 0x0e, 0x17, 0x58, 0xc3 }, /* 18: pushl %cs; popl %ss; popl %eax; ret */
|
||||
{ { 0x0e, 0x17, 0x58, 0xc3 }, /* pushl %cs; popl %ss; popl %eax; ret */
|
||||
1, 1, FALSE, STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffff } },
|
||||
|
||||
/* 20 */
|
||||
/* test overlong instruction (limit is 15 bytes, 5 on Win7) */
|
||||
{ { 0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0xfa,0xc3 },
|
||||
0, 16, TRUE, STATUS_ILLEGAL_INSTRUCTION, 0 },
|
||||
0, 16, TRUE, STATUS_ILLEGAL_INSTRUCTION, 0, { 0 },
|
||||
STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffff } },
|
||||
{ { 0x64,0x64,0x64,0x64,0xfa,0xc3 },
|
||||
0, 5, TRUE, STATUS_PRIVILEGED_INSTRUCTION, 0 },
|
||||
|
||||
/* test invalid interrupt */
|
||||
{ { 0xcd, 0xff, 0xc3 }, /* 21: int $0xff; ret */
|
||||
{ { 0xcd, 0xff, 0xc3 }, /* int $0xff; ret */
|
||||
0, 2, FALSE, STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffff } },
|
||||
|
||||
/* test moves to/from Crx */
|
||||
{ { 0x0f, 0x20, 0xc0, 0xc3 }, /* 22: movl %cr0,%eax; ret */
|
||||
{ { 0x0f, 0x20, 0xc0, 0xc3 }, /* movl %cr0,%eax; ret */
|
||||
0, 3, FALSE, STATUS_PRIVILEGED_INSTRUCTION, 0 },
|
||||
{ { 0x0f, 0x20, 0xe0, 0xc3 }, /* 23: movl %cr4,%eax; ret */
|
||||
{ { 0x0f, 0x20, 0xe0, 0xc3 }, /* movl %cr4,%eax; ret */
|
||||
0, 3, FALSE, STATUS_PRIVILEGED_INSTRUCTION, 0 },
|
||||
/* 25 */
|
||||
{ { 0x0f, 0x22, 0xc0, 0xc3 }, /* 24: movl %eax,%cr0; ret */
|
||||
{ { 0x0f, 0x22, 0xc0, 0xc3 }, /* movl %eax,%cr0; ret */
|
||||
0, 3, FALSE, STATUS_PRIVILEGED_INSTRUCTION, 0 },
|
||||
{ { 0x0f, 0x22, 0xe0, 0xc3 }, /* 25: movl %eax,%cr4; ret */
|
||||
{ { 0x0f, 0x22, 0xe0, 0xc3 }, /* movl %eax,%cr4; ret */
|
||||
0, 3, FALSE, STATUS_PRIVILEGED_INSTRUCTION, 0 },
|
||||
|
||||
/* test moves to/from Drx */
|
||||
{ { 0x0f, 0x21, 0xc0, 0xc3 }, /* 26: movl %dr0,%eax; ret */
|
||||
{ { 0x0f, 0x21, 0xc0, 0xc3 }, /* movl %dr0,%eax; ret */
|
||||
0, 3, FALSE, STATUS_PRIVILEGED_INSTRUCTION, 0 },
|
||||
{ { 0x0f, 0x21, 0xc8, 0xc3 }, /* 27: movl %dr1,%eax; ret */
|
||||
{ { 0x0f, 0x21, 0xc8, 0xc3 }, /* movl %dr1,%eax; ret */
|
||||
0, 3, FALSE, STATUS_PRIVILEGED_INSTRUCTION, 0 },
|
||||
{ { 0x0f, 0x21, 0xf8, 0xc3 }, /* 28: movl %dr7,%eax; ret */
|
||||
{ { 0x0f, 0x21, 0xf8, 0xc3 }, /* movl %dr7,%eax; ret */
|
||||
0, 3, FALSE, STATUS_PRIVILEGED_INSTRUCTION, 0 },
|
||||
/* 30 */
|
||||
{ { 0x0f, 0x23, 0xc0, 0xc3 }, /* 29: movl %eax,%dr0; ret */
|
||||
{ { 0x0f, 0x23, 0xc0, 0xc3 }, /* movl %eax,%dr0; ret */
|
||||
0, 3, FALSE, STATUS_PRIVILEGED_INSTRUCTION, 0 },
|
||||
{ { 0x0f, 0x23, 0xc8, 0xc3 }, /* 30: movl %eax,%dr1; ret */
|
||||
{ { 0x0f, 0x23, 0xc8, 0xc3 }, /* movl %eax,%dr1; ret */
|
||||
0, 3, FALSE, STATUS_PRIVILEGED_INSTRUCTION, 0 },
|
||||
{ { 0x0f, 0x23, 0xf8, 0xc3 }, /* 31: movl %eax,%dr7; ret */
|
||||
{ { 0x0f, 0x23, 0xf8, 0xc3 }, /* movl %eax,%dr7; ret */
|
||||
0, 3, FALSE, STATUS_PRIVILEGED_INSTRUCTION, 0 },
|
||||
|
||||
/* test memory reads */
|
||||
{ { 0xa1, 0xfc, 0xff, 0xff, 0xff, 0xc3 }, /* 32: movl 0xfffffffc,%eax; ret */
|
||||
{ { 0xa1, 0xfc, 0xff, 0xff, 0xff, 0xc3 }, /* movl 0xfffffffc,%eax; ret */
|
||||
0, 5, FALSE, STATUS_ACCESS_VIOLATION, 2, { 0, 0xfffffffc } },
|
||||
{ { 0xa1, 0xfd, 0xff, 0xff, 0xff, 0xc3 }, /* 33: movl 0xfffffffd,%eax; ret */
|
||||
{ { 0xa1, 0xfd, 0xff, 0xff, 0xff, 0xc3 }, /* movl 0xfffffffd,%eax; ret */
|
||||
0, 5, FALSE, STATUS_ACCESS_VIOLATION, 2, { 0, 0xfffffffd } },
|
||||
/* 35 */
|
||||
{ { 0xa1, 0xfe, 0xff, 0xff, 0xff, 0xc3 }, /* 34: movl 0xfffffffe,%eax; ret */
|
||||
{ { 0xa1, 0xfe, 0xff, 0xff, 0xff, 0xc3 }, /* movl 0xfffffffe,%eax; ret */
|
||||
0, 5, FALSE, STATUS_ACCESS_VIOLATION, 2, { 0, 0xfffffffe } },
|
||||
{ { 0xa1, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* 35: movl 0xffffffff,%eax; ret */
|
||||
{ { 0xa1, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl 0xffffffff,%eax; ret */
|
||||
0, 5, FALSE, STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffff } },
|
||||
|
||||
/* test memory writes */
|
||||
{ { 0xa3, 0xfc, 0xff, 0xff, 0xff, 0xc3 }, /* 36: movl %eax,0xfffffffc; ret */
|
||||
{ { 0xa3, 0xfc, 0xff, 0xff, 0xff, 0xc3 }, /* movl %eax,0xfffffffc; ret */
|
||||
0, 5, FALSE, STATUS_ACCESS_VIOLATION, 2, { 1, 0xfffffffc } },
|
||||
{ { 0xa3, 0xfd, 0xff, 0xff, 0xff, 0xc3 }, /* 37: movl %eax,0xfffffffd; ret */
|
||||
{ { 0xa3, 0xfd, 0xff, 0xff, 0xff, 0xc3 }, /* movl %eax,0xfffffffd; ret */
|
||||
0, 5, FALSE, STATUS_ACCESS_VIOLATION, 2, { 1, 0xfffffffd } },
|
||||
{ { 0xa3, 0xfe, 0xff, 0xff, 0xff, 0xc3 }, /* 38: movl %eax,0xfffffffe; ret */
|
||||
{ { 0xa3, 0xfe, 0xff, 0xff, 0xff, 0xc3 }, /* movl %eax,0xfffffffe; ret */
|
||||
0, 5, FALSE, STATUS_ACCESS_VIOLATION, 2, { 1, 0xfffffffe } },
|
||||
/* 40 */
|
||||
{ { 0xa3, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* 39: movl %eax,0xffffffff; ret */
|
||||
{ { 0xa3, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl %eax,0xffffffff; ret */
|
||||
0, 5, FALSE, STATUS_ACCESS_VIOLATION, 2, { 1, 0xffffffff } },
|
||||
|
||||
/* test exception with cleared %ds and %es (broken on Wow64) */
|
||||
|
@ -389,14 +393,23 @@ static DWORD handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *fram
|
|||
trace( "exception %u: %x flags:%x addr:%p\n",
|
||||
entry, rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
|
||||
|
||||
ok( rec->ExceptionCode == except->status,
|
||||
ok( rec->ExceptionCode == except->status ||
|
||||
(except->alt_status != 0 && rec->ExceptionCode == except->alt_status),
|
||||
"%u: Wrong exception code %x/%x\n", entry, rec->ExceptionCode, except->status );
|
||||
ok( rec->ExceptionAddress == (char*)code_mem + except->offset,
|
||||
"%u: Wrong exception address %p/%p\n", entry,
|
||||
rec->ExceptionAddress, (char*)code_mem + except->offset );
|
||||
|
||||
ok( rec->NumberParameters == except->nb_params,
|
||||
"%u: Wrong number of parameters %u/%u\n", entry, rec->NumberParameters, except->nb_params );
|
||||
if (except->alt_status == 0 || rec->ExceptionCode != except->alt_status)
|
||||
{
|
||||
ok( rec->NumberParameters == except->nb_params,
|
||||
"%u: Wrong number of parameters %u/%u\n", entry, rec->NumberParameters, except->nb_params );
|
||||
}
|
||||
else
|
||||
{
|
||||
ok( rec->NumberParameters == except->alt_nb_params,
|
||||
"%u: Wrong number of parameters %u/%u\n", entry, rec->NumberParameters, except->nb_params );
|
||||
}
|
||||
|
||||
/* Most CPUs (except Intel Core apparently) report a segment limit violation */
|
||||
/* instead of page faults for accesses beyond 0xffffffff */
|
||||
|
@ -414,10 +427,20 @@ static DWORD handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *fram
|
|||
goto skip_params;
|
||||
}
|
||||
|
||||
for (i = 0; i < rec->NumberParameters; i++)
|
||||
ok( rec->ExceptionInformation[i] == except->params[i],
|
||||
"%u: Wrong parameter %d: %lx/%x\n",
|
||||
entry, i, rec->ExceptionInformation[i], except->params[i] );
|
||||
if (except->alt_status == 0 || rec->ExceptionCode != except->alt_status)
|
||||
{
|
||||
for (i = 0; i < rec->NumberParameters; i++)
|
||||
ok( rec->ExceptionInformation[i] == except->params[i],
|
||||
"%u: Wrong parameter %d: %lx/%x\n",
|
||||
entry, i, rec->ExceptionInformation[i], except->params[i] );
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < rec->NumberParameters; i++)
|
||||
ok( rec->ExceptionInformation[i] == except->alt_params[i],
|
||||
"%u: Wrong parameter %d: %lx/%x\n",
|
||||
entry, i, rec->ExceptionInformation[i], except->alt_params[i] );
|
||||
}
|
||||
|
||||
skip_params:
|
||||
/* don't handle exception if it's not the address we expected */
|
||||
|
@ -451,20 +474,47 @@ static void test_prot_fault(void)
|
|||
}
|
||||
}
|
||||
|
||||
struct dbgreg_test {
|
||||
DWORD dr0, dr1, dr2, dr3, dr6, dr7;
|
||||
};
|
||||
|
||||
/* test handling of debug registers */
|
||||
static DWORD dreg_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
||||
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||
{
|
||||
const struct dbgreg_test *test = *(const struct dbgreg_test **)(frame + 1);
|
||||
|
||||
context->Eip += 2; /* Skips the popl (%eax) */
|
||||
context->Dr0 = 0x42424242;
|
||||
context->Dr1 = 0;
|
||||
context->Dr2 = 0;
|
||||
context->Dr3 = 0;
|
||||
context->Dr6 = 0;
|
||||
context->Dr7 = 0x155;
|
||||
context->Dr0 = test->dr0;
|
||||
context->Dr1 = test->dr1;
|
||||
context->Dr2 = test->dr2;
|
||||
context->Dr3 = test->dr3;
|
||||
context->Dr6 = test->dr6;
|
||||
context->Dr7 = test->dr7;
|
||||
return ExceptionContinueExecution;
|
||||
}
|
||||
|
||||
#define CHECK_DEBUG_REG(n, m) \
|
||||
ok((ctx.Dr##n & m) == test->dr##n, "(%d) failed to set debug register " #n " to %x, got %x\n", \
|
||||
test_num, test->dr##n, ctx.Dr##n)
|
||||
|
||||
static void check_debug_registers(int test_num, const struct dbgreg_test *test)
|
||||
{
|
||||
CONTEXT ctx;
|
||||
NTSTATUS status;
|
||||
|
||||
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
|
||||
status = pNtGetContextThread(GetCurrentThread(), &ctx);
|
||||
ok(status == STATUS_SUCCESS, "NtGetContextThread failed with %x\n", status);
|
||||
|
||||
CHECK_DEBUG_REG(0, ~0);
|
||||
CHECK_DEBUG_REG(1, ~0);
|
||||
CHECK_DEBUG_REG(2, ~0);
|
||||
CHECK_DEBUG_REG(3, ~0);
|
||||
CHECK_DEBUG_REG(6, 0x0f);
|
||||
CHECK_DEBUG_REG(7, ~0xdc00);
|
||||
}
|
||||
|
||||
static const BYTE segfault_code[5] = {
|
||||
0x31, 0xc0, /* xor %eax,%eax */
|
||||
0x8f, 0x00, /* popl (%eax) - cause exception */
|
||||
|
@ -621,6 +671,7 @@ static void test_exceptions(void)
|
|||
{
|
||||
CONTEXT ctx;
|
||||
NTSTATUS res;
|
||||
struct dbgreg_test dreg_test;
|
||||
|
||||
if (!pNtGetContextThread || !pNtSetContextThread)
|
||||
{
|
||||
|
@ -629,13 +680,21 @@ static void test_exceptions(void)
|
|||
}
|
||||
|
||||
/* test handling of debug registers */
|
||||
run_exception_test(dreg_handler, NULL, &segfault_code, sizeof(segfault_code), 0);
|
||||
memset(&dreg_test, 0, sizeof(dreg_test));
|
||||
|
||||
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
|
||||
res = pNtGetContextThread(GetCurrentThread(), &ctx);
|
||||
ok (res == STATUS_SUCCESS,"NtGetContextThread failed with %x\n", res);
|
||||
ok(ctx.Dr0 == 0x42424242,"failed to set debugregister 0 to 0x42424242, got %x\n", ctx.Dr0);
|
||||
ok((ctx.Dr7 & ~0xdc00) == 0x155,"failed to set debugregister 7 to 0x155, got %x\n", ctx.Dr7);
|
||||
dreg_test.dr0 = 0x42424240;
|
||||
dreg_test.dr2 = 0x126bb070;
|
||||
dreg_test.dr3 = 0x0badbad0;
|
||||
dreg_test.dr7 = 0xffff0115;
|
||||
run_exception_test(dreg_handler, &dreg_test, &segfault_code, sizeof(segfault_code), 0);
|
||||
check_debug_registers(1, &dreg_test);
|
||||
|
||||
dreg_test.dr0 = 0x42424242;
|
||||
dreg_test.dr2 = 0x100f0fe7;
|
||||
dreg_test.dr3 = 0x0abebabe;
|
||||
dreg_test.dr7 = 0x115;
|
||||
run_exception_test(dreg_handler, &dreg_test, &segfault_code, sizeof(segfault_code), 0);
|
||||
check_debug_registers(2, &dreg_test);
|
||||
|
||||
/* test single stepping behavior */
|
||||
got_exception = 0;
|
||||
|
@ -658,7 +717,7 @@ static void test_exceptions(void)
|
|||
ctx.Dr7 = 3;
|
||||
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
|
||||
res = pNtSetContextThread( GetCurrentThread(), &ctx);
|
||||
ok( res == STATUS_SUCCESS, "NtSetContextThread faild with %x\n", res);
|
||||
ok( res == STATUS_SUCCESS, "NtSetContextThread failed with %x\n", res);
|
||||
|
||||
got_exception = 0;
|
||||
run_exception_test(bpx_handler, NULL, dummy_code, sizeof(dummy_code), 0);
|
||||
|
@ -737,7 +796,7 @@ static void test_debugger(void)
|
|||
|
||||
if (counter > 100)
|
||||
{
|
||||
ok(FALSE, "got way too many exceptions, probaby caught in a infinite loop, terminating child\n");
|
||||
ok(FALSE, "got way too many exceptions, probably caught in a infinite loop, terminating child\n");
|
||||
pNtTerminateProcess(pi.hProcess, 1);
|
||||
}
|
||||
else if (counter >= 2) /* skip startup breakpoint */
|
||||
|
@ -805,8 +864,10 @@ static void test_debugger(void)
|
|||
} while (de.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT);
|
||||
|
||||
winetest_wait_child_process( pi.hProcess );
|
||||
ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError());
|
||||
ok(CloseHandle(pi.hProcess) != 0, "error %u\n", GetLastError());
|
||||
ret = CloseHandle(pi.hThread);
|
||||
ok(ret, "error %u\n", GetLastError());
|
||||
ret = CloseHandle(pi.hProcess);
|
||||
ok(ret, "error %u\n", GetLastError());
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* Copyright 2007 Jeff Latimer
|
||||
* Copyright 2007 Andrey Turkin
|
||||
* Copyright 2008 Jeff Zaroyko
|
||||
* Copyright 2011 Dmitry Timoshkov
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -35,6 +36,7 @@
|
|||
#include "wine/test.h"
|
||||
#include "winternl.h"
|
||||
#include "winuser.h"
|
||||
#include "winioctl.h"
|
||||
|
||||
#ifndef IO_COMPLETION_ALL_ACCESS
|
||||
#define IO_COMPLETION_ALL_ACCESS 0x001F0003
|
||||
|
@ -75,6 +77,7 @@ static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID,
|
|||
static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
|
||||
static NTSTATUS (WINAPI *pNtQueryDirectoryFile)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,
|
||||
PVOID,ULONG,FILE_INFORMATION_CLASS,BOOLEAN,PUNICODE_STRING,BOOLEAN);
|
||||
static NTSTATUS (WINAPI *pNtQueryVolumeInformationFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,FS_INFORMATION_CLASS);
|
||||
|
||||
static inline BOOL is_signaled( HANDLE obj )
|
||||
{
|
||||
|
@ -112,9 +115,9 @@ static HANDLE create_temp_file( ULONG flags )
|
|||
#define CKEY_FIRST 0x1030341
|
||||
#define CKEY_SECOND 0x132E46
|
||||
|
||||
ULONG_PTR completionKey;
|
||||
IO_STATUS_BLOCK ioSb;
|
||||
ULONG_PTR completionValue;
|
||||
static ULONG_PTR completionKey;
|
||||
static IO_STATUS_BLOCK ioSb;
|
||||
static ULONG_PTR completionValue;
|
||||
|
||||
static ULONG get_pending_msgs(HANDLE h)
|
||||
{
|
||||
|
@ -157,8 +160,10 @@ static void create_file_test(void)
|
|||
{
|
||||
static const WCHAR systemrootW[] = {'\\','S','y','s','t','e','m','R','o','o','t',
|
||||
'\\','f','a','i','l','i','n','g',0};
|
||||
static const WCHAR questionmarkInvalidNameW[] = {'a','f','i','l','e','?',0};
|
||||
static const WCHAR pipeInvalidNameW[] = {'a','|','b',0};
|
||||
NTSTATUS status;
|
||||
HANDLE dir;
|
||||
HANDLE dir, file;
|
||||
WCHAR path[MAX_PATH];
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
IO_STATUS_BLOCK io;
|
||||
|
@ -246,6 +251,35 @@ static void create_file_test(void)
|
|||
todo_wine
|
||||
ok( status == STATUS_INVALID_PARAMETER,
|
||||
"open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
|
||||
|
||||
/* Invalid chars in file/dirnames */
|
||||
pRtlDosPathNameToNtPathName_U(questionmarkInvalidNameW, &nameW, NULL, NULL);
|
||||
attr.ObjectName = &nameW;
|
||||
status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
|
||||
FILE_SHARE_READ, FILE_CREATE,
|
||||
FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
|
||||
ok(status == STATUS_OBJECT_NAME_INVALID,
|
||||
"open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
|
||||
|
||||
status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
|
||||
0, FILE_CREATE,
|
||||
FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
|
||||
ok(status == STATUS_OBJECT_NAME_INVALID,
|
||||
"open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
|
||||
|
||||
pRtlDosPathNameToNtPathName_U(pipeInvalidNameW, &nameW, NULL, NULL);
|
||||
attr.ObjectName = &nameW;
|
||||
status = pNtCreateFile(&dir, GENERIC_READ|SYNCHRONIZE, &attr, &io, NULL, 0,
|
||||
FILE_SHARE_READ, FILE_CREATE,
|
||||
FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
|
||||
ok(status == STATUS_OBJECT_NAME_INVALID,
|
||||
"open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
|
||||
|
||||
status = pNtCreateFile(&file, GENERIC_WRITE|SYNCHRONIZE, &attr, &io, NULL, 0,
|
||||
0, FILE_CREATE,
|
||||
FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
|
||||
ok(status == STATUS_OBJECT_NAME_INVALID,
|
||||
"open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
|
||||
}
|
||||
|
||||
static void open_file_test(void)
|
||||
|
@ -454,6 +488,7 @@ static void read_file_test(void)
|
|||
char buffer[128];
|
||||
LARGE_INTEGER offset;
|
||||
HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
|
||||
BOOL ret;
|
||||
|
||||
buffer[0] = 1;
|
||||
|
||||
|
@ -597,8 +632,8 @@ static void read_file_test(void)
|
|||
CloseHandle( read );
|
||||
|
||||
if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
|
||||
ok(DuplicateHandle(GetCurrentProcess(), read, GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS),
|
||||
"Failed to duplicate handle: %d\n", GetLastError());
|
||||
ret = DuplicateHandle(GetCurrentProcess(), read, GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS);
|
||||
ok(ret, "Failed to duplicate handle: %d\n", GetLastError());
|
||||
|
||||
apc_count = 0;
|
||||
U(iosb).Status = 0xdeadbabe;
|
||||
|
@ -711,6 +746,7 @@ static void read_file_test(void)
|
|||
ResetEvent( event );
|
||||
status = pNtWriteFile( handle, event, apc, &apc_count, &iosb, text, strlen(text), &offset, NULL );
|
||||
ok( status == STATUS_SUCCESS || status == STATUS_PENDING, "wrong status %x\n", status );
|
||||
if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
|
||||
ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
|
||||
ok( is_signaled( event ), "event is signaled\n" );
|
||||
|
@ -727,6 +763,7 @@ static void read_file_test(void)
|
|||
ok( status == STATUS_SUCCESS ||
|
||||
status == STATUS_PENDING, /* vista */
|
||||
"wrong status %x\n", status );
|
||||
if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
|
||||
ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
|
||||
ok( is_signaled( event ), "event is signaled\n" );
|
||||
|
@ -742,6 +779,7 @@ static void read_file_test(void)
|
|||
status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
|
||||
if (status == STATUS_PENDING) /* vista */
|
||||
{
|
||||
WaitForSingleObject( event, 1000 );
|
||||
ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
|
||||
ok( is_signaled( event ), "event is signaled\n" );
|
||||
|
@ -772,6 +810,7 @@ static void read_file_test(void)
|
|||
status == STATUS_SUCCESS ||
|
||||
status == STATUS_PENDING, /* vista */
|
||||
"wrong status %x\n", status );
|
||||
if (status == STATUS_PENDING) WaitForSingleObject( event, 1000 );
|
||||
ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == strlen(text), "wrong info %lu\n", iosb.Information );
|
||||
ok( is_signaled( event ), "event is signaled\n" );
|
||||
|
@ -813,6 +852,46 @@ static void read_file_test(void)
|
|||
CloseHandle( event );
|
||||
}
|
||||
|
||||
static void append_file_test(void)
|
||||
{
|
||||
const char text[] = "foobar";
|
||||
HANDLE handle;
|
||||
NTSTATUS status;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
DWORD written;
|
||||
char buffer[128];
|
||||
|
||||
GetTempFileNameA( ".", "foo", 0, buffer );
|
||||
/* It is possible to open a file with only FILE_APPEND_DATA access flags.
|
||||
It matches the O_WRONLY|O_APPEND open() posix behavior */
|
||||
handle = CreateFileA(buffer, FILE_APPEND_DATA, 0, NULL, CREATE_ALWAYS,
|
||||
FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||
ok( handle != INVALID_HANDLE_VALUE, "Failed to create a temp file in FILE_APPEND_DATA mode.\n" );
|
||||
if(handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
skip("Couldn't create a temporary file, skipping FILE_APPEND_DATA test\n");
|
||||
return;
|
||||
}
|
||||
|
||||
U(iosb).Status = STATUS_PENDING;
|
||||
iosb.Information = 0;
|
||||
|
||||
status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb,
|
||||
text, sizeof(text), NULL, NULL);
|
||||
|
||||
if (status == STATUS_PENDING)
|
||||
{
|
||||
WaitForSingleObject( handle, 1000 );
|
||||
status = U(iosb).Status;
|
||||
}
|
||||
written = iosb.Information;
|
||||
|
||||
todo_wine
|
||||
ok(status == STATUS_SUCCESS && written == sizeof(text), "FILE_APPEND_DATA NtWriteFile failed\n");
|
||||
|
||||
CloseHandle(handle);
|
||||
}
|
||||
|
||||
static void nt_mailslot_test(void)
|
||||
{
|
||||
HANDLE hslot;
|
||||
|
@ -858,7 +937,7 @@ static void nt_mailslot_test(void)
|
|||
"rc = %x not STATUS_SUCCESS or STATUS_INVALID_PARAMETER\n", rc);
|
||||
ok( hslot != 0, "Handle is invalid\n");
|
||||
|
||||
if ( rc == STATUS_SUCCESS ) rc = pNtClose(hslot);
|
||||
if ( rc == STATUS_SUCCESS ) pNtClose(hslot);
|
||||
|
||||
/*
|
||||
* Test that the length field is checked properly
|
||||
|
@ -947,8 +1026,11 @@ static void test_iocp_fileio(HANDLE h)
|
|||
ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
|
||||
if (hPipeClt != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
U(iosb).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
|
||||
ok( res == STATUS_INVALID_PARAMETER, "Unexpected NtSetInformationFile on non-overlapped handle: %x\n", res );
|
||||
ok( U(iosb).Status == STATUS_INVALID_PARAMETER /* 98 */ || U(iosb).Status == 0xdeadbeef /* NT4+ */,
|
||||
"Unexpected iosb.Status on non-overlapped handle: %x\n", U(iosb).Status );
|
||||
CloseHandle(hPipeClt);
|
||||
}
|
||||
CloseHandle( hPipeSrv );
|
||||
|
@ -968,7 +1050,8 @@ static void test_iocp_fileio(HANDLE h)
|
|||
DWORD read;
|
||||
long count;
|
||||
|
||||
NTSTATUS res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
|
||||
U(iosb).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
|
||||
ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
|
||||
ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
|
||||
|
||||
|
@ -1047,8 +1130,10 @@ static void test_file_basic_information(void)
|
|||
/* Clear fbi to avoid setting times */
|
||||
memset(&fbi, 0, sizeof(fbi));
|
||||
fbi.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
|
||||
ok ( res == STATUS_SUCCESS, "can't set system attribute\n");
|
||||
ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
|
||||
ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
|
||||
|
||||
memset(&fbi, 0, sizeof(fbi));
|
||||
res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
|
||||
|
@ -1058,8 +1143,10 @@ static void test_file_basic_information(void)
|
|||
/* Then HIDDEN */
|
||||
memset(&fbi, 0, sizeof(fbi));
|
||||
fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
|
||||
ok ( res == STATUS_SUCCESS, "can't set system attribute\n");
|
||||
ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
|
||||
ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
|
||||
|
||||
memset(&fbi, 0, sizeof(fbi));
|
||||
res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
|
||||
|
@ -1069,8 +1156,10 @@ static void test_file_basic_information(void)
|
|||
/* Check NORMAL last of all (to make sure we can clear attributes) */
|
||||
memset(&fbi, 0, sizeof(fbi));
|
||||
fbi.FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
|
||||
ok ( res == STATUS_SUCCESS, "can't set normal attribute\n");
|
||||
ok ( res == STATUS_SUCCESS, "can't set normal attribute, NtSetInformationFile returned %x\n", res );
|
||||
ok ( U(io).Status == STATUS_SUCCESS, "can't set normal attribute, io.Status is %x\n", U(io).Status );
|
||||
|
||||
memset(&fbi, 0, sizeof(fbi));
|
||||
res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation);
|
||||
|
@ -1107,10 +1196,14 @@ static void test_file_all_information(void)
|
|||
/* Clear fbi to avoid setting times */
|
||||
memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
|
||||
fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_SYSTEM;
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
|
||||
ok ( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "shouldn't be able to set FileAllInformation, res %x\n", res);
|
||||
ok ( res == STATUS_INVALID_INFO_CLASS || broken(res == STATUS_NOT_IMPLEMENTED), "shouldn't be able to set FileAllInformation, res %x\n", res);
|
||||
todo_wine ok ( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileAllInformation, io.Status is %x\n", U(io).Status);
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
|
||||
ok ( res == STATUS_SUCCESS, "can't set system attribute\n");
|
||||
ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
|
||||
ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
|
||||
|
||||
memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
|
||||
res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
|
||||
|
@ -1120,8 +1213,10 @@ static void test_file_all_information(void)
|
|||
/* Then HIDDEN */
|
||||
memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
|
||||
fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
|
||||
ok ( res == STATUS_SUCCESS, "can't set system attribute\n");
|
||||
ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
|
||||
ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
|
||||
|
||||
memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
|
||||
res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
|
||||
|
@ -1131,8 +1226,10 @@ static void test_file_all_information(void)
|
|||
/* Check NORMAL last of all (to make sure we can clear attributes) */
|
||||
memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
|
||||
fai_buf.fai.BasicInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile(h, &io, &fai_buf.fai.BasicInformation, sizeof fai_buf.fai.BasicInformation, FileBasicInformation);
|
||||
ok ( res == STATUS_SUCCESS, "can't set normal attribute\n");
|
||||
ok ( res == STATUS_SUCCESS, "can't set system attribute, res: %x\n", res );
|
||||
ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status: %x\n", U(io).Status );
|
||||
|
||||
memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
|
||||
res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation);
|
||||
|
@ -1440,6 +1537,145 @@ static void test_file_all_name_information(void)
|
|||
HeapFree( GetProcessHeap(), 0, file_name );
|
||||
}
|
||||
|
||||
static void test_query_volume_information_file(void)
|
||||
{
|
||||
NTSTATUS status;
|
||||
HANDLE dir;
|
||||
WCHAR path[MAX_PATH];
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
IO_STATUS_BLOCK io;
|
||||
UNICODE_STRING nameW;
|
||||
FILE_FS_VOLUME_INFORMATION *ffvi;
|
||||
BYTE buf[sizeof(FILE_FS_VOLUME_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
|
||||
|
||||
GetWindowsDirectoryW( path, MAX_PATH );
|
||||
pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = 0;
|
||||
attr.ObjectName = &nameW;
|
||||
attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||
attr.SecurityDescriptor = NULL;
|
||||
attr.SecurityQualityOfService = NULL;
|
||||
|
||||
status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
|
||||
ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
|
||||
pRtlFreeUnicodeString( &nameW );
|
||||
|
||||
ZeroMemory( buf, sizeof(buf) );
|
||||
U(io).Status = 0xdadadada;
|
||||
io.Information = 0xcacacaca;
|
||||
|
||||
status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsVolumeInformation );
|
||||
|
||||
ffvi = (FILE_FS_VOLUME_INFORMATION *)buf;
|
||||
|
||||
todo_wine
|
||||
{
|
||||
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
|
||||
ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
|
||||
|
||||
ok(io.Information == (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
|
||||
"expected %d, got %lu\n", (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ffvi->VolumeLabelLength),
|
||||
io.Information);
|
||||
|
||||
ok(ffvi->VolumeCreationTime.QuadPart != 0, "Missing VolumeCreationTime\n");
|
||||
ok(ffvi->VolumeSerialNumber != 0, "Missing VolumeSerialNumber\n");
|
||||
ok(ffvi->SupportsObjects == 1,"expected 1, got %d\n", ffvi->SupportsObjects);
|
||||
}
|
||||
ok(ffvi->VolumeLabelLength == lstrlenW(ffvi->VolumeLabel) * sizeof(WCHAR), "got %d\n", ffvi->VolumeLabelLength);
|
||||
|
||||
trace("VolumeSerialNumber: %x VolumeLabelName: %s\n", ffvi->VolumeSerialNumber, wine_dbgstr_w(ffvi->VolumeLabel));
|
||||
|
||||
CloseHandle( dir );
|
||||
}
|
||||
|
||||
static void test_NtCreateFile(void)
|
||||
{
|
||||
static const struct test_data
|
||||
{
|
||||
DWORD disposition, attrib_in, status, result, attrib_out, needs_cleanup;
|
||||
} td[] =
|
||||
{
|
||||
/* 0*/{ FILE_CREATE, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
|
||||
/* 1*/{ FILE_CREATE, 0, STATUS_OBJECT_NAME_COLLISION, 0, 0, TRUE },
|
||||
/* 2*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
|
||||
/* 3*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
|
||||
/* 4*/{ FILE_OPEN, FILE_ATTRIBUTE_READONLY, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
|
||||
/* 5*/{ FILE_OPEN_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
|
||||
/* 6*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE, TRUE },
|
||||
/* 7*/{ FILE_OPEN_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
|
||||
/* 8*/{ FILE_OPEN_IF, 0, 0, FILE_OPENED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
|
||||
/* 9*/{ FILE_OVERWRITE, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
|
||||
/*10*/{ FILE_OVERWRITE, 0, STATUS_OBJECT_NAME_NOT_FOUND, 0, 0, FALSE },
|
||||
/*11*/{ FILE_CREATE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
|
||||
/*12*/{ FILE_OVERWRITE, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
|
||||
/*13*/{ FILE_OVERWRITE_IF, 0, STATUS_ACCESS_DENIED, 0, 0, TRUE },
|
||||
/*14*/{ FILE_OVERWRITE_IF, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
|
||||
/*15*/{ FILE_OVERWRITE_IF, FILE_ATTRIBUTE_READONLY, 0, FILE_OVERWRITTEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, FALSE },
|
||||
/*16*/{ FILE_SUPERSEDE, 0, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE, FALSE },
|
||||
/*17*/{ FILE_SUPERSEDE, FILE_ATTRIBUTE_READONLY, 0, FILE_SUPERSEDED, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, TRUE },
|
||||
/*18*/{ FILE_SUPERSEDE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, TRUE }
|
||||
};
|
||||
static const WCHAR fooW[] = {'f','o','o',0};
|
||||
static const WCHAR dotW[] = {'.',0};
|
||||
NTSTATUS status;
|
||||
HANDLE handle;
|
||||
WCHAR path[MAX_PATH];
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
IO_STATUS_BLOCK io;
|
||||
UNICODE_STRING nameW;
|
||||
DWORD ret, i;
|
||||
|
||||
GetTempFileNameW(dotW, fooW, 0, path);
|
||||
DeleteFileW(path);
|
||||
pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
|
||||
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = NULL;
|
||||
attr.ObjectName = &nameW;
|
||||
attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||
attr.SecurityDescriptor = NULL;
|
||||
attr.SecurityQualityOfService = NULL;
|
||||
|
||||
for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
|
||||
{
|
||||
status = pNtCreateFile(&handle, GENERIC_READ, &attr, &io, NULL,
|
||||
td[i].attrib_in, FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
td[i].disposition, 0, NULL, 0);
|
||||
|
||||
ok(status == td[i].status, "%d: expected %#x got %#x\n", i, td[i].status, status);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
ok(io.Information == td[i].result,"%d: expected %#x got %#lx\n", i, td[i].result, io.Information);
|
||||
|
||||
ret = GetFileAttributesW(path);
|
||||
ret &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
|
||||
/* FIXME: leave only 'else' case below once Wine is fixed */
|
||||
if (ret != td[i].attrib_out)
|
||||
{
|
||||
todo_wine
|
||||
ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
|
||||
SetFileAttributesW(path, td[i].attrib_out);
|
||||
}
|
||||
else
|
||||
ok(ret == td[i].attrib_out, "%d: expected %#x got %#x\n", i, td[i].attrib_out, ret);
|
||||
|
||||
CloseHandle(handle);
|
||||
}
|
||||
|
||||
if (td[i].needs_cleanup)
|
||||
{
|
||||
SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
|
||||
DeleteFileW(path);
|
||||
}
|
||||
}
|
||||
|
||||
SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
|
||||
DeleteFileW( path );
|
||||
}
|
||||
|
||||
START_TEST(file)
|
||||
{
|
||||
HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
|
||||
|
@ -1474,11 +1710,14 @@ START_TEST(file)
|
|||
pNtSetInformationFile = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
|
||||
pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
|
||||
pNtQueryDirectoryFile = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
|
||||
pNtQueryVolumeInformationFile = (void *)GetProcAddress(hntdll, "NtQueryVolumeInformationFile");
|
||||
|
||||
test_NtCreateFile();
|
||||
create_file_test();
|
||||
open_file_test();
|
||||
delete_file_test();
|
||||
read_file_test();
|
||||
append_file_test();
|
||||
nt_mailslot_test();
|
||||
test_iocompletion();
|
||||
test_file_basic_information();
|
||||
|
@ -1486,4 +1725,5 @@ START_TEST(file)
|
|||
test_file_both_information();
|
||||
test_file_name_information();
|
||||
test_file_all_name_information();
|
||||
test_query_volume_information_file();
|
||||
}
|
||||
|
|
|
@ -28,6 +28,11 @@ static NTSTATUS (WINAPI * pNtQueryInformationThread)(HANDLE, THREADINFOCLASS, PV
|
|||
static NTSTATUS (WINAPI * pNtSetInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG);
|
||||
static NTSTATUS (WINAPI * pNtSetInformationThread)(HANDLE, THREADINFOCLASS, PVOID, ULONG);
|
||||
static NTSTATUS (WINAPI * pNtReadVirtualMemory)(HANDLE, const void*, void*, SIZE_T, SIZE_T*);
|
||||
static NTSTATUS (WINAPI * pNtQueryVirtualMemory)(HANDLE, LPCVOID, MEMORY_INFORMATION_CLASS , PVOID , SIZE_T , SIZE_T *);
|
||||
static NTSTATUS (WINAPI * pNtCreateSection)(HANDLE*,ACCESS_MASK,const OBJECT_ATTRIBUTES*,const LARGE_INTEGER*,ULONG,ULONG,HANDLE);
|
||||
static NTSTATUS (WINAPI * pNtMapViewOfSection)(HANDLE,HANDLE,PVOID*,ULONG,SIZE_T,const LARGE_INTEGER*,SIZE_T*,SECTION_INHERIT,ULONG,ULONG);
|
||||
static NTSTATUS (WINAPI * pNtUnmapViewOfSection)(HANDLE,PVOID);
|
||||
static NTSTATUS (WINAPI * pNtClose)(HANDLE);
|
||||
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
|
||||
|
||||
static BOOL is_wow64;
|
||||
|
@ -61,6 +66,11 @@ static BOOL InitFunctionPtrs(void)
|
|||
NTDLL_GET_PROC(NtSetInformationProcess);
|
||||
NTDLL_GET_PROC(NtSetInformationThread);
|
||||
NTDLL_GET_PROC(NtReadVirtualMemory);
|
||||
NTDLL_GET_PROC(NtQueryVirtualMemory);
|
||||
NTDLL_GET_PROC(NtClose);
|
||||
NTDLL_GET_PROC(NtCreateSection);
|
||||
NTDLL_GET_PROC(NtMapViewOfSection);
|
||||
NTDLL_GET_PROC(NtUnmapViewOfSection);
|
||||
|
||||
pIsWow64Process = (void *)GetProcAddress(GetModuleHandle("kernel32.dll"), "IsWow64Process");
|
||||
if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
|
||||
|
@ -198,6 +208,7 @@ static void test_query_timeofday(void)
|
|||
|
||||
sti.uCurrentTimeZoneId = 0xdeadbeef;
|
||||
status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 28, &ReturnLength);
|
||||
ok(status == STATUS_SUCCESS || broken(status == STATUS_INFO_LENGTH_MISMATCH /* NT4 */), "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( 0xdeadbeef == sti.uCurrentTimeZoneId, "This part of the buffer should not have been filled\n");
|
||||
|
||||
status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 32, &ReturnLength);
|
||||
|
@ -356,6 +367,7 @@ static void test_query_procperf(void)
|
|||
|
||||
/* Find out the number of processors */
|
||||
status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
NeededLength = sbi.NumberOfProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
|
||||
|
||||
sppi = HeapAlloc(GetProcessHeap(), 0, NeededLength);
|
||||
|
@ -505,6 +517,7 @@ static void test_query_interrupt(void)
|
|||
|
||||
/* Find out the number of processors */
|
||||
status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
NeededLength = sbi.NumberOfProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION);
|
||||
|
||||
sii = HeapAlloc(GetProcessHeap(), 0, NeededLength);
|
||||
|
@ -918,6 +931,174 @@ static void test_query_process_image_file_name(void)
|
|||
HeapFree(GetProcessHeap(), 0, file_nameA);
|
||||
}
|
||||
|
||||
static void test_query_process_debug_object_handle(int argc, char **argv)
|
||||
{
|
||||
char cmdline[MAX_PATH];
|
||||
STARTUPINFO si = {0};
|
||||
PROCESS_INFORMATION pi;
|
||||
BOOL ret;
|
||||
HANDLE debug_object;
|
||||
NTSTATUS status;
|
||||
|
||||
sprintf(cmdline, "%s %s %s", argv[0], argv[1], "debuggee");
|
||||
|
||||
si.cb = sizeof(si);
|
||||
ret = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS, NULL,
|
||||
NULL, &si, &pi);
|
||||
ok(ret, "CreateProcess failed with last error %u\n", GetLastError());
|
||||
if (!ret) return;
|
||||
|
||||
status = pNtQueryInformationProcess(NULL, ProcessDebugObjectHandle, NULL,
|
||||
0, NULL);
|
||||
if (status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED)
|
||||
{
|
||||
win_skip("ProcessDebugObjectHandle is not supported\n");
|
||||
return;
|
||||
}
|
||||
ok(status == STATUS_INFO_LENGTH_MISMATCH,
|
||||
"Expected NtQueryInformationProcess to return STATUS_INFO_LENGTH_MISMATCH, got 0x%08x\n",
|
||||
status);
|
||||
|
||||
status = pNtQueryInformationProcess(NULL, ProcessDebugObjectHandle, NULL,
|
||||
sizeof(debug_object), NULL);
|
||||
ok(status == STATUS_INVALID_HANDLE ||
|
||||
status == STATUS_ACCESS_VIOLATION, /* XP */
|
||||
"Expected NtQueryInformationProcess to return STATUS_INVALID_HANDLE, got 0x%08x\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess(GetCurrentProcess(),
|
||||
ProcessDebugObjectHandle, NULL, sizeof(debug_object), NULL);
|
||||
ok(status == STATUS_ACCESS_VIOLATION,
|
||||
"Expected NtQueryInformationProcess to return STATUS_ACCESS_VIOLATION, got 0x%08x\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess(NULL, ProcessDebugObjectHandle,
|
||||
&debug_object, sizeof(debug_object), NULL);
|
||||
ok(status == STATUS_INVALID_HANDLE,
|
||||
"Expected NtQueryInformationProcess to return STATUS_ACCESS_VIOLATION, got 0x%08x\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess(GetCurrentProcess(),
|
||||
ProcessDebugObjectHandle, &debug_object,
|
||||
sizeof(debug_object) - 1, NULL);
|
||||
ok(status == STATUS_INFO_LENGTH_MISMATCH,
|
||||
"Expected NtQueryInformationProcess to return STATUS_INFO_LENGTH_MISMATCH, got 0x%08x\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess(GetCurrentProcess(),
|
||||
ProcessDebugObjectHandle, &debug_object,
|
||||
sizeof(debug_object) + 1, NULL);
|
||||
ok(status == STATUS_INFO_LENGTH_MISMATCH,
|
||||
"Expected NtQueryInformationProcess to return STATUS_INFO_LENGTH_MISMATCH, got 0x%08x\n", status);
|
||||
|
||||
debug_object = (HANDLE)0xdeadbeef;
|
||||
status = pNtQueryInformationProcess(GetCurrentProcess(),
|
||||
ProcessDebugObjectHandle, &debug_object,
|
||||
sizeof(debug_object), NULL);
|
||||
ok(status == STATUS_PORT_NOT_SET,
|
||||
"Expected NtQueryInformationProcess to return STATUS_PORT_NOT_SET, got 0x%08x\n", status);
|
||||
ok(debug_object == NULL ||
|
||||
broken(debug_object == (HANDLE)0xdeadbeef), /* Wow64 */
|
||||
"Expected debug object handle to be NULL, got %p\n", debug_object);
|
||||
|
||||
debug_object = (HANDLE)0xdeadbeef;
|
||||
status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugObjectHandle,
|
||||
&debug_object, sizeof(debug_object), NULL);
|
||||
todo_wine
|
||||
ok(status == STATUS_SUCCESS,
|
||||
"Expected NtQueryInformationProcess to return STATUS_SUCCESS, got 0x%08x\n", status);
|
||||
todo_wine
|
||||
ok(debug_object != NULL,
|
||||
"Expected debug object handle to be non-NULL, got %p\n", debug_object);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
DEBUG_EVENT ev;
|
||||
|
||||
ret = WaitForDebugEvent(&ev, INFINITE);
|
||||
ok(ret, "WaitForDebugEvent failed with last error %u\n", GetLastError());
|
||||
if (!ret) break;
|
||||
|
||||
if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;
|
||||
|
||||
ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
|
||||
ok(ret, "ContinueDebugEvent failed with last error %u\n", GetLastError());
|
||||
if (!ret) break;
|
||||
}
|
||||
|
||||
ret = CloseHandle(pi.hThread);
|
||||
ok(ret, "CloseHandle failed with last error %u\n", GetLastError());
|
||||
ret = CloseHandle(pi.hProcess);
|
||||
ok(ret, "CloseHandle failed with last error %u\n", GetLastError());
|
||||
}
|
||||
|
||||
static void test_query_process_debug_flags(int argc, char **argv)
|
||||
{
|
||||
DWORD debug_flags = 0xdeadbeef;
|
||||
char cmdline[MAX_PATH];
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFO si = { 0 };
|
||||
NTSTATUS status;
|
||||
BOOL ret;
|
||||
|
||||
sprintf(cmdline, "%s %s %s", argv[0], argv[1], "debuggee");
|
||||
|
||||
si.cb = sizeof(si);
|
||||
ret = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &si, &pi);
|
||||
ok(ret, "CreateProcess failed, last error %#x.\n", GetLastError());
|
||||
if (!ret) return;
|
||||
|
||||
status = pNtQueryInformationProcess(NULL, ProcessDebugFlags,
|
||||
NULL, 0, NULL);
|
||||
ok(status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INVALID_INFO_CLASS) /* NT4 */, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess(NULL, ProcessDebugFlags,
|
||||
NULL, sizeof(debug_flags), NULL);
|
||||
ok(status == STATUS_INVALID_HANDLE || status == STATUS_ACCESS_VIOLATION || broken(status == STATUS_INVALID_INFO_CLASS) /* W7PROX64 (32-bit) */,
|
||||
"Expected STATUS_INVALID_HANDLE, got %#x.\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags,
|
||||
NULL, sizeof(debug_flags), NULL);
|
||||
ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess(NULL, ProcessDebugFlags,
|
||||
&debug_flags, sizeof(debug_flags), NULL);
|
||||
ok(status == STATUS_INVALID_HANDLE || broken(status == STATUS_INVALID_INFO_CLASS) /* NT4 */, "Expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags,
|
||||
&debug_flags, sizeof(debug_flags) - 1, NULL);
|
||||
ok(status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INVALID_INFO_CLASS) /* NT4 */, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags,
|
||||
&debug_flags, sizeof(debug_flags) + 1, NULL);
|
||||
ok(status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INVALID_INFO_CLASS) /* NT4 */, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
|
||||
|
||||
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags,
|
||||
&debug_flags, sizeof(debug_flags), NULL);
|
||||
ok(!status || broken(status == STATUS_INVALID_INFO_CLASS) /* NT4 */, "NtQueryInformationProcess failed, status %#x.\n", status);
|
||||
ok(debug_flags == TRUE|| broken(status == STATUS_INVALID_INFO_CLASS) /* NT4 */, "Expected flag TRUE, got %x.\n", debug_flags);
|
||||
|
||||
status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugFlags,
|
||||
&debug_flags, sizeof(debug_flags), NULL);
|
||||
ok(!status || broken(status == STATUS_INVALID_INFO_CLASS) /* NT4 */, "NtQueryInformationProcess failed, status %#x.\n", status);
|
||||
ok(debug_flags == FALSE || broken(status == STATUS_INVALID_INFO_CLASS) /* NT4 */, "Expected flag FALSE, got %x.\n", debug_flags);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
DEBUG_EVENT ev;
|
||||
|
||||
ret = WaitForDebugEvent(&ev, INFINITE);
|
||||
ok(ret, "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
|
||||
if (!ret) break;
|
||||
|
||||
if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;
|
||||
|
||||
ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
|
||||
ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
|
||||
if (!ret) break;
|
||||
}
|
||||
|
||||
ret = CloseHandle(pi.hThread);
|
||||
ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
|
||||
ret = CloseHandle(pi.hProcess);
|
||||
ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
|
||||
}
|
||||
|
||||
static void test_readvirtualmemory(void)
|
||||
{
|
||||
|
@ -970,6 +1151,153 @@ static void test_readvirtualmemory(void)
|
|||
CloseHandle(process);
|
||||
}
|
||||
|
||||
static void test_mapprotection(void)
|
||||
{
|
||||
HANDLE h;
|
||||
void* addr;
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
ULONG oldflags, flagsize, flags = MEM_EXECUTE_OPTION_ENABLE;
|
||||
LARGE_INTEGER size, offset;
|
||||
NTSTATUS status;
|
||||
SIZE_T retlen, count;
|
||||
void (*f)(void);
|
||||
|
||||
if (!pNtClose) {
|
||||
skip("No NtClose ... Win98\n");
|
||||
return;
|
||||
}
|
||||
/* Switch to being a noexec unaware process */
|
||||
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &oldflags, sizeof (oldflags), &flagsize);
|
||||
if (status == STATUS_INVALID_PARAMETER) {
|
||||
skip("Invalid Parameter on ProcessExecuteFlags query?\n");
|
||||
return;
|
||||
}
|
||||
ok( (status == STATUS_SUCCESS) || (status == STATUS_INVALID_INFO_CLASS), "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
status = pNtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &flags, sizeof(flags) );
|
||||
ok( (status == STATUS_SUCCESS) || (status == STATUS_INVALID_INFO_CLASS), "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
|
||||
size.u.LowPart = 0x1000;
|
||||
size.u.HighPart = 0;
|
||||
status = pNtCreateSection ( &h,
|
||||
STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE,
|
||||
NULL,
|
||||
&size,
|
||||
PAGE_READWRITE,
|
||||
SEC_COMMIT | SEC_NOCACHE,
|
||||
0
|
||||
);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
|
||||
offset.u.LowPart = 0;
|
||||
offset.u.HighPart = 0;
|
||||
count = 0x1000;
|
||||
addr = NULL;
|
||||
status = pNtMapViewOfSection ( h, GetCurrentProcess(), &addr, 0, 0, &offset, &count, ViewShare, 0, PAGE_READWRITE);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
memset (addr, 0xc3, 1); /* lret ... in both i386 and x86_64 */
|
||||
trace("trying to execute code in the readwrite only mapped anon file...\n");
|
||||
f = addr;f();
|
||||
trace("...done.\n");
|
||||
#endif
|
||||
|
||||
status = pNtQueryVirtualMemory( GetCurrentProcess(), addr, MemoryBasicInformation, &info, sizeof(info), &retlen );
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( retlen == sizeof(info), "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok(info.Protect == PAGE_READWRITE, "addr.Protect is not PAGE_READWRITE, but 0x%x\n", info.Protect);
|
||||
|
||||
status = pNtUnmapViewOfSection (GetCurrentProcess(), addr);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
pNtClose (h);
|
||||
|
||||
/* Switch back */
|
||||
pNtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &oldflags, sizeof(oldflags) );
|
||||
}
|
||||
|
||||
static void test_queryvirtualmemory(void)
|
||||
{
|
||||
NTSTATUS status;
|
||||
SIZE_T readcount;
|
||||
static const char teststring[] = "test string";
|
||||
static char datatestbuf[42] = "abc";
|
||||
static char rwtestbuf[42];
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
char stackbuf[42];
|
||||
HMODULE module;
|
||||
|
||||
module = GetModuleHandle( "ntdll.dll" );
|
||||
trace("Check flags of the PE header of NTDLL.DLL at %p\n", module);
|
||||
status = pNtQueryVirtualMemory(NtCurrentProcess(), module, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
|
||||
ok (mbi.AllocationBase == module, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi.AllocationBase, module);
|
||||
ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
|
||||
ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%x\n", mbi.State, MEM_COMMIT);
|
||||
ok (mbi.Protect == PAGE_READONLY, "mbi.Protect is 0x%x, expected 0x%x\n", mbi.Protect, PAGE_READONLY);
|
||||
ok (mbi.Type == MEM_IMAGE, "mbi.Type is 0x%x, expected 0x%x\n", mbi.Type, MEM_IMAGE);
|
||||
|
||||
trace("Check flags of a function entry in NTDLL.DLL at %p\n", pNtQueryVirtualMemory);
|
||||
module = GetModuleHandle( "ntdll.dll" );
|
||||
status = pNtQueryVirtualMemory(NtCurrentProcess(), pNtQueryVirtualMemory, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
|
||||
ok (mbi.AllocationBase == module, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi.AllocationBase, module);
|
||||
ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
|
||||
ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%x\n", mbi.State, MEM_COMMIT);
|
||||
ok (mbi.Protect == PAGE_EXECUTE_READ, "mbi.Protect is 0x%x, expected 0x%x\n", mbi.Protect, PAGE_EXECUTE_READ);
|
||||
|
||||
trace("Check flags of heap at %p\n", GetProcessHeap());
|
||||
status = pNtQueryVirtualMemory(NtCurrentProcess(), GetProcessHeap(), MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
|
||||
ok (mbi.AllocationProtect == PAGE_READWRITE || mbi.AllocationProtect == PAGE_EXECUTE_READWRITE,
|
||||
"mbi.AllocationProtect is 0x%x\n", mbi.AllocationProtect);
|
||||
ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%x\n", mbi.State, MEM_COMMIT);
|
||||
ok (mbi.Protect == PAGE_READWRITE || mbi.Protect == PAGE_EXECUTE_READWRITE,
|
||||
"mbi.Protect is 0x%x\n", mbi.Protect);
|
||||
|
||||
trace("Check flags of stack at %p\n", stackbuf);
|
||||
status = pNtQueryVirtualMemory(NtCurrentProcess(), stackbuf, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
|
||||
ok (mbi.AllocationProtect == PAGE_READWRITE, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_READWRITE);
|
||||
ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%x\n", mbi.State, MEM_COMMIT);
|
||||
ok (mbi.Protect == PAGE_READWRITE, "mbi.Protect is 0x%x, expected 0x%x\n", mbi.Protect, PAGE_READWRITE);
|
||||
|
||||
trace("Check flags of read-only data at %p\n", teststring);
|
||||
module = GetModuleHandle( NULL );
|
||||
status = pNtQueryVirtualMemory(NtCurrentProcess(), teststring, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
|
||||
ok (mbi.AllocationBase == module, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi.AllocationBase, module);
|
||||
ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
|
||||
ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%X\n", mbi.State, MEM_COMMIT);
|
||||
if (mbi.Protect != PAGE_READONLY)
|
||||
todo_wine ok( mbi.Protect == PAGE_READONLY, "mbi.Protect is 0x%x, expected 0x%X\n", mbi.Protect, PAGE_READONLY);
|
||||
|
||||
trace("Check flags of read-write data at %p\n", datatestbuf);
|
||||
status = pNtQueryVirtualMemory(NtCurrentProcess(), datatestbuf, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
|
||||
ok (mbi.AllocationBase == module, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi.AllocationBase, module);
|
||||
ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
|
||||
ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%X\n", mbi.State, MEM_COMMIT);
|
||||
ok (mbi.Protect == PAGE_READWRITE || mbi.Protect == PAGE_WRITECOPY,
|
||||
"mbi.Protect is 0x%x\n", mbi.Protect);
|
||||
|
||||
trace("Check flags of read-write uninitialized data (.bss) at %p\n", rwtestbuf);
|
||||
status = pNtQueryVirtualMemory(NtCurrentProcess(), rwtestbuf, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
|
||||
if (mbi.AllocationBase == module)
|
||||
{
|
||||
ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
|
||||
ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%X\n", mbi.State, MEM_COMMIT);
|
||||
ok (mbi.Protect == PAGE_READWRITE, "mbi.Protect is 0x%x, expected 0x%X\n", mbi.Protect, PAGE_READWRITE);
|
||||
}
|
||||
else skip( "bss is outside of module\n" ); /* this can happen on Mac OS */
|
||||
}
|
||||
|
||||
static void test_affinity(void)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
@ -1009,6 +1337,7 @@ static void test_affinity(void)
|
|||
status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( tbi.AffinityMask == 1, "Unexpected thread affinity\n" );
|
||||
|
||||
/* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
|
||||
|
@ -1027,6 +1356,7 @@ static void test_affinity(void)
|
|||
if (status == STATUS_SUCCESS)
|
||||
{
|
||||
status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( broken(tbi.AffinityMask == 1) || tbi.AffinityMask == (1 << si.dwNumberOfProcessors) - 1,
|
||||
"Unexpected thread affinity\n" );
|
||||
}
|
||||
|
@ -1147,14 +1477,28 @@ START_TEST(info)
|
|||
trace("Starting test_query_process_handlecount()\n");
|
||||
test_query_process_handlecount();
|
||||
|
||||
/* 27 ProcessImageFileName */
|
||||
/* 0x1B ProcessImageFileName */
|
||||
trace("Starting test_query_process_image_file_name()\n");
|
||||
test_query_process_image_file_name();
|
||||
|
||||
/* 0x1E ProcessDebugObjectHandle */
|
||||
trace("Starting test_query_process_debug_object_handle()\n");
|
||||
test_query_process_debug_object_handle(argc, argv);
|
||||
|
||||
/* 0x1F ProcessDebugFlags */
|
||||
trace("Starting test_process_debug_flags()\n");
|
||||
test_query_process_debug_flags(argc, argv);
|
||||
|
||||
/* belongs into it's own file */
|
||||
trace("Starting test_readvirtualmemory()\n");
|
||||
test_readvirtualmemory();
|
||||
|
||||
trace("Starting test_queryvirtualmemory()\n");
|
||||
test_queryvirtualmemory();
|
||||
|
||||
trace("Starting test_mapprotection()\n");
|
||||
test_mapprotection();
|
||||
|
||||
trace("Starting test_affinity()\n");
|
||||
test_affinity();
|
||||
}
|
||||
|
|
|
@ -326,7 +326,7 @@ static void one_RtlInt64ToUnicodeString_test(int test_num, const largeint2str_t
|
|||
/* the string would have (which can be larger than the MaximumLength). */
|
||||
/* To allow all this in the tests we do the following: */
|
||||
if (expected_unicode_string.Length >= 64) {
|
||||
/* The value is too large to convert only triggerd when testing native */
|
||||
/* The value is too large to convert only triggered when testing native */
|
||||
/* Length is not filled with the expected string length (garbage?) */
|
||||
expected_unicode_string.Length = unicode_string.Length;
|
||||
} /* if */
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<file>large_int.c</file>
|
||||
<file>om.c</file>
|
||||
<file>path.c</file>
|
||||
<file>pipe.c</file>
|
||||
<file>port.c</file>
|
||||
<file>reg.c</file>
|
||||
<file>rtlbitmap.c</file>
|
||||
|
|
|
@ -46,6 +46,7 @@ static NTSTATUS (WINAPI *pNtOpenSymbolicLinkObject)(PHANDLE, ACCESS_MASK, POBJEC
|
|||
static NTSTATUS (WINAPI *pNtCreateSymbolicLinkObject)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PUNICODE_STRING);
|
||||
static NTSTATUS (WINAPI *pNtQuerySymbolicLinkObject)(HANDLE,PUNICODE_STRING,PULONG);
|
||||
static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,ULONG,PULONG);
|
||||
static NTSTATUS (WINAPI *pNtReleaseSemaphore)(HANDLE handle, ULONG count, PULONG previous);
|
||||
|
||||
|
||||
static void test_case_sensitive (void)
|
||||
|
@ -419,9 +420,12 @@ static void test_directory(void)
|
|||
memset( buffer, 0xaa, sizeof(buffer) );
|
||||
status = pNtQuerySymbolicLinkObject( dir, &str, &len );
|
||||
ok( status == STATUS_SUCCESS, "NtQuerySymbolicLinkObject failed %08x\n", status );
|
||||
if (status != STATUS_SUCCESS)
|
||||
goto error;
|
||||
full_len = str.Length + sizeof(WCHAR);
|
||||
ok( len == full_len, "bad length %u/%u\n", len, full_len );
|
||||
ok( buffer[len / sizeof(WCHAR) - 1] == 0, "no terminating null\n" );
|
||||
if (len == full_len)
|
||||
ok( buffer[len / sizeof(WCHAR) - 1] == 0, "no terminating null\n" );
|
||||
|
||||
str.MaximumLength = str.Length;
|
||||
len = 0xdeadbeef;
|
||||
|
@ -441,6 +445,7 @@ static void test_directory(void)
|
|||
ok( status == STATUS_SUCCESS, "NtQuerySymbolicLinkObject failed %08x\n", status );
|
||||
ok( len == full_len, "bad length %u/%u\n", len, full_len );
|
||||
|
||||
error:
|
||||
pNtClose(dir);
|
||||
}
|
||||
|
||||
|
@ -654,10 +659,12 @@ static void test_query_object(void)
|
|||
{
|
||||
static const WCHAR name[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s',
|
||||
'\\','t','e','s','t','_','e','v','e','n','t'};
|
||||
static const WCHAR type_event[] = {'E','v','e','n','t'};
|
||||
static const WCHAR type_file[] = {'F','i','l','e'};
|
||||
HANDLE handle;
|
||||
char buffer[1024];
|
||||
NTSTATUS status;
|
||||
ULONG len;
|
||||
ULONG len, expected_len;
|
||||
UNICODE_STRING *str;
|
||||
char dir[MAX_PATH];
|
||||
|
||||
|
@ -668,11 +675,21 @@ static void test_query_object(void)
|
|||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
|
||||
ok( len >= sizeof(UNICODE_STRING) + sizeof(name) + sizeof(WCHAR), "unexpected len %u\n", len );
|
||||
|
||||
len = 0;
|
||||
status = pNtQueryObject( handle, ObjectTypeInformation, buffer, 0, &len );
|
||||
todo_wine ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
|
||||
todo_wine ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + sizeof(type_event) + sizeof(WCHAR), "unexpected len %u\n", len );
|
||||
|
||||
len = 0;
|
||||
status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(UNICODE_STRING), &len );
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
|
||||
ok( len >= sizeof(UNICODE_STRING) + sizeof(name) + sizeof(WCHAR), "unexpected len %u\n", len );
|
||||
|
||||
len = 0;
|
||||
status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(OBJECT_TYPE_INFORMATION), &len );
|
||||
todo_wine ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
|
||||
todo_wine ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + sizeof(type_event) + sizeof(WCHAR), "unexpected len %u\n", len );
|
||||
|
||||
len = 0;
|
||||
status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(buffer), &len );
|
||||
ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
|
||||
|
@ -689,6 +706,21 @@ static void test_query_object(void)
|
|||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
|
||||
ok( len >= sizeof(UNICODE_STRING) + sizeof(name) + sizeof(WCHAR), "unexpected len %u\n", len );
|
||||
|
||||
len = 0;
|
||||
memset( buffer, 0, sizeof(buffer) );
|
||||
status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(buffer), &len );
|
||||
todo_wine ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
|
||||
todo_wine ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
|
||||
str = (UNICODE_STRING *)buffer;
|
||||
todo_wine ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + str->Length + sizeof(WCHAR), "unexpected len %u\n", len );
|
||||
todo_wine ok( str->Buffer && !memcmp( str->Buffer, type_event, sizeof(type_file) ),
|
||||
"wrong/bad type name %s (%p)\n", wine_dbgstr_w(str->Buffer), str->Buffer );
|
||||
|
||||
len -= sizeof(WCHAR);
|
||||
status = pNtQueryObject( handle, ObjectTypeInformation, buffer, len, &len );
|
||||
todo_wine ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
|
||||
todo_wine ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + sizeof(type_event) + sizeof(WCHAR), "unexpected len %u\n", len );
|
||||
|
||||
pNtClose( handle );
|
||||
|
||||
handle = CreateEventA( NULL, FALSE, FALSE, NULL );
|
||||
|
@ -709,13 +741,62 @@ static void test_query_object(void)
|
|||
ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
|
||||
ok( len > sizeof(UNICODE_STRING), "unexpected len %u\n", len );
|
||||
str = (UNICODE_STRING *)buffer;
|
||||
ok( sizeof(UNICODE_STRING) + str->Length + sizeof(WCHAR) == len ||
|
||||
broken(sizeof(UNICODE_STRING) + str->Length == len), /* NT4 */
|
||||
expected_len = sizeof(UNICODE_STRING) + str->Length + sizeof(WCHAR);
|
||||
ok( len == expected_len || broken(len == expected_len - sizeof(WCHAR)), /* NT4 */
|
||||
"unexpected len %u\n", len );
|
||||
trace( "got %s len %u\n", wine_dbgstr_w(str->Buffer), len );
|
||||
|
||||
len = 0;
|
||||
status = pNtQueryObject( handle, ObjectNameInformation, buffer, 0, &len );
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INSUFFICIENT_RESOURCES),
|
||||
"NtQueryObject failed %x\n", status );
|
||||
ok( len == expected_len || broken(!len || len == sizeof(UNICODE_STRING)),
|
||||
"unexpected len %u\n", len );
|
||||
|
||||
len = 0;
|
||||
status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(UNICODE_STRING), &len );
|
||||
ok( status == STATUS_BUFFER_OVERFLOW || broken(status == STATUS_INSUFFICIENT_RESOURCES
|
||||
|| status == STATUS_INFO_LENGTH_MISMATCH),
|
||||
"NtQueryObject failed %x\n", status );
|
||||
ok( len == expected_len || broken(!len),
|
||||
"unexpected len %u\n", len );
|
||||
|
||||
len = 0;
|
||||
memset( buffer, 0, sizeof(buffer) );
|
||||
status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(buffer), &len );
|
||||
todo_wine ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
|
||||
todo_wine ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
|
||||
str = (UNICODE_STRING *)buffer;
|
||||
expected_len = sizeof(OBJECT_TYPE_INFORMATION) + str->Length + sizeof(WCHAR);
|
||||
todo_wine ok( len >= expected_len, "unexpected len %u\n", len );
|
||||
todo_wine ok( str->Buffer && !memcmp( str->Buffer, type_file, sizeof(type_file) ),
|
||||
"wrong/bad type name %s (%p)\n", wine_dbgstr_w(str->Buffer), str->Buffer );
|
||||
|
||||
pNtClose( handle );
|
||||
}
|
||||
|
||||
static void test_type_mismatch(void)
|
||||
{
|
||||
HANDLE h;
|
||||
NTSTATUS res;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = 0;
|
||||
attr.ObjectName = NULL;
|
||||
attr.Attributes = 0;
|
||||
attr.SecurityDescriptor = NULL;
|
||||
attr.SecurityQualityOfService = NULL;
|
||||
|
||||
res = pNtCreateEvent( &h, 0, &attr, 0, 0 );
|
||||
ok(!res, "can't create event: %x\n", res);
|
||||
|
||||
res = pNtReleaseSemaphore( h, 30, NULL );
|
||||
ok(res == STATUS_OBJECT_TYPE_MISMATCH, "expected 0xc0000024, got %x\n", res);
|
||||
|
||||
pNtClose( h );
|
||||
}
|
||||
|
||||
START_TEST(om)
|
||||
{
|
||||
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
||||
|
@ -747,6 +828,7 @@ START_TEST(om)
|
|||
pNtCreateTimer = (void *)GetProcAddress(hntdll, "NtCreateTimer");
|
||||
pNtCreateSection = (void *)GetProcAddress(hntdll, "NtCreateSection");
|
||||
pNtQueryObject = (void *)GetProcAddress(hntdll, "NtQueryObject");
|
||||
pNtReleaseSemaphore = (void *)GetProcAddress(hntdll, "NtReleaseSemaphore");
|
||||
|
||||
test_case_sensitive();
|
||||
test_namespace_pipe();
|
||||
|
@ -754,4 +836,5 @@ START_TEST(om)
|
|||
test_directory();
|
||||
test_symboliclink();
|
||||
test_query_object();
|
||||
test_type_mismatch();
|
||||
}
|
||||
|
|
430
rostests/winetests/ntdll/pipe.c
Normal file
430
rostests/winetests/ntdll/pipe.c
Normal file
|
@ -0,0 +1,430 @@
|
|||
/* Unit test suite for Ntdll NamedPipe API functions
|
||||
*
|
||||
* Copyright 2011 Bernhard Loos
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "ntstatus.h"
|
||||
#define WIN32_NO_STATUS
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
#include "winreg.h"
|
||||
#include "winnls.h"
|
||||
#include "wine/test.h"
|
||||
#include "winternl.h"
|
||||
#include "winioctl.h"
|
||||
|
||||
#ifndef __WINE_WINTERNL_H
|
||||
|
||||
typedef struct {
|
||||
ULONG NamedPipeType;
|
||||
ULONG NamedPipeConfiguration;
|
||||
ULONG MaximumInstances;
|
||||
ULONG CurrentInstances;
|
||||
ULONG InboundQuota;
|
||||
ULONG ReadDataAvailable;
|
||||
ULONG OutboundQuota;
|
||||
ULONG WriteQuotaAvailable;
|
||||
ULONG NamedPipeState;
|
||||
ULONG NamedPipeEnd;
|
||||
} FILE_PIPE_LOCAL_INFORMATION;
|
||||
|
||||
#ifndef FILE_SYNCHRONOUS_IO_ALERT
|
||||
#define FILE_SYNCHRONOUS_IO_ALERT 0x10
|
||||
#endif
|
||||
|
||||
#ifndef FILE_SYNCHRONOUS_IO_NONALERT
|
||||
#define FILE_SYNCHRONOUS_IO_NONALERT 0x20
|
||||
#endif
|
||||
|
||||
#ifndef FSCTL_PIPE_LISTEN
|
||||
#define FSCTL_PIPE_LISTEN CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static NTSTATUS (WINAPI *pNtFsControlFile) (HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, PVOID apc_context, PIO_STATUS_BLOCK io, ULONG code, PVOID in_buffer, ULONG in_size, PVOID out_buffer, ULONG out_size);
|
||||
static NTSTATUS (WINAPI *pNtCreateNamedPipeFile) (PHANDLE handle, ULONG access,
|
||||
POBJECT_ATTRIBUTES attr, PIO_STATUS_BLOCK iosb,
|
||||
ULONG sharing, ULONG dispo, ULONG options,
|
||||
ULONG pipe_type, ULONG read_mode,
|
||||
ULONG completion_mode, ULONG max_inst,
|
||||
ULONG inbound_quota, ULONG outbound_quota,
|
||||
PLARGE_INTEGER timeout);
|
||||
static NTSTATUS (WINAPI *pNtQueryInformationFile) (IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass);
|
||||
static NTSTATUS (WINAPI *pNtCancelIoFile) (HANDLE hFile, PIO_STATUS_BLOCK io_status);
|
||||
static void (WINAPI *pRtlInitUnicodeString) (PUNICODE_STRING target, PCWSTR source);
|
||||
|
||||
static HANDLE (WINAPI *pOpenThread)(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId);
|
||||
static DWORD (WINAPI *pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData);
|
||||
|
||||
|
||||
static BOOL init_func_ptrs(void)
|
||||
{
|
||||
HMODULE module = GetModuleHandle("ntdll.dll");
|
||||
|
||||
#define loadfunc(name) if (!(p##name = (void *)GetProcAddress(module, #name))) { \
|
||||
trace("GetProcAddress(%s) failed\n", #name); \
|
||||
return FALSE; \
|
||||
}
|
||||
|
||||
loadfunc(NtFsControlFile)
|
||||
loadfunc(NtCreateNamedPipeFile)
|
||||
loadfunc(NtQueryInformationFile)
|
||||
loadfunc(NtCancelIoFile)
|
||||
loadfunc(RtlInitUnicodeString)
|
||||
|
||||
/* not fatal */
|
||||
module = GetModuleHandle("kernel32.dll");
|
||||
pOpenThread = (void *)GetProcAddress(module, "OpenThread");
|
||||
pQueueUserAPC = (void *)GetProcAddress(module, "QueueUserAPC");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const WCHAR testpipe[] = { '\\', '\\', '.', '\\', 'p', 'i', 'p', 'e', '\\',
|
||||
't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 };
|
||||
static const WCHAR testpipe_nt[] = { '\\', '?', '?', '\\', 'p', 'i', 'p', 'e', '\\',
|
||||
't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 };
|
||||
|
||||
static NTSTATUS create_pipe(PHANDLE handle, ULONG sharing, ULONG options)
|
||||
{
|
||||
IO_STATUS_BLOCK iosb;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
UNICODE_STRING name;
|
||||
LARGE_INTEGER timeout;
|
||||
NTSTATUS res;
|
||||
|
||||
pRtlInitUnicodeString(&name, testpipe_nt);
|
||||
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = 0;
|
||||
attr.ObjectName = &name;
|
||||
attr.Attributes = 0x40; /*case insensitive */
|
||||
attr.SecurityDescriptor = NULL;
|
||||
attr.SecurityQualityOfService = NULL;
|
||||
|
||||
timeout.QuadPart = -100000000000ll;
|
||||
|
||||
res = pNtCreateNamedPipeFile(handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb, sharing, 2 /*FILE_CREATE*/,
|
||||
options, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void test_create_invalid(void)
|
||||
{
|
||||
IO_STATUS_BLOCK iosb;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
UNICODE_STRING name;
|
||||
LARGE_INTEGER timeout;
|
||||
NTSTATUS res;
|
||||
HANDLE handle, handle2;
|
||||
FILE_PIPE_LOCAL_INFORMATION info;
|
||||
|
||||
pRtlInitUnicodeString(&name, testpipe_nt);
|
||||
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = 0;
|
||||
attr.ObjectName = &name;
|
||||
attr.Attributes = 0x40; /*case insensitive */
|
||||
attr.SecurityDescriptor = NULL;
|
||||
attr.SecurityQualityOfService = NULL;
|
||||
|
||||
timeout.QuadPart = -100000000000ll;
|
||||
|
||||
/* create a pipe with sharing = 0 */
|
||||
res = pNtCreateNamedPipeFile(&handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb, 0, 2 /*FILE_CREATE*/,
|
||||
0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout);
|
||||
todo_wine ok(res == STATUS_INVALID_PARAMETER, "NtCreateNamedPipeFile returned %x\n", res);
|
||||
if (!res)
|
||||
CloseHandle(handle);
|
||||
|
||||
/* create a pipe without r/w access */
|
||||
res = pNtCreateNamedPipeFile(&handle, SYNCHRONIZE, &attr, &iosb, FILE_SHARE_READ | FILE_SHARE_WRITE, 2 /*FILE_CREATE*/,
|
||||
0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout);
|
||||
ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
|
||||
|
||||
res = pNtQueryInformationFile(handle, &iosb, &info, sizeof(info), (FILE_INFORMATION_CLASS)24);
|
||||
todo_wine ok(res == STATUS_ACCESS_DENIED, "NtQueryInformationFile returned %x\n", res);
|
||||
|
||||
/* test FILE_CREATE creation disposition */
|
||||
res = pNtCreateNamedPipeFile(&handle2, SYNCHRONIZE, &attr, &iosb, FILE_SHARE_READ | FILE_SHARE_WRITE, 2 /*FILE_CREATE*/,
|
||||
0, 1, 0, 0, 0xFFFFFFFF, 500, 500, &timeout);
|
||||
todo_wine ok(res == STATUS_ACCESS_DENIED, "NtCreateNamedPipeFile returned %x\n", res);
|
||||
if (!res)
|
||||
CloseHandle(handle2);
|
||||
|
||||
CloseHandle(handle);
|
||||
}
|
||||
|
||||
static BOOL ioapc_called;
|
||||
static void CALLBACK ioapc(void *arg, PIO_STATUS_BLOCK io, ULONG reserved)
|
||||
{
|
||||
ioapc_called = TRUE;
|
||||
}
|
||||
|
||||
static NTSTATUS listen_pipe(HANDLE hPipe, HANDLE hEvent, PIO_STATUS_BLOCK iosb, BOOL use_apc)
|
||||
{
|
||||
int dummy;
|
||||
|
||||
ioapc_called = FALSE;
|
||||
|
||||
return pNtFsControlFile(hPipe, hEvent, use_apc ? &ioapc: NULL, use_apc ? &dummy: NULL, iosb, FSCTL_PIPE_LISTEN, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static void test_overlapped(void)
|
||||
{
|
||||
IO_STATUS_BLOCK iosb;
|
||||
HANDLE hEvent;
|
||||
HANDLE hPipe;
|
||||
HANDLE hClient;
|
||||
NTSTATUS res;
|
||||
|
||||
hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
|
||||
ok(hEvent != INVALID_HANDLE_VALUE, "can't create event, GetLastError: %x\n", GetLastError());
|
||||
|
||||
res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, 0 /* OVERLAPPED */);
|
||||
ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
|
||||
|
||||
memset(&iosb, 0x55, sizeof(iosb));
|
||||
|
||||
/* try with event and apc */
|
||||
res = listen_pipe(hPipe, hEvent, &iosb, TRUE);
|
||||
ok(res == STATUS_PENDING, "NtFsControlFile returned %x\n", res);
|
||||
|
||||
hClient = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
|
||||
ok(hClient != INVALID_HANDLE_VALUE, "can't open pipe, GetLastError: %x\n", GetLastError());
|
||||
|
||||
ok(U(iosb).Status == 0, "Wrong iostatus %x\n", U(iosb).Status);
|
||||
ok(WaitForSingleObject(hEvent, 0) == 0, "hEvent not signaled\n");
|
||||
|
||||
ok(!ioapc_called, "IOAPC ran too early\n");
|
||||
|
||||
SleepEx(0, TRUE); /* alertable wait state */
|
||||
|
||||
ok(ioapc_called, "IOAPC didn't run\n");
|
||||
|
||||
CloseHandle(hEvent);
|
||||
CloseHandle(hPipe);
|
||||
CloseHandle(hClient);
|
||||
}
|
||||
|
||||
static BOOL userapc_called;
|
||||
static void CALLBACK userapc(ULONG_PTR dwParam)
|
||||
{
|
||||
userapc_called = TRUE;
|
||||
}
|
||||
|
||||
static BOOL open_succeeded;
|
||||
static DWORD WINAPI thread(PVOID main_thread)
|
||||
{
|
||||
HANDLE h;
|
||||
|
||||
Sleep(400);
|
||||
|
||||
if (main_thread) {
|
||||
userapc_called = FALSE;
|
||||
ok(pQueueUserAPC(&userapc, main_thread, 0), "can't queue user apc, GetLastError: %x\n", GetLastError());
|
||||
CloseHandle(main_thread);
|
||||
}
|
||||
|
||||
Sleep(400);
|
||||
|
||||
h = CreateFileW(testpipe, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
|
||||
|
||||
if (h != INVALID_HANDLE_VALUE) {
|
||||
open_succeeded = TRUE;
|
||||
Sleep(100);
|
||||
CloseHandle(h);
|
||||
} else
|
||||
open_succeeded = FALSE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_alertable(void)
|
||||
{
|
||||
IO_STATUS_BLOCK iosb;
|
||||
HANDLE hEvent;
|
||||
HANDLE hPipe;
|
||||
NTSTATUS res;
|
||||
HANDLE hThread;
|
||||
|
||||
memset(&iosb, 0x55, sizeof(iosb));
|
||||
|
||||
hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
|
||||
ok(hEvent != INVALID_HANDLE_VALUE, "can't create event, GetLastError: %x\n", GetLastError());
|
||||
|
||||
res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_ALERT);
|
||||
ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
|
||||
|
||||
/* queue an user apc before calling listen */
|
||||
userapc_called = FALSE;
|
||||
ok(pQueueUserAPC(&userapc, GetCurrentThread(), 0), "can't queue user apc, GetLastError: %x\n", GetLastError());
|
||||
|
||||
res = listen_pipe(hPipe, hEvent, &iosb, TRUE);
|
||||
todo_wine ok(res == STATUS_CANCELLED, "NtFsControlFile returned %x\n", res);
|
||||
|
||||
todo_wine ok(userapc_called, "user apc didn't run\n");
|
||||
ok(U(iosb).Status == 0x55555555, "iosb.Status got changed to %x\n", U(iosb).Status);
|
||||
todo_wine ok(WaitForSingleObjectEx(hEvent, 0, TRUE) == WAIT_TIMEOUT, "hEvent signaled\n");
|
||||
ok(!ioapc_called, "IOAPC ran\n");
|
||||
|
||||
/* queue an user apc from a different thread */
|
||||
hThread = CreateThread(NULL, 0, &thread, pOpenThread(MAXIMUM_ALLOWED, FALSE, GetCurrentThreadId()), 0, 0);
|
||||
ok(hThread != INVALID_HANDLE_VALUE, "can't create thread, GetLastError: %x\n", GetLastError());
|
||||
|
||||
/* wine_todo: the earlier NtFsControlFile call gets cancelled after the pipe gets set into listen state
|
||||
instead of before, so this NtFsControlFile will fail STATUS_INVALID_HANDLE */
|
||||
res = listen_pipe(hPipe, hEvent, &iosb, TRUE);
|
||||
todo_wine ok(res == STATUS_CANCELLED, "NtFsControlFile returned %x\n", res);
|
||||
|
||||
ok(userapc_called, "user apc didn't run\n");
|
||||
todo_wine ok(U(iosb).Status == 0x55555555, "iosb.Status got changed to %x\n", U(iosb).Status);
|
||||
ok(WaitForSingleObjectEx(hEvent, 0, TRUE) == WAIT_TIMEOUT, "hEvent signaled\n");
|
||||
ok(!ioapc_called, "IOAPC ran\n");
|
||||
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
|
||||
SleepEx(0, TRUE); /* get rid of the userapc, if NtFsControlFile failed */
|
||||
|
||||
ok(open_succeeded, "couldn't open client side pipe\n");
|
||||
|
||||
CloseHandle(hThread);
|
||||
DisconnectNamedPipe(hPipe);
|
||||
|
||||
/* finally try without an apc */
|
||||
hThread = CreateThread(NULL, 0, &thread, 0, 0, 0);
|
||||
ok(hThread != INVALID_HANDLE_VALUE, "can't create thread, GetLastError: %x\n", GetLastError());
|
||||
|
||||
res = listen_pipe(hPipe, hEvent, &iosb, TRUE);
|
||||
todo_wine ok(!res, "NtFsControlFile returned %x\n", res);
|
||||
|
||||
ok(open_succeeded, "couldn't open client side pipe\n");
|
||||
ok(!U(iosb).Status, "Wrong iostatus %x\n", U(iosb).Status);
|
||||
todo_wine ok(WaitForSingleObject(hEvent, 0) == 0, "hEvent not signaled\n");
|
||||
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
CloseHandle(hThread);
|
||||
CloseHandle(hEvent);
|
||||
CloseHandle(hPipe);
|
||||
}
|
||||
|
||||
static void test_nonalertable(void)
|
||||
{
|
||||
IO_STATUS_BLOCK iosb;
|
||||
HANDLE hEvent;
|
||||
HANDLE hPipe;
|
||||
NTSTATUS res;
|
||||
HANDLE hThread;
|
||||
|
||||
memset(&iosb, 0x55, sizeof(iosb));
|
||||
|
||||
hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
|
||||
ok(hEvent != INVALID_HANDLE_VALUE, "can't create event, GetLastError: %x\n", GetLastError());
|
||||
|
||||
res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT);
|
||||
ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
|
||||
|
||||
hThread = CreateThread(NULL, 0, &thread, 0, 0, 0);
|
||||
ok(hThread != INVALID_HANDLE_VALUE, "can't create thread, GetLastError: %x\n", GetLastError());
|
||||
|
||||
userapc_called = FALSE;
|
||||
ok(pQueueUserAPC(&userapc, GetCurrentThread(), 0), "can't queue user apc, GetLastError: %x\n", GetLastError());
|
||||
|
||||
res = listen_pipe(hPipe, hEvent, &iosb, TRUE);
|
||||
todo_wine ok(!res, "NtFsControlFile returned %x\n", res);
|
||||
|
||||
ok(open_succeeded, "couldn't open client side pipe\n");
|
||||
todo_wine ok(!U(iosb).Status, "Wrong iostatus %x\n", U(iosb).Status);
|
||||
todo_wine ok(WaitForSingleObject(hEvent, 0) == 0, "hEvent not signaled\n");
|
||||
|
||||
ok(!ioapc_called, "IOAPC ran too early\n");
|
||||
ok(!userapc_called, "user apc ran too early\n");
|
||||
|
||||
SleepEx(0, TRUE); /* alertable wait state */
|
||||
|
||||
ok(ioapc_called, "IOAPC didn't run\n");
|
||||
ok(userapc_called, "user apc didn't run\n");
|
||||
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
CloseHandle(hThread);
|
||||
CloseHandle(hEvent);
|
||||
CloseHandle(hPipe);
|
||||
}
|
||||
|
||||
static void test_cancelio(void)
|
||||
{
|
||||
IO_STATUS_BLOCK iosb;
|
||||
IO_STATUS_BLOCK cancel_sb;
|
||||
HANDLE hEvent;
|
||||
HANDLE hPipe;
|
||||
NTSTATUS res;
|
||||
|
||||
hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
|
||||
ok(hEvent != INVALID_HANDLE_VALUE, "can't create event, GetLastError: %x\n", GetLastError());
|
||||
|
||||
res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, 0 /* OVERLAPPED */);
|
||||
ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
|
||||
|
||||
memset(&iosb, 0x55, sizeof(iosb));
|
||||
|
||||
res = listen_pipe(hPipe, hEvent, &iosb, TRUE);
|
||||
ok(res == STATUS_PENDING, "NtFsControlFile returned %x\n", res);
|
||||
|
||||
res = pNtCancelIoFile(hPipe, &cancel_sb);
|
||||
todo_wine ok(!res, "NtCancelIoFile returned %x\n", res);
|
||||
|
||||
todo_wine {
|
||||
ok(U(iosb).Status == STATUS_CANCELLED, "Wrong iostatus %x\n", U(iosb).Status);
|
||||
ok(WaitForSingleObject(hEvent, 0) == 0, "hEvent not signaled\n");
|
||||
}
|
||||
|
||||
ok(!ioapc_called, "IOAPC ran too early\n");
|
||||
|
||||
SleepEx(0, TRUE); /* alertable wait state */
|
||||
|
||||
ok(ioapc_called, "IOAPC didn't run\n");
|
||||
|
||||
CloseHandle(hEvent);
|
||||
CloseHandle(hPipe);
|
||||
}
|
||||
|
||||
START_TEST(pipe)
|
||||
{
|
||||
if (!init_func_ptrs())
|
||||
return;
|
||||
|
||||
trace("starting invalid create tests\n");
|
||||
test_create_invalid();
|
||||
|
||||
trace("starting overlapped tests\n");
|
||||
test_overlapped();
|
||||
|
||||
if (!pOpenThread || !pQueueUserAPC)
|
||||
return;
|
||||
|
||||
trace("starting alertable tests\n");
|
||||
test_alertable();
|
||||
|
||||
trace("starting nonalertable tests\n");
|
||||
test_nonalertable();
|
||||
|
||||
trace("starting cancelio tests\n");
|
||||
test_cancelio();
|
||||
}
|
|
@ -128,7 +128,6 @@ static NTSTATUS (WINAPI *pNtConnectPort)(PHANDLE,PUNICODE_STRING,
|
|||
PLPC_SECTION_WRITE,PLPC_SECTION_READ,
|
||||
PVOID,PVOID,PULONG);
|
||||
static NTSTATUS (WINAPI *pRtlInitUnicodeString)(PUNICODE_STRING,LPCWSTR);
|
||||
static NTSTATUS (WINAPI *pNtWaitForSingleObject)(HANDLE,BOOLEAN,PLARGE_INTEGER);
|
||||
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
|
||||
|
||||
static BOOL is_wow64;
|
||||
|
@ -150,7 +149,6 @@ static BOOL init_function_ptrs(void)
|
|||
pNtRegisterThreadTerminatePort = (void *)GetProcAddress(hntdll, "NtRegisterThreadTerminatePort");
|
||||
pNtConnectPort = (void *)GetProcAddress(hntdll, "NtConnectPort");
|
||||
pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
|
||||
pNtWaitForSingleObject = (void *)GetProcAddress(hntdll, "NtWaitForSingleObject");
|
||||
|
||||
if (!pNtCompleteConnectPort || !pNtAcceptConnectPort ||
|
||||
!pNtReplyWaitReceivePort || !pNtCreatePort || !pNtRequestWaitReplyPort ||
|
||||
|
|
|
@ -637,6 +637,7 @@ static void test_NtDeleteKey(void)
|
|||
|
||||
InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
|
||||
status = pNtOpenKey(&hkey, am, &attr);
|
||||
ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
|
||||
|
||||
status = pNtDeleteKey(hkey);
|
||||
ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
|
||||
|
@ -1197,6 +1198,11 @@ static void test_redirection(void)
|
|||
|
||||
pRtlInitUnicodeString( &str, classes64W );
|
||||
status = pNtCreateKey( &key64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
|
||||
if (status == STATUS_ACCESS_DENIED)
|
||||
{
|
||||
skip("Not authorized to modify the Classes key\n");
|
||||
return;
|
||||
}
|
||||
ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
|
||||
|
||||
pRtlInitUnicodeString( &str, classes32W );
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "ntdll_test.h"
|
||||
#include "inaddr.h"
|
||||
|
||||
#ifndef __WINE_WINTERNL_H
|
||||
|
||||
|
@ -45,6 +46,20 @@ typedef struct _RTL_HANDLE_TABLE
|
|||
|
||||
#endif
|
||||
|
||||
/* avoid #include <winsock2.h> */
|
||||
#undef htons
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define htons(s) ((USHORT)(s))
|
||||
#else /* WORDS_BIGENDIAN */
|
||||
static inline USHORT __my_ushort_swap(USHORT s)
|
||||
{
|
||||
return (s >> 8) | (s << 8);
|
||||
}
|
||||
#define htons(s) __my_ushort_swap(s)
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
|
||||
|
||||
|
||||
/* Function ptrs for ntdll calls */
|
||||
static HMODULE hntdll = 0;
|
||||
static SIZE_T (WINAPI *pRtlCompareMemory)(LPCVOID,LPCVOID,SIZE_T);
|
||||
|
@ -70,8 +85,14 @@ static NTSTATUS (WINAPI *pRtlFreeSid)(PSID);
|
|||
static struct _TEB * (WINAPI *pNtCurrentTeb)(void);
|
||||
static DWORD (WINAPI *pRtlGetThreadErrorMode)(void);
|
||||
static NTSTATUS (WINAPI *pRtlSetThreadErrorMode)(DWORD, LPDWORD);
|
||||
static IMAGE_BASE_RELOCATION *(WINAPI *pLdrProcessRelocationBlock)(void*,UINT,USHORT*,INT_PTR);
|
||||
static CHAR * (WINAPI *pRtlIpv4AddressToStringA)(const IN_ADDR *, LPSTR);
|
||||
static NTSTATUS (WINAPI *pRtlIpv4AddressToStringExA)(const IN_ADDR *, USHORT, LPSTR, PULONG);
|
||||
|
||||
static HMODULE hkernel32 = 0;
|
||||
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
|
||||
|
||||
|
||||
#define LEN 16
|
||||
static const char* src_src = "This is a test!"; /* 16 bytes long, incl NUL */
|
||||
static ULONG src_aligned_block[4];
|
||||
|
@ -107,6 +128,9 @@ static void InitFunctionPtrs(void)
|
|||
pNtCurrentTeb = (void *)GetProcAddress(hntdll, "NtCurrentTeb");
|
||||
pRtlGetThreadErrorMode = (void *)GetProcAddress(hntdll, "RtlGetThreadErrorMode");
|
||||
pRtlSetThreadErrorMode = (void *)GetProcAddress(hntdll, "RtlSetThreadErrorMode");
|
||||
pLdrProcessRelocationBlock = (void *)GetProcAddress(hntdll, "LdrProcessRelocationBlock");
|
||||
pRtlIpv4AddressToStringA = (void *)GetProcAddress(hntdll, "RtlIpv4AddressToStringA");
|
||||
pRtlIpv4AddressToStringExA = (void *)GetProcAddress(hntdll, "RtlIpv4AddressToStringExA");
|
||||
}
|
||||
hkernel32 = LoadLibraryA("kernel32.dll");
|
||||
ok(hkernel32 != 0, "LoadLibrary failed\n");
|
||||
|
@ -1006,8 +1030,8 @@ static void test_RtlAllocateAndInitializeSid(void)
|
|||
/* these tests crash on XP */
|
||||
if (0)
|
||||
{
|
||||
ret = pRtlAllocateAndInitializeSid(NULL, 0, 1, 2, 3, 4, 5, 6, 7, 8, &psid);
|
||||
ret = pRtlAllocateAndInitializeSid(&sia, 0, 1, 2, 3, 4, 5, 6, 7, 8, NULL);
|
||||
pRtlAllocateAndInitializeSid(NULL, 0, 1, 2, 3, 4, 5, 6, 7, 8, &psid);
|
||||
pRtlAllocateAndInitializeSid(&sia, 0, 1, 2, 3, 4, 5, 6, 7, 8, NULL);
|
||||
}
|
||||
|
||||
ret = pRtlAllocateAndInitializeSid(&sia, 9, 1, 2, 3, 4, 5, 6, 7, 8, &psid);
|
||||
|
@ -1094,6 +1118,201 @@ static void test_RtlThreadErrorMode(void)
|
|||
pRtlSetThreadErrorMode(oldmode, NULL);
|
||||
}
|
||||
|
||||
static void test_LdrProcessRelocationBlock(void)
|
||||
{
|
||||
IMAGE_BASE_RELOCATION *ret;
|
||||
USHORT reloc;
|
||||
DWORD addr32;
|
||||
SHORT addr16;
|
||||
|
||||
if(!pLdrProcessRelocationBlock) {
|
||||
win_skip("LdrProcessRelocationBlock not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
addr32 = 0x50005;
|
||||
reloc = IMAGE_REL_BASED_HIGHLOW<<12;
|
||||
ret = pLdrProcessRelocationBlock(&addr32, 1, &reloc, 0x500050);
|
||||
ok((USHORT*)ret == &reloc+1, "ret = %p, expected %p\n", ret, &reloc+1);
|
||||
ok(addr32 == 0x550055, "addr32 = %x, expected 0x550055\n", addr32);
|
||||
|
||||
addr16 = 0x505;
|
||||
reloc = IMAGE_REL_BASED_HIGH<<12;
|
||||
ret = pLdrProcessRelocationBlock(&addr16, 1, &reloc, 0x500060);
|
||||
ok((USHORT*)ret == &reloc+1, "ret = %p, expected %p\n", ret, &reloc+1);
|
||||
ok(addr16 == 0x555, "addr16 = %x, expected 0x555\n", addr16);
|
||||
|
||||
addr16 = 0x505;
|
||||
reloc = IMAGE_REL_BASED_LOW<<12;
|
||||
ret = pLdrProcessRelocationBlock(&addr16, 1, &reloc, 0x500060);
|
||||
ok((USHORT*)ret == &reloc+1, "ret = %p, expected %p\n", ret, &reloc+1);
|
||||
ok(addr16 == 0x565, "addr16 = %x, expected 0x565\n", addr16);
|
||||
}
|
||||
|
||||
static void test_RtlIpv4AddressToString(void)
|
||||
{
|
||||
CHAR buffer[20];
|
||||
CHAR *res;
|
||||
IN_ADDR ip;
|
||||
DWORD len;
|
||||
|
||||
if (!pRtlIpv4AddressToStringA)
|
||||
{
|
||||
win_skip("RtlIpv4AddressToStringA not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ip.S_un.S_un_b.s_b1 = 1;
|
||||
ip.S_un.S_un_b.s_b2 = 2;
|
||||
ip.S_un.S_un_b.s_b3 = 3;
|
||||
ip.S_un.S_un_b.s_b4 = 4;
|
||||
|
||||
memset(buffer, '#', sizeof(buffer) - 1);
|
||||
buffer[sizeof(buffer) -1] = 0;
|
||||
res = pRtlIpv4AddressToStringA(&ip, buffer);
|
||||
len = strlen(buffer);
|
||||
ok(res == (buffer + len), "got %p with '%s' (expected %p)\n", res, buffer, buffer + len);
|
||||
|
||||
res = pRtlIpv4AddressToStringA(&ip, NULL);
|
||||
ok( (res == (char *)~0) ||
|
||||
broken(res == (char *)0 + len), /* XP and w2003 */
|
||||
"got %p (expected ~0)\n", res);
|
||||
|
||||
if (0) {
|
||||
/* this crashes in windows */
|
||||
memset(buffer, '#', sizeof(buffer) - 1);
|
||||
buffer[sizeof(buffer) -1] = 0;
|
||||
res = pRtlIpv4AddressToStringA(NULL, buffer);
|
||||
trace("got %p with '%s'\n", res, buffer);
|
||||
}
|
||||
|
||||
if (0) {
|
||||
/* this crashes in windows */
|
||||
res = pRtlIpv4AddressToStringA(NULL, NULL);
|
||||
trace("got %p\n", res);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_RtlIpv4AddressToStringEx(void)
|
||||
{
|
||||
CHAR ip_1234[] = "1.2.3.4";
|
||||
CHAR ip_1234_80[] = "1.2.3.4:80";
|
||||
LPSTR expect;
|
||||
CHAR buffer[30];
|
||||
NTSTATUS res;
|
||||
IN_ADDR ip;
|
||||
ULONG size;
|
||||
DWORD used;
|
||||
USHORT port;
|
||||
|
||||
if (!pRtlIpv4AddressToStringExA)
|
||||
{
|
||||
win_skip("RtlIpv4AddressToStringExA not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ip.S_un.S_un_b.s_b1 = 1;
|
||||
ip.S_un.S_un_b.s_b2 = 2;
|
||||
ip.S_un.S_un_b.s_b3 = 3;
|
||||
ip.S_un.S_un_b.s_b4 = 4;
|
||||
|
||||
port = htons(80);
|
||||
expect = ip_1234_80;
|
||||
|
||||
size = sizeof(buffer);
|
||||
memset(buffer, '#', sizeof(buffer) - 1);
|
||||
buffer[sizeof(buffer) -1] = 0;
|
||||
res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
|
||||
used = strlen(buffer);
|
||||
ok( (res == STATUS_SUCCESS) &&
|
||||
(size == strlen(expect) + 1) && !strcmp(buffer, expect),
|
||||
"got 0x%x and size %d with '%s'\n", res, size, buffer);
|
||||
|
||||
size = used + 1;
|
||||
memset(buffer, '#', sizeof(buffer) - 1);
|
||||
buffer[sizeof(buffer) -1] = 0;
|
||||
res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
|
||||
ok( (res == STATUS_SUCCESS) &&
|
||||
(size == strlen(expect) + 1) && !strcmp(buffer, expect),
|
||||
"got 0x%x and size %d with '%s'\n", res, size, buffer);
|
||||
|
||||
size = used;
|
||||
memset(buffer, '#', sizeof(buffer) - 1);
|
||||
buffer[sizeof(buffer) -1] = 0;
|
||||
res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
|
||||
ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1),
|
||||
"got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n",
|
||||
res, size, buffer, used + 1);
|
||||
|
||||
size = used - 1;
|
||||
memset(buffer, '#', sizeof(buffer) - 1);
|
||||
buffer[sizeof(buffer) -1] = 0;
|
||||
res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
|
||||
ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1),
|
||||
"got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n",
|
||||
res, size, buffer, used + 1);
|
||||
|
||||
|
||||
/* to get only the ip, use 0 as port */
|
||||
port = 0;
|
||||
expect = ip_1234;
|
||||
|
||||
size = sizeof(buffer);
|
||||
memset(buffer, '#', sizeof(buffer) - 1);
|
||||
buffer[sizeof(buffer) -1] = 0;
|
||||
res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
|
||||
used = strlen(buffer);
|
||||
ok( (res == STATUS_SUCCESS) &&
|
||||
(size == strlen(expect) + 1) && !strcmp(buffer, expect),
|
||||
"got 0x%x and size %d with '%s'\n", res, size, buffer);
|
||||
|
||||
size = used + 1;
|
||||
memset(buffer, '#', sizeof(buffer) - 1);
|
||||
buffer[sizeof(buffer) -1] = 0;
|
||||
res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
|
||||
ok( (res == STATUS_SUCCESS) &&
|
||||
(size == strlen(expect) + 1) && !strcmp(buffer, expect),
|
||||
"got 0x%x and size %d with '%s'\n", res, size, buffer);
|
||||
|
||||
size = used;
|
||||
memset(buffer, '#', sizeof(buffer) - 1);
|
||||
buffer[sizeof(buffer) -1] = 0;
|
||||
res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
|
||||
ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1),
|
||||
"got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n",
|
||||
res, size, buffer, used + 1);
|
||||
|
||||
size = used - 1;
|
||||
memset(buffer, '#', sizeof(buffer) - 1);
|
||||
buffer[sizeof(buffer) -1] = 0;
|
||||
res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
|
||||
ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1),
|
||||
"got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n",
|
||||
res, size, buffer, used + 1);
|
||||
|
||||
|
||||
/* parameters are checked */
|
||||
memset(buffer, '#', sizeof(buffer) - 1);
|
||||
buffer[sizeof(buffer) -1] = 0;
|
||||
res = pRtlIpv4AddressToStringExA(&ip, 0, buffer, NULL);
|
||||
ok(res == STATUS_INVALID_PARAMETER,
|
||||
"got 0x%x with '%s' (expected STATUS_INVALID_PARAMETER)\n", res, buffer);
|
||||
|
||||
size = sizeof(buffer);
|
||||
res = pRtlIpv4AddressToStringExA(&ip, 0, NULL, &size);
|
||||
ok( res == STATUS_INVALID_PARAMETER,
|
||||
"got 0x%x and size %d (expected STATUS_INVALID_PARAMETER)\n", res, size);
|
||||
|
||||
size = sizeof(buffer);
|
||||
memset(buffer, '#', sizeof(buffer) - 1);
|
||||
buffer[sizeof(buffer) -1] = 0;
|
||||
res = pRtlIpv4AddressToStringExA(NULL, 0, buffer, &size);
|
||||
ok( res == STATUS_INVALID_PARAMETER,
|
||||
"got 0x%x and size %d with '%s' (expected STATUS_INVALID_PARAMETER)\n",
|
||||
res, size, buffer);
|
||||
}
|
||||
|
||||
|
||||
START_TEST(rtl)
|
||||
{
|
||||
InitFunctionPtrs();
|
||||
|
@ -1114,4 +1333,7 @@ START_TEST(rtl)
|
|||
test_RtlAllocateAndInitializeSid();
|
||||
test_RtlDeleteTimer();
|
||||
test_RtlThreadErrorMode();
|
||||
test_LdrProcessRelocationBlock();
|
||||
test_RtlIpv4AddressToString();
|
||||
test_RtlIpv4AddressToStringEx();
|
||||
}
|
||||
|
|
|
@ -497,6 +497,7 @@ static void test_RtlFindSetRuns(void)
|
|||
|
||||
/* Get first 2 */
|
||||
ulCount = pRtlFindSetRuns(&bm, runs, 2, FALSE);
|
||||
ok(ulCount == 2, "RtlFindClearRuns returned %d, expected 2\n", ulCount);
|
||||
ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 101,"bad find\n");
|
||||
ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 101,"bad find\n");
|
||||
ok (runs[0].NumberOfBits + runs[1].NumberOfBits == 19 + 3,"bad size\n");
|
||||
|
@ -506,6 +507,7 @@ static void test_RtlFindSetRuns(void)
|
|||
/* Get longest 3 */
|
||||
memset(runs, 0, sizeof(runs));
|
||||
ulCount = pRtlFindSetRuns(&bm, runs, 2, TRUE);
|
||||
ok(ulCount == 2, "RtlFindClearRuns returned %d, expected 2\n", ulCount);
|
||||
ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 1877,"bad find\n");
|
||||
ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 1877,"bad find\n");
|
||||
ok (runs[0].NumberOfBits + runs[1].NumberOfBits == 33 + 19,"bad size\n");
|
||||
|
@ -515,6 +517,7 @@ static void test_RtlFindSetRuns(void)
|
|||
/* Get all 3 */
|
||||
memset(runs, 0, sizeof(runs));
|
||||
ulCount = pRtlFindSetRuns(&bm, runs, 3, TRUE);
|
||||
ok(ulCount == 3, "RtlFindClearRuns returned %d, expected 3\n", ulCount);
|
||||
ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 101 ||
|
||||
runs[0].StartingIndex == 1877,"bad find\n");
|
||||
ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 101 ||
|
||||
|
@ -571,6 +574,7 @@ static void test_RtlFindClearRuns(void)
|
|||
|
||||
/* Get first 2 */
|
||||
ulCount = pRtlFindClearRuns(&bm, runs, 2, FALSE);
|
||||
ok(ulCount == 2, "RtlFindClearRuns returned %d, expected 2\n", ulCount);
|
||||
ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 101,"bad find\n");
|
||||
ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 101,"bad find\n");
|
||||
ok (runs[0].NumberOfBits + runs[1].NumberOfBits == 19 + 3,"bad size\n");
|
||||
|
@ -580,6 +584,7 @@ static void test_RtlFindClearRuns(void)
|
|||
/* Get longest 3 */
|
||||
memset(runs, 0, sizeof(runs));
|
||||
ulCount = pRtlFindClearRuns(&bm, runs, 2, TRUE);
|
||||
ok(ulCount == 2, "RtlFindClearRuns returned %d, expected 2\n", ulCount);
|
||||
ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 1877,"bad find\n");
|
||||
ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 1877,"bad find\n");
|
||||
ok (runs[0].NumberOfBits + runs[1].NumberOfBits == 33 + 19,"bad size\n");
|
||||
|
@ -589,6 +594,7 @@ static void test_RtlFindClearRuns(void)
|
|||
/* Get all 3 */
|
||||
memset(runs, 0, sizeof(runs));
|
||||
ulCount = pRtlFindClearRuns(&bm, runs, 3, TRUE);
|
||||
ok(ulCount == 3, "RtlFindClearRuns returned %d, expected 3\n", ulCount);
|
||||
ok (runs[0].StartingIndex == 7 || runs[0].StartingIndex == 101 ||
|
||||
runs[0].StartingIndex == 1877,"bad find\n");
|
||||
ok (runs[1].StartingIndex == 7 || runs[1].StartingIndex == 101 ||
|
||||
|
|
|
@ -748,7 +748,10 @@ static const ustr2astr_t ustr2astr[] = {
|
|||
{ 8, 6, 12, "------------", 12, 12, 12, "abcdef", FALSE, 5, 6, 6, "abcde", STATUS_BUFFER_OVERFLOW},
|
||||
{ 8, 7, 12, "------------", 12, 12, 12, "abcdef", FALSE, 6, 7, 7, "abcdef", STATUS_SUCCESS},
|
||||
{ 8, 7, 12, "------------", 0, 12, 12, NULL, FALSE, 0, 7, 0, "", STATUS_SUCCESS},
|
||||
#if 0
|
||||
/* crashes on Japanese and Chinese XP */
|
||||
{ 0, 0, 12, NULL, 10, 10, 12, NULL, FALSE, 5, 0, 0, NULL, STATUS_BUFFER_OVERFLOW},
|
||||
#endif
|
||||
};
|
||||
#define NB_USTR2ASTR (sizeof(ustr2astr)/sizeof(*ustr2astr))
|
||||
|
||||
|
@ -1610,7 +1613,7 @@ static void one_RtlIntegerToUnicodeString_test(int test_num, const int2str_t *in
|
|||
/* the string would have (which can be larger than the MaximumLength). */
|
||||
/* To allow all this in the tests we do the following: */
|
||||
if (expected_unicode_string.Length > 32 && unicode_string.Length == 0) {
|
||||
/* The value is too large to convert only triggerd when testing native */
|
||||
/* The value is too large to convert only triggered when testing native */
|
||||
expected_unicode_string.Length = 0;
|
||||
}
|
||||
} else {
|
||||
|
@ -1751,7 +1754,7 @@ static void test_RtlIsTextUnicode(void)
|
|||
|
||||
/* build byte reversed unicode string with no control chars */
|
||||
be_unicode_no_controls = HeapAlloc(GetProcessHeap(), 0, sizeof(unicode) + sizeof(WCHAR));
|
||||
ok(be_unicode_no_controls != NULL, "Expeced HeapAlloc to succeed.\n");
|
||||
ok(be_unicode_no_controls != NULL, "Expected HeapAlloc to succeed.\n");
|
||||
be_unicode_no_controls[0] = 0xfffe;
|
||||
for (i = 0; i < sizeof(unicode_no_controls)/sizeof(unicode_no_controls[0]); i++)
|
||||
be_unicode_no_controls[i + 1] = (unicode_no_controls[i] >> 8) | ((unicode_no_controls[i] & 0xff) << 8);
|
||||
|
@ -1827,7 +1830,7 @@ static const WCHAR szGuid[] = { '{','0','1','0','2','0','3','0','4','-',
|
|||
static const WCHAR szGuid2[] = { '{','0','1','0','2','0','3','0','4','-',
|
||||
'0','5','0','6','-' ,'0','7','0','8','-','0','9','0','A','-',
|
||||
'0','B','0','C','0','D','0','E','0','F','0','A',']','\0' };
|
||||
DEFINE_GUID(IID_Endianess, 0x01020304, 0x0506, 0x0708, 0x09, 0x0A, 0x0B,
|
||||
DEFINE_GUID(IID_Endianness, 0x01020304, 0x0506, 0x0708, 0x09, 0x0A, 0x0B,
|
||||
0x0C, 0x0D, 0x0E, 0x0F, 0x0A);
|
||||
|
||||
static void test_RtlGUIDFromString(void)
|
||||
|
@ -1841,7 +1844,7 @@ static void test_RtlGUIDFromString(void)
|
|||
|
||||
ret = pRtlGUIDFromString(&str, &guid);
|
||||
ok(ret == 0, "expected ret=0, got 0x%0x\n", ret);
|
||||
ok(memcmp(&guid, &IID_Endianess, sizeof(guid)) == 0, "Endianess broken\n");
|
||||
ok(IsEqualGUID(&guid, &IID_Endianness), "Endianness broken\n");
|
||||
|
||||
str.Length = str.MaximumLength = sizeof(szGuid2) - sizeof(WCHAR);
|
||||
str.Buffer = (LPWSTR)szGuid2;
|
||||
|
@ -1858,9 +1861,9 @@ static void test_RtlStringFromGUID(void)
|
|||
str.Length = str.MaximumLength = 0;
|
||||
str.Buffer = NULL;
|
||||
|
||||
ret = pRtlStringFromGUID(&IID_Endianess, &str);
|
||||
ret = pRtlStringFromGUID(&IID_Endianness, &str);
|
||||
ok(ret == 0, "expected ret=0, got 0x%0x\n", ret);
|
||||
ok(str.Buffer && !lstrcmpiW(str.Buffer, szGuid), "Endianess broken\n");
|
||||
ok(str.Buffer && !lstrcmpiW(str.Buffer, szGuid), "Endianness broken\n");
|
||||
pRtlFreeUnicodeString(&str);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,8 +51,8 @@ static LPWSTR (WINAPIV *p_ultow)(ULONG, LPWSTR, INT);
|
|||
static LPWSTR (WINAPIV *p_i64tow)(LONGLONG, LPWSTR, INT);
|
||||
static LPWSTR (WINAPIV *p_ui64tow)(ULONGLONG, LPWSTR, INT);
|
||||
|
||||
static long (WINAPIV *pwcstol)(LPCWSTR, LPWSTR *, INT);
|
||||
static ULONG (WINAPIV *pwcstoul)(LPCWSTR, LPWSTR *, INT);
|
||||
static LPWSTR (__cdecl *p_wcslwr)(LPWSTR);
|
||||
static LPWSTR (__cdecl *p_wcsupr)(LPWSTR);
|
||||
|
||||
static LPWSTR (WINAPIV *p_wcschr)(LPCWSTR, WCHAR);
|
||||
static LPWSTR (WINAPIV *p_wcsrchr)(LPCWSTR, WCHAR);
|
||||
|
@ -89,8 +89,8 @@ static void InitFunctionPtrs(void)
|
|||
p_i64tow = (void *)GetProcAddress(hntdll, "_i64tow");
|
||||
p_ui64tow = (void *)GetProcAddress(hntdll, "_ui64tow");
|
||||
|
||||
pwcstol = (void *)GetProcAddress(hntdll, "wcstol");
|
||||
pwcstoul = (void *)GetProcAddress(hntdll, "wcstoul");
|
||||
p_wcslwr = (void *)GetProcAddress(hntdll, "_wcslwr");
|
||||
p_wcsupr = (void *)GetProcAddress(hntdll, "_wcsupr");
|
||||
|
||||
p_wcschr= (void *)GetProcAddress(hntdll, "wcschr");
|
||||
p_wcsrchr= (void *)GetProcAddress(hntdll, "wcsrchr");
|
||||
|
@ -1143,22 +1143,54 @@ static void test_wcsrchr(void)
|
|||
"wcsrchr should have returned NULL\n");
|
||||
}
|
||||
|
||||
static __cdecl int intcomparefunc(const void *a, const void*b)
|
||||
static void test_wcslwrupr(void)
|
||||
{
|
||||
ok (a != b, "must never get the same pointer\n");
|
||||
return (*(int*)a) - (*(int*)b);
|
||||
static WCHAR teststringW[] = {'a','b','r','a','c','a','d','a','b','r','a',0};
|
||||
static WCHAR emptyW[1] = {0};
|
||||
static const WCHAR constemptyW[1] = {0};
|
||||
|
||||
if (0) /* crashes on native */
|
||||
{
|
||||
static const WCHAR conststringW[] = {'a','b','r','a','c','a','d','a','b','r','a',0};
|
||||
ok(p_wcslwr((LPWSTR)conststringW) == conststringW, "p_wcslwr returned different string\n");
|
||||
ok(p_wcsupr((LPWSTR)conststringW) == conststringW, "p_wcsupr returned different string\n");
|
||||
ok(p_wcslwr(NULL) == NULL, "p_wcslwr didn't returned NULL\n");
|
||||
ok(p_wcsupr(NULL) == NULL, "p_wcsupr didn't returned NULL\n");
|
||||
}
|
||||
ok(p_wcslwr(teststringW) == teststringW, "p_wcslwr returned different string\n");
|
||||
ok(p_wcsupr(teststringW) == teststringW, "p_wcsupr returned different string\n");
|
||||
ok(p_wcslwr(emptyW) == emptyW, "p_wcslwr returned different string\n");
|
||||
ok(p_wcsupr(emptyW) == emptyW, "p_wcsupr returned different string\n");
|
||||
ok(p_wcslwr((LPWSTR)constemptyW) == constemptyW, "p_wcslwr returned different string\n");
|
||||
ok(p_wcsupr((LPWSTR)constemptyW) == constemptyW, "p_wcsupr returned different string\n");
|
||||
}
|
||||
|
||||
static __cdecl int charcomparefunc(const void *a, const void*b)
|
||||
static __cdecl int intcomparefunc(const void *a, const void *b)
|
||||
{
|
||||
ok (a != b, "must never get the same pointer\n");
|
||||
return (*(char*)a) - (*(char*)b);
|
||||
const int *p = a, *q = b;
|
||||
|
||||
ok (a != b, "must never get the same pointer\n");
|
||||
|
||||
return *p - *q;
|
||||
}
|
||||
|
||||
static __cdecl int strcomparefunc(const void *a, const void*b)
|
||||
static __cdecl int charcomparefunc(const void *a, const void *b)
|
||||
{
|
||||
ok (a != b, "must never get the same pointer\n");
|
||||
return lstrcmpA(*(char**)a,*(char**)b);
|
||||
const char *p = a, *q = b;
|
||||
|
||||
ok (a != b, "must never get the same pointer\n");
|
||||
|
||||
return *p - *q;
|
||||
}
|
||||
|
||||
static __cdecl int strcomparefunc(const void *a, const void *b)
|
||||
{
|
||||
const char * const *p = a;
|
||||
const char * const *q = b;
|
||||
|
||||
ok (a != b, "must never get the same pointer\n");
|
||||
|
||||
return lstrcmpA(*p, *q);
|
||||
}
|
||||
|
||||
static void test_qsort(void)
|
||||
|
@ -1175,6 +1207,27 @@ static void test_qsort(void)
|
|||
"."
|
||||
};
|
||||
|
||||
p_qsort ((void*)arr, 0, sizeof(int), intcomparefunc);
|
||||
ok(arr[0] == 23, "badly sorted, nmemb=0, arr[0] is %d\n", arr[0]);
|
||||
ok(arr[1] == 42, "badly sorted, nmemb=0, arr[1] is %d\n", arr[1]);
|
||||
ok(arr[2] == 8, "badly sorted, nmemb=0, arr[2] is %d\n", arr[2]);
|
||||
ok(arr[3] == 4, "badly sorted, nmemb=0, arr[3] is %d\n", arr[3]);
|
||||
ok(arr[4] == 16, "badly sorted, nmemb=0, arr[4] is %d\n", arr[4]);
|
||||
|
||||
p_qsort ((void*)arr, 1, sizeof(int), intcomparefunc);
|
||||
ok(arr[0] == 23, "badly sorted, nmemb=1, arr[0] is %d\n", arr[0]);
|
||||
ok(arr[1] == 42, "badly sorted, nmemb=1, arr[1] is %d\n", arr[1]);
|
||||
ok(arr[2] == 8, "badly sorted, nmemb=1, arr[2] is %d\n", arr[2]);
|
||||
ok(arr[3] == 4, "badly sorted, nmemb=1, arr[3] is %d\n", arr[3]);
|
||||
ok(arr[4] == 16, "badly sorted, nmemb=1, arr[4] is %d\n", arr[4]);
|
||||
|
||||
p_qsort ((void*)arr, 5, 0, intcomparefunc);
|
||||
ok(arr[0] == 23, "badly sorted, size=0, arr[0] is %d\n", arr[0]);
|
||||
ok(arr[1] == 42, "badly sorted, size=0, arr[1] is %d\n", arr[1]);
|
||||
ok(arr[2] == 8, "badly sorted, size=0, arr[2] is %d\n", arr[2]);
|
||||
ok(arr[3] == 4, "badly sorted, size=0, arr[3] is %d\n", arr[3]);
|
||||
ok(arr[4] == 16, "badly sorted, size=0, arr[4] is %d\n", arr[4]);
|
||||
|
||||
p_qsort ((void*)arr, 5, sizeof(int), intcomparefunc);
|
||||
ok(arr[0] == 4, "badly sorted, arr[0] is %d\n", arr[0]);
|
||||
ok(arr[1] == 8, "badly sorted, arr[1] is %d\n", arr[1]);
|
||||
|
@ -1241,6 +1294,8 @@ START_TEST(string)
|
|||
test_wcschr();
|
||||
if (p_wcsrchr)
|
||||
test_wcsrchr();
|
||||
if (p_wcslwr && p_wcsupr)
|
||||
test_wcslwrupr();
|
||||
if (patoi)
|
||||
test_atoi();
|
||||
if (patol)
|
||||
|
|
|
@ -18,6 +18,7 @@ extern void func_info(void);
|
|||
extern void func_large_int(void);
|
||||
extern void func_om(void);
|
||||
extern void func_path(void);
|
||||
extern void func_pipe(void);
|
||||
extern void func_port(void);
|
||||
extern void func_reg(void);
|
||||
extern void func_rtl(void);
|
||||
|
@ -40,6 +41,7 @@ const struct test winetest_testlist[] =
|
|||
{ "large_int", func_large_int },
|
||||
{ "om", func_om },
|
||||
{ "path", func_path },
|
||||
{ "pipe", func_pipe },
|
||||
{ "port", func_port },
|
||||
{ "reg", func_reg },
|
||||
{ "rtl", func_rtl },
|
||||
|
|
|
@ -39,7 +39,7 @@ static inline int IsLeapYear(int Year)
|
|||
}
|
||||
|
||||
/* start time of the tests */
|
||||
TIME_FIELDS tftest = {1889,12,31,23,59,59,0,0};
|
||||
static TIME_FIELDS tftest = {1889,12,31,23,59,59,0,0};
|
||||
|
||||
static void test_pRtlTimeToTimeFields(void)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue