[NTDLL_WINETEST]

* Sync with Wine 1.7.1.

svn path=/trunk/; revision=60007
This commit is contained in:
Amine Khaldi 2013-09-10 16:49:44 +00:00
parent 515b54ee2a
commit ac467dd40b
6 changed files with 1080 additions and 62 deletions

View file

@ -32,4 +32,5 @@ add_importlibs(ntdll_winetest user32 msvcrt kernel32 ntdll)
add_cd_file(TARGET ntdll_winetest DESTINATION reactos/bin FOR all)
if(NOT MSVC)
allow_warnings(ntdll_winetest)
add_target_compile_flags(ntdll_winetest "-Wno-format")
endif()

View file

@ -162,11 +162,12 @@ static void tally_test_file(FILE_BOTH_DIRECTORY_INFORMATION *dir_info)
}
static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char *testdirA,
UNICODE_STRING *mask,
BOOLEAN single_entry, BOOLEAN restart_flag)
{
HANDLE dirh;
IO_STATUS_BLOCK io;
UINT data_pos;
UINT data_pos, data_size;
UINT data_len; /* length of dir data */
BYTE data[8192]; /* directory data */
FILE_BOTH_DIRECTORY_INFORMATION *dir_info;
@ -176,6 +177,8 @@ static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char
reset_found_files();
data_size = mask ? offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[256] ) : sizeof(data);
/* Read the directory and note which files are found */
status = pNtOpenFile( &dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, attr, &io, FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT|FILE_OPEN_FOR_BACKUP_INTENT|FILE_DIRECTORY_FILE);
@ -185,9 +188,9 @@ static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char
return;
}
pNtQueryDirectoryFile( dirh, NULL, NULL, NULL, &io, data, sizeof(data),
FileBothDirectoryInformation, single_entry, NULL, restart_flag );
ok (U(io).Status == STATUS_SUCCESS, "filed to query directory; status %x\n", U(io).Status);
pNtQueryDirectoryFile( dirh, NULL, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, single_entry, mask, restart_flag );
ok (U(io).Status == STATUS_SUCCESS, "failed 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");
@ -199,11 +202,11 @@ static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char
tally_test_file(dir_info);
if (dir_info->NextEntryOffset == 0) {
pNtQueryDirectoryFile( dirh, 0, NULL, NULL, &io, data, sizeof(data),
FileBothDirectoryInformation, single_entry, NULL, FALSE );
pNtQueryDirectoryFile( dirh, 0, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, single_entry, mask, 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);
ok (U(io).Status == STATUS_SUCCESS, "failed to query directory; status %x\n", U(io).Status);
data_len = io.Information;
if (data_len < sizeof(FILE_BOTH_DIRECTORY_INFORMATION))
break;
@ -215,10 +218,16 @@ static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char
}
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 (ReturnSingleEntry=%d,RestartScan=%d)\n",
testfiles[i].nfound, testfiles[i].description, single_entry, restart_flag);
if (mask)
for (i=0; testfiles[i].name; i++)
ok(testfiles[i].nfound == (testfiles[i].nameW == mask->Buffer),
"Wrong number %d of %s files found (single_entry=%d,mask=%s)\n",
testfiles[i].nfound, testfiles[i].description, single_entry,
wine_dbgstr_wn(mask->Buffer, mask->Length/sizeof(WCHAR) ));
else
for (i=0; testfiles[i].name; i++)
ok(testfiles[i].nfound == 1, "Wrong number %d of %s files found (single_entry=%d,restart=%d)\n",
testfiles[i].nfound, testfiles[i].description, single_entry, restart_flag);
pNtClose(dirh);
}
@ -228,6 +237,7 @@ static void test_NtQueryDirectoryFile(void)
UNICODE_STRING ntdirname;
char testdirA[MAX_PATH];
WCHAR testdirW[MAX_PATH];
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");
@ -243,10 +253,23 @@ static void test_NtQueryDirectoryFile(void)
}
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);
test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, FALSE, TRUE);
test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, FALSE, FALSE);
test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, TRUE, TRUE);
test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, TRUE, FALSE);
for (i = 0; testfiles[i].name; i++)
{
UNICODE_STRING mask;
if (testfiles[i].nameW[0] == '.') continue; /* . and .. as masks are broken on Windows */
mask.Buffer = testfiles[i].nameW;
mask.Length = mask.MaximumLength = lstrlenW(testfiles[i].nameW) * sizeof(WCHAR);
test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, FALSE, TRUE);
test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, FALSE, FALSE);
test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, TRUE, TRUE);
test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, TRUE, FALSE);
}
done:
tear_down_attribute_test(testdirA);

View file

