[NTDLL_WINETEST]

* Sync with Wine 1.3.29.

svn path=/trunk/; revision=53975
This commit is contained in:
Amine Khaldi 2011-10-03 19:29:29 +00:00
parent 421109a7e3
commit 4aec35aa7b
21 changed files with 1687 additions and 151 deletions

View file

@ -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

View file

@ -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");

View file

@ -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)
{

View file

@ -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);

View file

@ -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 );

View file

@ -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);

View file

@ -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;
}

View file

@ -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();
}

View 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();
}

View file

@ -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 */

View file

@ -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>

View 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();
}

View 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();
}

View file

@ -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 ||

View file

@ -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 );

View file

@ -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();
}

View file

@ -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 ||

View file

@ -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);
}

View file

@ -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)

View file

@ -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 },

View file

@ -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)
{