@ -72,7 +72,7 @@ static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_AT
static NTSTATUS (WINAPI *pNtOpenIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
static NTSTATUS (WINAPI *pNtQueryIoCompletion)(HANDLE, IO_COMPLETION_INFORMATION_CLASS, PVOID, ULONG, PULONG);
static NTSTATUS (WINAPI *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER);
static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, ULONG);
static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, SIZE_T);
static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
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,
@ -81,7 +81,7 @@ static NTSTATUS (WINAPI *pNtQueryVolumeInformationFile)(HANDLE,PIO_STATUS_BLOCK,
static inline BOOL is_signaled( HANDLE obj )
{
return WaitForSingleObject( obj, 0 ) == 0;
return WaitForSingleObject( obj, 0 ) == WAIT_OBJECT_0;
}
#define PIPENAME "\\\\.\\pipe\\ntdll_tests_file.c"
@ -101,10 +101,11 @@ static BOOL create_pipe( HANDLE *read, HANDLE *write, ULONG flags, ULONG size )
static HANDLE create_temp_file( ULONG flags )
{
char buffer[MAX_PATH];
char path[MAX_PATH], buffer[MAX_PATH];
HANDLE handle;
GetTempFileNameA( ".", "foo", 0, buffer );
GetTempPathA( MAX_PATH, path );
GetTempFileNameA( path, "foo", 0, buffer );
handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
flags | FILE_FLAG_DELETE_ON_CLOSE, 0);
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
@ -505,7 +506,8 @@ static void read_file_test(void)
ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
ok( !apc_count, "apc was called\n" );
WriteFile( write, buffer, 1, &written, NULL );
ret = WriteFile( write, buffer, 1, &written, NULL );
ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
/* iosb updated here by async i/o */
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
@ -530,7 +532,8 @@ static void read_file_test(void)
ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
ok( !apc_count, "apc was called\n" );
WriteFile( write, buffer, 1, &written, NULL );
ret = WriteFile( write, buffer, 1, &written, NULL );
ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
/* iosb updated here by async i/o */
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
@ -548,7 +551,8 @@ static void read_file_test(void)
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
ResetEvent( event );
WriteFile( write, buffer, 1, &written, NULL );
ret = WriteFile( write, buffer, 1, &written, NULL );
ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
@ -571,7 +575,8 @@ static void read_file_test(void)
ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
ok( !apc_count, "apc was called\n" );
WriteFile( write, buffer, 1, &written, NULL );
ret = WriteFile( write, buffer, 1, &written, NULL );
ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
/* partial read is good enough */
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
ok( is_signaled( event ), "event is signaled\n" );
@ -777,6 +782,8 @@ static void read_file_test(void)
iosb.Information = 0xdeadbeef;
offset.QuadPart = strlen(text) + 2;
status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
todo_wine
ok(status == STATUS_PENDING || broken(status == STATUS_END_OF_FILE) /* before Vista */, "expected STATUS_PENDING, got %#x\n", status);
if (status == STATUS_PENDING) /* vista */
{
WaitForSingleObject( event, 1000 );
@ -787,16 +794,6 @@ static void read_file_test(void)
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc was not called\n" );
}
else
{
ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
ok( !is_signaled( event ), "event is signaled\n" );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( !apc_count, "apc was called\n" );
}
CloseHandle( handle );
/* now a non-overlapped file */
@ -859,9 +856,10 @@ static void append_file_test(void)
NTSTATUS status;
IO_STATUS_BLOCK iosb;
DWORD written;
char buffer[128];
char path[MAX_PATH], buffer[MAX_PATH];
GetTempFileNameA( ".", "foo", 0, buffer );
GetTempPathA( MAX_PATH, path );
GetTempFileNameA( path, "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,
@ -990,8 +988,11 @@ static void test_iocp_setcompletion(HANDLE h)
{
NTSTATUS res;
ULONG count;
SIZE_T size = 3;
res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, 3 );
if (sizeof(size) > 4) size |= (ULONGLONG)0x12345678 << 32;
res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size );
ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
count = get_pending_msgs(h);
@ -1000,7 +1001,7 @@ static void test_iocp_setcompletion(HANDLE h)
if (get_msg(h))
{
ok( completionKey == CKEY_FIRST, "Invalid completion key: %lx\n", completionKey );
ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
ok( ioSb.Information == size, "Invalid ioSb.Information: %lu\n", ioSb.Information );
ok( U(ioSb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
ok( completionValue == CVALUE_FIRST, "Invalid completion value: %lx\n", completionValue );
}
@ -1299,6 +1300,158 @@ static void test_file_both_information(void)
CloseHandle( h );
}
static void test_file_disposition_information(void)
{
char buffer[MAX_PATH + 16];
DWORD dirpos;
HANDLE handle, handle2;
NTSTATUS res;
IO_STATUS_BLOCK io;
FILE_DISPOSITION_INFORMATION fdi;
BOOL fileDeleted;
/* cannot set disposition on file not opened with delete access */
GetTempFileNameA( ".", "dis", 0, buffer );
handle = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
res = pNtQueryInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
ok( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "Unexpected NtQueryInformationFile result (expected STATUS_INVALID_INFO_CLASS, got %x)\n", res );
fdi.DoDeleteFile = TRUE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
todo_wine
ok( res == STATUS_ACCESS_DENIED, "unexpected FileDispositionInformation result (expected STATUS_ACCESS_DENIED, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "File shouldn't have been deleted\n" );
DeleteFileA( buffer );
/* can set disposition on file opened with proper access */
GetTempFileNameA( ".", "dis", 0, buffer );
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
fdi.DoDeleteFile = TRUE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
todo_wine
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
todo_wine
ok( fileDeleted, "File should have been deleted\n" );
DeleteFileA( buffer );
/* cannot set disposition on readonly file */
GetTempFileNameA( ".", "dis", 0, buffer );
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
fdi.DoDeleteFile = TRUE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
todo_wine
ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "File shouldn't have been deleted\n" );
SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
DeleteFileA( buffer );
/* can set disposition on file and then reset it */
GetTempFileNameA( ".", "dis", 0, buffer );
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
fdi.DoDeleteFile = TRUE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
todo_wine
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
fdi.DoDeleteFile = FALSE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
todo_wine
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "File shouldn't have been deleted\n" );
DeleteFileA( buffer );
/* Delete-on-close flag doesn't change file disposition until a handle is closed */
GetTempFileNameA( ".", "dis", 0, buffer );
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
fdi.DoDeleteFile = FALSE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
todo_wine
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( fileDeleted, "File should have been deleted\n" );
DeleteFileA( buffer );
/* Delete-on-close flag sets disposition when a handle is closed and then it could be changed back */
GetTempFileNameA( ".", "dis", 0, buffer );
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
ok( DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &handle2, 0, FALSE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
CloseHandle( handle );
fdi.DoDeleteFile = FALSE;
res = pNtSetInformationFile( handle2, &io, &fdi, sizeof fdi, FileDispositionInformation );
todo_wine
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
CloseHandle( handle2 );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( fileDeleted, "File should have been deleted\n" );
DeleteFileA( buffer );
/* can set disposition on a directory opened with proper access */
GetTempFileNameA( ".", "dis", 0, buffer );
DeleteFileA( buffer );
ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
fdi.DoDeleteFile = TRUE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
todo_wine
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
todo_wine
ok( fileDeleted, "Directory should have been deleted\n" );
RemoveDirectoryA( buffer );
/* RemoveDirectory sets directory disposition and it can be undone */
GetTempFileNameA( ".", "dis", 0, buffer );
DeleteFileA( buffer );
ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
RemoveDirectoryA( buffer );
fdi.DoDeleteFile = FALSE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
todo_wine
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
RemoveDirectoryA( buffer );
/* cannot set disposition on a non-empty directory */
GetTempFileNameA( ".", "dis", 0, buffer );
DeleteFileA( buffer );
ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
dirpos = lstrlenA( buffer );
lstrcpyA( buffer + dirpos, "\\tst" );
handle2 = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
CloseHandle( handle2 );
fdi.DoDeleteFile = TRUE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
todo_wine
ok( res == STATUS_DIRECTORY_NOT_EMPTY, "unexpected FileDispositionInformation result (expected STATUS_DIRECTORY_NOT_EMPTY, got %x)\n", res );
DeleteFileA( buffer );
buffer[dirpos] = '\0';
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
RemoveDirectoryA( buffer );
}
static void test_iocompletion(void)
{
HANDLE h = INVALID_HANDLE_VALUE;
@ -1634,6 +1787,52 @@ todo_wine
CloseHandle( dir );
}
static void test_query_attribute_information_file(void)
{
NTSTATUS status;
HANDLE dir;
WCHAR path[MAX_PATH];
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
UNICODE_STRING nameW;
FILE_FS_ATTRIBUTE_INFORMATION *ffai;
BYTE buf[sizeof(FILE_FS_ATTRIBUTE_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), FileFsAttributeInformation );
ffai = (FILE_FS_ATTRIBUTE_INFORMATION *)buf;
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(ffai->FileSystemAttribute != 0, "Missing FileSystemAttribute\n");
ok(ffai->MaximumComponentNameLength != 0, "Missing MaximumComponentNameLength\n");
ok(ffai->FileSystemNameLength != 0, "Missing FileSystemNameLength\n");
trace("FileSystemAttribute: %x MaximumComponentNameLength: %x FileSystemName: %s\n",
ffai->FileSystemAttribute, ffai->MaximumComponentNameLength,
wine_dbgstr_wn(ffai->FileSystemName, ffai->FileSystemNameLength / sizeof(WCHAR)));
CloseHandle( dir );
}
static void test_NtCreateFile(void)
{
static const struct test_data
@ -1662,7 +1861,6 @@ static void test_NtCreateFile(void)
/*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];
@ -1671,7 +1869,8 @@ static void test_NtCreateFile(void)
UNICODE_STRING nameW;
DWORD ret, i;
GetTempFileNameW(dotW, fooW, 0, path);
GetTempPathW(MAX_PATH, path);
GetTempFileNameW(path, fooW, 0, path);
DeleteFileW(path);
pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
@ -1720,6 +1919,420 @@ static void test_NtCreateFile(void)
DeleteFileW( path );
}
static void test_read_write(void)
{
static const char contents[] = "1234567890abcd";
char buf[256];
HANDLE hfile;
OVERLAPPED ovl;
IO_STATUS_BLOCK iob;
DWORD ret, bytes, status;
LARGE_INTEGER offset;
iob.Status = -1;
iob.Information = -1;
offset.QuadPart = 0;
status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
iob.Status = -1;
iob.Information = -1;
offset.QuadPart = 0;
status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
hfile = create_temp_file(0);
if (!hfile) return;
iob.Status = -1;
iob.Information = -1;
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#x\n", status);
ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
iob.Status = -1;
iob.Information = -1;
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
iob.Status = -1;
iob.Information = -1;
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), NULL, NULL);
ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
bytes = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
ok(ret, "ReadFile error %d\n", GetLastError());
ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
ok(bytes == 0, "bytes %u\n", bytes);
SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
bytes = 0;
SetLastError(0xdeadbeef);
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
ok(ret, "ReadFile error %d\n", GetLastError());
ok(bytes == sizeof(contents), "bytes %u\n", bytes);
ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
iob.Status = -1;
iob.Information = -1;
offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
bytes = 0;
SetLastError(0xdeadbeef);
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
ok(ret, "ReadFile error %d\n", GetLastError());
ok(bytes == sizeof(contents), "bytes %u\n", bytes);
ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
bytes = 0;
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
ok(bytes == sizeof(contents), "bytes %u\n", bytes);
iob.Status = -1;
iob.Information = -1;
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
todo_wine
ok(iob.Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", iob.Status);
todo_wine
ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
iob.Status = -1;
iob.Information = -1;
offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
todo_wine
ok(iob.Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", iob.Status);
todo_wine
ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
bytes = 0;
SetLastError(0xdeadbeef);
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
ok(ret, "ReadFile error %d\n", GetLastError());
ok(bytes == sizeof(contents), "bytes %u\n", bytes);
ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
iob.Status = -1;
iob.Information = -1;
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
todo_wine
ok(iob.Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", iob.Status);
todo_wine
ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
iob.Status = -1;
iob.Information = -1;
offset.QuadPart = 0;
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
iob.Status = -1;
iob.Information = -1;
offset.QuadPart = sizeof(contents) - 4;
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
iob.Status = -1;
iob.Information = -1;
offset.QuadPart = 0;
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
S(U(ovl)).Offset = sizeof(contents) - 4;
S(U(ovl)).OffsetHigh = 0;
ovl.hEvent = 0;
bytes = 0;
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
ok(ret, "WriteFile error %d\n", GetLastError());
ok(bytes == 4, "bytes %u\n", bytes);
S(U(ovl)).Offset = 0;
S(U(ovl)).OffsetHigh = 0;
ovl.Internal = -1;
ovl.InternalHigh = -1;
ovl.hEvent = 0;
bytes = 0;
SetLastError(0xdeadbeef);
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
ok(ret, "ReadFile error %d\n", GetLastError());
ok(bytes == sizeof(contents), "bytes %u\n", bytes);
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
CloseHandle(hfile);
hfile = create_temp_file(FILE_FLAG_OVERLAPPED);
if (!hfile) return;
bytes = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
todo_wine
ok(!ret, "WriteFile should fail\n");
todo_wine
ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
todo_wine
ok(bytes == 0, "bytes %u\n", bytes);
iob.Status = -1;
iob.Information = -1;
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), NULL, NULL);
todo_wine
ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
todo_wine
ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
todo_wine
ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
iob.Status = -1;
iob.Information = -1;
offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
todo_wine
ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
todo_wine
ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
todo_wine
ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
iob.Status = -1;
iob.Information = -1;
offset.QuadPart = 0;
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
todo_wine
ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* see below */, "expected STATUS_PENDING, got %#x\n", status);
ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
/* even fully updated XP passes this test, but it looks like some VMs
* in a testbot get never updated, so overlapped IO is broken. Instead
* of fighting with broken tests and adding a bunch of broken() statements
* it's better to skip further tests completely.
*/
if (status != STATUS_PENDING)
{
todo_wine
win_skip("broken overlapped IO implementation, update your OS\n");
CloseHandle(hfile);
return;
}
ret = WaitForSingleObject(hfile, 3000);
ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
bytes = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
ok(!ret, "ReadFile should fail\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
ok(bytes == 0, "bytes %u\n", bytes);
iob.Status = -1;
iob.Information = -1;
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
iob.Status = -1;
iob.Information = -1;
offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
offset.QuadPart = sizeof(contents);
S(U(ovl)).Offset = offset.u.LowPart;
S(U(ovl)).OffsetHigh = offset.u.HighPart;
ovl.Internal = -1;
ovl.InternalHigh = -1;
ovl.hEvent = 0;
bytes = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
ok(!ret, "ReadFile should fail\n");
ok(GetLastError() == ERROR_IO_PENDING || broken(GetLastError() == ERROR_HANDLE_EOF), "expected ERROR_IO_PENDING, got %d\n", GetLastError());
/* even fully updated XP passes this test, but it looks like some VMs
* in a testbot get never updated, so overlapped IO is broken. Instead
* of fighting with broken tests and adding a bunch of broken() statements
* it's better to skip further tests completely.
*/
if (GetLastError() != ERROR_IO_PENDING)
{
win_skip("broken overlapped IO implementation, update your OS\n");
CloseHandle(hfile);
return;
}
ok(bytes == 0, "bytes %u\n", bytes);
ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
bytes = 0xdeadbeef;
ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
ok(!ret, "GetOverlappedResult should report FALSE\n");
ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
ok(bytes == 0, "expected 0, read %u\n", bytes);
ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
iob.Status = -1;
iob.Information = -1;
offset.QuadPart = sizeof(contents);
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
ok(status == STATUS_PENDING, "expected STATUS_PENDING, got %#x\n", status);
ok(iob.Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", iob.Status);
ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
S(U(ovl)).Offset = offset.u.LowPart;
S(U(ovl)).OffsetHigh = offset.u.HighPart;
ovl.Internal = iob.Status;
ovl.InternalHigh = iob.Information;
ovl.hEvent = 0;
bytes = 0xdeadbeef;
ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
ok(!ret, "GetOverlappedResult should report FALSE\n");
ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
ok(bytes == 0, "expected 0, read %u\n", bytes);
ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
S(U(ovl)).Offset = 0;
S(U(ovl)).OffsetHigh = 0;
ovl.Internal = -1;
ovl.InternalHigh = -1;
ovl.hEvent = 0;
bytes = 0;
SetLastError(0xdeadbeef);
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
ok(!ret, "ReadFile should fail\n");
ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
ok(bytes == 0, "bytes %u\n", bytes);
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
bytes = 0xdeadbeef;
ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
ok(ret, "GetOverlappedResult error %d\n", GetLastError());
ok(bytes == sizeof(contents), "bytes %u\n", bytes);
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
iob.Status = -1;
iob.Information = -1;
offset.QuadPart = sizeof(contents) - 4;
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* before Vista */, "expected STATUS_PENDING, got %#x\n", status);
ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
ret = WaitForSingleObject(hfile, 3000);
ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
iob.Status = -1;
iob.Information = -1;
offset.QuadPart = 0;
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
ok(status == STATUS_PENDING, "expected STATUS_PENDING, got %#x\n", status);
ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
ret = WaitForSingleObject(hfile, 3000);
ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
S(U(ovl)).Offset = sizeof(contents) - 4;
S(U(ovl)).OffsetHigh = 0;
ovl.Internal = -1;
ovl.InternalHigh = -1;
ovl.hEvent = 0;
bytes = 0;
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
ok(!ret || broken(ret) /* before Vista */, "WriteFile should fail\n");
ok(GetLastError() == ERROR_IO_PENDING || broken(GetLastError() == 0xdeadbeef) /* before Vista */, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
ok(bytes == 0 || broken(bytes == 4) /* before Vista */, "bytes %u\n", bytes);
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
bytes = 0xdeadbeef;
ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
ok(ret, "GetOverlappedResult error %d\n", GetLastError());
ok(bytes == 4, "bytes %u\n", bytes);
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
S(U(ovl)).Offset = 0;
S(U(ovl)).OffsetHigh = 0;
ovl.Internal = -1;
ovl.InternalHigh = -1;
ovl.hEvent = 0;
bytes = 0;
SetLastError(0xdeadbeef);
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
ok(!ret, "ReadFile should fail\n");
ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
ok(bytes == 0, "bytes %u\n", bytes);
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
bytes = 0xdeadbeef;
ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
ok(ret, "GetOverlappedResult error %d\n", GetLastError());
ok(bytes == sizeof(contents), "bytes %u\n", bytes);
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
CloseHandle(hfile);
}
START_TEST(file)
{
HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
@ -1756,6 +2369,7 @@ START_TEST(file)
pNtQueryDirectoryFile = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
pNtQueryVolumeInformationFile = (void *)GetProcAddress(hntdll, "NtQueryVolumeInformationFile");
test_read_write();
test_NtCreateFile();
create_file_test();
open_file_test();
@ -1769,5 +2383,7 @@ START_TEST(file)
test_file_both_information();
test_file_name_information();
test_file_all_name_information();
test_file_disposition_information();
test_query_volume_information_file();
test_query_attribute_information_file();
}

View file

@ -505,18 +505,51 @@ static void test_query_cache(void)
{
NTSTATUS status;
ULONG ReturnLength;
SYSTEM_CACHE_INFORMATION sci;
BYTE buffer[128];
SYSTEM_CACHE_INFORMATION *sci = (SYSTEM_CACHE_INFORMATION *) buffer;
ULONG expected;
INT i;
status = pNtQuerySystemInformation(SystemCacheInformation, &sci, 0, &ReturnLength);
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
/* the large SYSTEM_CACHE_INFORMATION on WIN64 is not documented */
expected = sizeof(SYSTEM_CACHE_INFORMATION);
for (i = sizeof(buffer); i>= expected; i--)
{
ReturnLength = 0xdeadbeef;
status = pNtQuerySystemInformation(SystemCacheInformation, sci, i, &ReturnLength);
ok(!status && (ReturnLength == expected),
"%d: got 0x%x and %u (expected STATUS_SUCCESS and %u)\n", i, status, ReturnLength, expected);
}
status = pNtQuerySystemInformation(SystemCacheInformation, &sci, sizeof(sci), &ReturnLength);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
ok( sizeof(sci) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
/* buffer too small for the full result.
Up to win7, the function succeeds with a partial result. */
status = pNtQuerySystemInformation(SystemCacheInformation, sci, i, &ReturnLength);
if (!status)
{
expected = offsetof(SYSTEM_CACHE_INFORMATION, MinimumWorkingSet);
for (; i>= expected; i--)
{
ReturnLength = 0xdeadbeef;
status = pNtQuerySystemInformation(SystemCacheInformation, sci, i, &ReturnLength);
ok(!status && (ReturnLength == expected),
"%d: got 0x%x and %u (expected STATUS_SUCCESS and %u)\n", i, status, ReturnLength, expected);
}
}
status = pNtQuerySystemInformation(SystemCacheInformation, &sci, sizeof(sci) + 2, &ReturnLength);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
ok( sizeof(sci) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
/* buffer too small for the result, this call will always fail */
ReturnLength = 0xdeadbeef;
status = pNtQuerySystemInformation(SystemCacheInformation, sci, i, &ReturnLength);
ok( status == STATUS_INFO_LENGTH_MISMATCH &&
((ReturnLength == expected) || broken(!ReturnLength) || broken(ReturnLength == 0xfffffff0)),
"%d: got 0x%x and %u (expected STATUS_INFO_LENGTH_MISMATCH and %u)\n", i, status, ReturnLength, expected);
if (0) {
/* this crashes on some vista / win7 machines */
ReturnLength = 0xdeadbeef;
status = pNtQuerySystemInformation(SystemCacheInformation, sci, 0, &ReturnLength);
ok( status == STATUS_INFO_LENGTH_MISMATCH &&
((ReturnLength == expected) || broken(!ReturnLength) || broken(ReturnLength == 0xfffffff0)),
"0: got 0x%x and %u (expected STATUS_INFO_LENGTH_MISMATCH and %u)\n", status, ReturnLength, expected);
}
}
static void test_query_interrupt(void)

View file

@ -30,6 +30,9 @@ static NTSTATUS (WINAPI *pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPC
static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
static VOID (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
static NTSTATUS (WINAPI *pNtCreateEvent) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, BOOLEAN, BOOLEAN);
static NTSTATUS (WINAPI *pNtOpenEvent) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES);
static NTSTATUS (WINAPI *pNtPulseEvent) ( HANDLE, PULONG );
static NTSTATUS (WINAPI *pNtQueryEvent) ( HANDLE, EVENT_INFORMATION_CLASS, PVOID, ULONG, PULONG );
static NTSTATUS (WINAPI *pNtCreateMutant)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, BOOLEAN );
static NTSTATUS (WINAPI *pNtOpenMutant) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES );
static NTSTATUS (WINAPI *pNtCreateSemaphore)( PHANDLE, ACCESS_MASK,const POBJECT_ATTRIBUTES,LONG,LONG );
@ -46,8 +49,15 @@ 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 NTSTATUS (WINAPI *pNtReleaseSemaphore)(HANDLE, ULONG, PULONG);
static NTSTATUS (WINAPI *pNtCreateKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, ULONG );
static NTSTATUS (WINAPI *pNtOpenKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES * );
static NTSTATUS (WINAPI *pNtWaitForKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
static NTSTATUS (WINAPI *pNtReleaseKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
#define KEYEDEVENT_WAIT 0x0001
#define KEYEDEVENT_WAKE 0x0002
#define KEYEDEVENT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x0003)
static void test_case_sensitive (void)
{
@ -798,6 +808,230 @@ static void test_type_mismatch(void)
pNtClose( h );
}
static void test_event(void)
{
HANDLE Event;
HANDLE Event2;
NTSTATUS status;
UNICODE_STRING str;
OBJECT_ATTRIBUTES attr;
EVENT_BASIC_INFORMATION info;
static const WCHAR eventName[] = {'\\','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',0};
pRtlInitUnicodeString(&str, eventName);
InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, 1, 0);
ok( status == STATUS_SUCCESS, "NtCreateEvent failed %08x\n", status );
status = pNtPulseEvent(Event, NULL);
ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status );
status = pNtQueryEvent(Event, EventBasicInformation, &info, sizeof(info), NULL);
ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
ok( info.EventType == 1 && info.EventState == 0,
"NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType, info.EventState );
status = pNtOpenEvent(&Event2, GENERIC_ALL, &attr);
ok( status == STATUS_SUCCESS, "NtOpenEvent failed %08x\n", status );
status = pNtClose(Event);
status = pNtQueryEvent(Event2, EventBasicInformation, &info, sizeof(info), NULL);
ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
ok( info.EventType == 1 && info.EventState == 0,
"NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType, info.EventState );
status = pNtClose(Event2);
}
static const WCHAR keyed_nameW[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s',
'\\','W','i','n','e','T','e','s','t','E','v','e','n','t',0};
static DWORD WINAPI keyed_event_thread( void *arg )
{
HANDLE handle;
NTSTATUS status;
LARGE_INTEGER timeout;
OBJECT_ATTRIBUTES attr;
UNICODE_STRING str;
ULONG_PTR i;
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.ObjectName = &str;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
RtlInitUnicodeString( &str, keyed_nameW );
status = pNtOpenKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS, &attr );
ok( !status, "NtOpenKeyedEvent failed %x\n", status );
for (i = 0; i < 20; i++)
{
if (i & 1)
status = pNtWaitForKeyedEvent( handle, (void *)(i * 2), 0, NULL );
else
status = pNtReleaseKeyedEvent( handle, (void *)(i * 2), 0, NULL );
ok( status == STATUS_SUCCESS, "%li: failed %x\n", i, status );
Sleep( 20 - i );
}
status = pNtReleaseKeyedEvent( handle, (void *)0x1234, 0, NULL );
ok( status == STATUS_SUCCESS, "NtReleaseKeyedEvent %x\n", status );
timeout.QuadPart = -10000;
status = pNtWaitForKeyedEvent( handle, (void *)0x5678, 0, &timeout );
ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
status = pNtReleaseKeyedEvent( handle, (void *)0x9abc, 0, &timeout );
ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
NtClose( handle );
return 0;
}
static void test_keyed_events(void)
{
OBJECT_ATTRIBUTES attr;
UNICODE_STRING str;
HANDLE handle, event, thread;
NTSTATUS status;
LARGE_INTEGER timeout;
ULONG_PTR i;
if (!pNtCreateKeyedEvent)
{
win_skip( "Keyed events not supported\n" );
return;
}
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.ObjectName = &str;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
RtlInitUnicodeString( &str, keyed_nameW );
status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS | SYNCHRONIZE, &attr, 0 );
ok( !status, "NtCreateKeyedEvent failed %x\n", status );
status = WaitForSingleObject( handle, 1000 );
ok( status == 0, "WaitForSingleObject %x\n", status );
timeout.QuadPart = -100000;
status = pNtWaitForKeyedEvent( handle, (void *)255, 0, &timeout );
ok( status == STATUS_INVALID_PARAMETER_1, "NtWaitForKeyedEvent %x\n", status );
status = pNtReleaseKeyedEvent( handle, (void *)255, 0, &timeout );
ok( status == STATUS_INVALID_PARAMETER_1, "NtReleaseKeyedEvent %x\n", status );
status = pNtWaitForKeyedEvent( handle, (void *)254, 0, &timeout );
ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
status = pNtReleaseKeyedEvent( handle, (void *)254, 0, &timeout );
ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
status = pNtWaitForKeyedEvent( handle, NULL, 0, &timeout );
ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
status = pNtReleaseKeyedEvent( handle, NULL, 0, &timeout );
ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
status = pNtWaitForKeyedEvent( (HANDLE)0xdeadbeef, (void *)9, 0, &timeout );
ok( status == STATUS_INVALID_PARAMETER_1, "NtWaitForKeyedEvent %x\n", status );
status = pNtReleaseKeyedEvent( (HANDLE)0xdeadbeef, (void *)9, 0, &timeout );
ok( status == STATUS_INVALID_PARAMETER_1, "NtReleaseKeyedEvent %x\n", status );
status = pNtWaitForKeyedEvent( (HANDLE)0xdeadbeef, (void *)8, 0, &timeout );
ok( status == STATUS_INVALID_HANDLE, "NtWaitForKeyedEvent %x\n", status );
status = pNtReleaseKeyedEvent( (HANDLE)0xdeadbeef, (void *)8, 0, &timeout );
ok( status == STATUS_INVALID_HANDLE, "NtReleaseKeyedEvent %x\n", status );
thread = CreateThread( NULL, 0, keyed_event_thread, 0, 0, NULL );
for (i = 0; i < 20; i++)
{
if (i & 1)
status = pNtReleaseKeyedEvent( handle, (void *)(i * 2), 0, NULL );
else
status = pNtWaitForKeyedEvent( handle, (void *)(i * 2), 0, NULL );
ok( status == STATUS_SUCCESS, "%li: failed %x\n", i, status );
Sleep( i );
}
status = pNtWaitForKeyedEvent( handle, (void *)0x1234, 0, &timeout );
ok( status == STATUS_SUCCESS, "NtWaitForKeyedEvent %x\n", status );
status = pNtWaitForKeyedEvent( handle, (void *)0x5678, 0, &timeout );
ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
status = pNtReleaseKeyedEvent( handle, (void *)0x9abc, 0, &timeout );
ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
ok( WaitForSingleObject( thread, 30000 ) == 0, "wait failed\n" );
NtClose( handle );
/* test access rights */
status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_WAIT, &attr, 0 );
ok( !status, "NtCreateKeyedEvent failed %x\n", status );
status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
ok( status == STATUS_ACCESS_DENIED, "NtReleaseKeyedEvent %x\n", status );
NtClose( handle );
status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_WAKE, &attr, 0 );
ok( !status, "NtCreateKeyedEvent failed %x\n", status );
status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
ok( status == STATUS_ACCESS_DENIED, "NtWaitForKeyedEvent %x\n", status );
status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
NtClose( handle );
status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS, &attr, 0 );
ok( !status, "NtCreateKeyedEvent failed %x\n", status );
status = WaitForSingleObject( handle, 1000 );
ok( status == WAIT_FAILED && GetLastError() == ERROR_ACCESS_DENIED,
"WaitForSingleObject %x err %u\n", status, GetLastError() );
status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
NtClose( handle );
/* GENERIC_READ gives wait access */
status = pNtCreateKeyedEvent( &handle, GENERIC_READ, &attr, 0 );
ok( !status, "NtCreateKeyedEvent failed %x\n", status );
status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
ok( status == STATUS_ACCESS_DENIED, "NtReleaseKeyedEvent %x\n", status );
NtClose( handle );
/* GENERIC_WRITE gives wake access */
status = pNtCreateKeyedEvent( &handle, GENERIC_WRITE, &attr, 0 );
ok( !status, "NtCreateKeyedEvent failed %x\n", status );
status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
ok( status == STATUS_ACCESS_DENIED, "NtWaitForKeyedEvent %x\n", status );
status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
/* it's not an event */
status = pNtPulseEvent( handle, NULL );
ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtPulseEvent %x\n", status );
status = pNtCreateEvent( &event, GENERIC_ALL, &attr, FALSE, FALSE );
ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_OBJECT_TYPE_MISMATCH,
"CreateEvent %x\n", status );
NtClose( handle );
status = pNtCreateEvent( &event, GENERIC_ALL, &attr, FALSE, FALSE );
ok( status == 0, "CreateEvent %x\n", status );
status = pNtWaitForKeyedEvent( event, (void *)8, 0, &timeout );
ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtWaitForKeyedEvent %x\n", status );
status = pNtReleaseKeyedEvent( event, (void *)8, 0, &timeout );
ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtReleaseKeyedEvent %x\n", status );
NtClose( event );
}
START_TEST(om)
{
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
@ -815,6 +1049,9 @@ START_TEST(om)
pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
pNtCreateEvent = (void *)GetProcAddress(hntdll, "NtCreateEvent");
pNtCreateMutant = (void *)GetProcAddress(hntdll, "NtCreateMutant");
pNtOpenEvent = (void *)GetProcAddress(hntdll, "NtOpenEvent");
pNtQueryEvent = (void *)GetProcAddress(hntdll, "NtQueryEvent");
pNtPulseEvent = (void *)GetProcAddress(hntdll, "NtPulseEvent");
pNtOpenMutant = (void *)GetProcAddress(hntdll, "NtOpenMutant");
pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
@ -830,6 +1067,10 @@ START_TEST(om)
pNtCreateSection = (void *)GetProcAddress(hntdll, "NtCreateSection");
pNtQueryObject = (void *)GetProcAddress(hntdll, "NtQueryObject");
pNtReleaseSemaphore = (void *)GetProcAddress(hntdll, "NtReleaseSemaphore");
pNtCreateKeyedEvent = (void *)GetProcAddress(hntdll, "NtCreateKeyedEvent");
pNtOpenKeyedEvent = (void *)GetProcAddress(hntdll, "NtOpenKeyedEvent");
pNtWaitForKeyedEvent = (void *)GetProcAddress(hntdll, "NtWaitForKeyedEvent");
pNtReleaseKeyedEvent = (void *)GetProcAddress(hntdll, "NtReleaseKeyedEvent");
test_case_sensitive();
test_namespace_pipe();
@ -838,4 +1079,9 @@ START_TEST(om)
test_symboliclink();
test_query_object();
test_type_mismatch();
test_event();
if (winetest_interactive)
test_keyed_events();
else
skip("Skipping test_keyed_events(). ROSTESTS-118.\n");
}

View file

@ -30,6 +30,9 @@
#include "winnls.h"
#include "guiddef.h"
#define HASH_STRING_ALGORITHM_X65599 1
#define HASH_STRING_ALGORITHM_INVALID 0xffffffff
/* Function ptrs for ntdll calls */
static HMODULE hntdll = 0;
static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING, PCANSI_STRING, BOOLEAN);
@ -64,6 +67,7 @@ static NTSTATUS (WINAPI *pRtlValidateUnicodeString)(LONG, UNICODE_STRING *);
static NTSTATUS (WINAPI *pRtlGUIDFromString)(const UNICODE_STRING*,GUID*);
static NTSTATUS (WINAPI *pRtlStringFromGUID)(const GUID*, UNICODE_STRING*);
static BOOLEAN (WINAPI *pRtlIsTextUnicode)(LPVOID, INT, INT *);
static NTSTATUS (WINAPI *pRtlHashUnicodeString)(PCUNICODE_STRING,BOOLEAN,ULONG,ULONG*);
/*static VOID (WINAPI *pRtlFreeOemString)(PSTRING);*/
/*static VOID (WINAPI *pRtlCopyUnicodeString)(UNICODE_STRING *, const UNICODE_STRING *);*/
@ -132,10 +136,10 @@ static void InitFunctionPtrs(void)
pRtlGUIDFromString = (void *)GetProcAddress(hntdll, "RtlGUIDFromString");
pRtlStringFromGUID = (void *)GetProcAddress(hntdll, "RtlStringFromGUID");
pRtlIsTextUnicode = (void *)GetProcAddress(hntdll, "RtlIsTextUnicode");
pRtlHashUnicodeString = (void*)GetProcAddress(hntdll, "RtlHashUnicodeString");
}
}
static void test_RtlInitString(void)
{
static const char teststring[] = "Some Wild String";
@ -192,6 +196,12 @@ static void test_RtlInitUnicodeStringEx(void)
UNICODE_STRING uni;
NTSTATUS result;
if (!pRtlInitUnicodeStringEx)
{
win_skip("RtlInitUnicodeStringEx is not available\n");
return;
}
teststring2 = HeapAlloc(GetProcessHeap(), 0, (TESTSTRING2_LEN + 1) * sizeof(WCHAR));
memset(teststring2, 'X', TESTSTRING2_LEN * sizeof(WCHAR));
teststring2[TESTSTRING2_LEN] = '\0';
@ -406,6 +416,12 @@ static void test_RtlDuplicateUnicodeString(void)
NTSTATUS result;
unsigned int test_num;
if (!pRtlDuplicateUnicodeString)
{
win_skip("RtlDuplicateUnicodeString is not available\n");
return;
}
for (test_num = 0; test_num < NB_DUPL_USTR; test_num++) {
source_str.Length = dupl_ustr[test_num].source_Length;
source_str.MaximumLength = dupl_ustr[test_num].source_MaximumLength;
@ -1180,6 +1196,12 @@ static void test_RtlFindCharInUnicodeString(void)
unsigned int idx;
unsigned int test_num;
if (!pRtlFindCharInUnicodeString)
{
win_skip("RtlFindCharInUnicodeString is not available\n");
return;
}
for (test_num = 0; test_num < NB_FIND_CH_IN_USTR; test_num++) {
if (find_ch_in_ustr[test_num].main_str != NULL) {
main_str.Length = strlen(find_ch_in_ustr[test_num].main_str) * sizeof(WCHAR);
@ -1710,6 +1732,12 @@ static void test_RtlIsTextUnicode(void)
int flags;
int i;
if (!pRtlIsTextUnicode)
{
win_skip("RtlIsTextUnicode is not available\n");
return;
}
ok(!pRtlIsTextUnicode(ascii, sizeof(ascii), NULL), "ASCII text detected as Unicode\n");
res = pRtlIsTextUnicode(unicode, sizeof(unicode), NULL);
@ -1839,6 +1867,12 @@ static void test_RtlGUIDFromString(void)
UNICODE_STRING str;
NTSTATUS ret;
if (!pRtlGUIDFromString)
{
win_skip("RtlGUIDFromString is not available\n");
return;
}
str.Length = str.MaximumLength = sizeof(szGuid) - sizeof(WCHAR);
str.Buffer = (LPWSTR)szGuid;
@ -1858,6 +1892,12 @@ static void test_RtlStringFromGUID(void)
UNICODE_STRING str;
NTSTATUS ret;
if (!pRtlStringFromGUID)
{
win_skip("RtlStringFromGUID is not available\n");
return;
}
str.Length = str.MaximumLength = 0;
str.Buffer = NULL;
@ -1867,6 +1907,70 @@ static void test_RtlStringFromGUID(void)
pRtlFreeUnicodeString(&str);
}
struct hash_unicodestring_test {
WCHAR str[50];
BOOLEAN case_insensitive;
ULONG hash;
};
static const struct hash_unicodestring_test hash_test[] = {
{ {'T',0}, FALSE, 0x00000054 },
{ {'T','e','s','t',0}, FALSE, 0x766bb952 },
{ {'T','e','S','t',0}, FALSE, 0x764bb172 },
{ {'t','e','s','t',0}, FALSE, 0x4745d132 },
{ {'t','e','s','t',0}, TRUE, 0x6689c132 },
{ {'T','E','S','T',0}, TRUE, 0x6689c132 },
{ {'T','E','S','T',0}, FALSE, 0x6689c132 },
{ {'a','b','c','d','e','f',0}, FALSE, 0x971318c3 },
{ { 0 } }
};
static void test_RtlHashUnicodeString(void)
{
static const WCHAR strW[] = {'T','e','s','t',0,'1',0};
const struct hash_unicodestring_test *ptr;
UNICODE_STRING str;
NTSTATUS status;
ULONG hash;
if (!pRtlHashUnicodeString)
{
win_skip("RtlHashUnicodeString is not available\n");
return;
}
status = pRtlHashUnicodeString(NULL, FALSE, HASH_STRING_ALGORITHM_X65599, &hash);
ok(status == STATUS_INVALID_PARAMETER, "got status 0x%08x\n", status);
RtlInitUnicodeString(&str, strW);
status = pRtlHashUnicodeString(&str, FALSE, HASH_STRING_ALGORITHM_X65599, NULL);
ok(status == STATUS_INVALID_PARAMETER, "got status 0x%08x\n", status);
status = pRtlHashUnicodeString(&str, FALSE, HASH_STRING_ALGORITHM_INVALID, &hash);
ok(status == STATUS_INVALID_PARAMETER, "got status 0x%08x\n", status);
/* embedded null */
str.Buffer = (PWSTR)strW;
str.Length = sizeof(strW) - sizeof(WCHAR);
str.MaximumLength = sizeof(strW);
status = pRtlHashUnicodeString(&str, FALSE, HASH_STRING_ALGORITHM_X65599, &hash);
ok(status == STATUS_SUCCESS, "got status 0x%08x\n", status);
ok(hash == 0x32803083, "got 0x%08x\n", hash);
ptr = hash_test;
while (*ptr->str)
{
RtlInitUnicodeString(&str, ptr->str);
hash = 0;
status = pRtlHashUnicodeString(&str, ptr->case_insensitive, HASH_STRING_ALGORITHM_X65599, &hash);
ok(status == STATUS_SUCCESS, "got status 0x%08x for %s\n", status, wine_dbgstr_w(ptr->str));
ok(hash == ptr->hash, "got wrong hash 0x%08x, expected 0x%08x, for %s, mode %d\n", hash, ptr->hash,
wine_dbgstr_w(ptr->str), ptr->case_insensitive);
ptr++;
}
}
START_TEST(rtlstr)
{
InitFunctionPtrs();
@ -1887,22 +1991,17 @@ START_TEST(rtlstr)
test_RtlAppendUnicodeStringToString();
}
if (pRtlInitUnicodeStringEx)
test_RtlInitUnicodeStringEx();
if (pRtlDuplicateUnicodeString)
test_RtlDuplicateUnicodeString();
if (pRtlFindCharInUnicodeString)
test_RtlFindCharInUnicodeString();
if (pRtlGUIDFromString)
test_RtlGUIDFromString();
if (pRtlStringFromGUID)
test_RtlStringFromGUID();
if (pRtlIsTextUnicode)
test_RtlIsTextUnicode();
test_RtlInitUnicodeStringEx();
test_RtlDuplicateUnicodeString();
test_RtlFindCharInUnicodeString();
test_RtlGUIDFromString();
test_RtlStringFromGUID();
test_RtlIsTextUnicode();
if(0)
{
test_RtlUpcaseUnicodeChar();
test_RtlUpcaseUnicodeString();
test_RtlDowncaseUnicodeString();
}
test_RtlHashUnicodeString();
}