Author: akhaldi Date: Tue Sep 10 16:49:44 2013 New Revision: 60007
URL: http://svn.reactos.org/svn/reactos?rev=60007&view=rev Log: [NTDLL_WINETEST] * Sync with Wine 1.7.1.
Modified: trunk/rostests/winetests/ntdll/CMakeLists.txt trunk/rostests/winetests/ntdll/directory.c trunk/rostests/winetests/ntdll/file.c trunk/rostests/winetests/ntdll/info.c trunk/rostests/winetests/ntdll/om.c trunk/rostests/winetests/ntdll/rtlstr.c
Modified: trunk/rostests/winetests/ntdll/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ntdll/CMakeLists... ============================================================================== --- trunk/rostests/winetests/ntdll/CMakeLists.txt [iso-8859-1] (original) +++ trunk/rostests/winetests/ntdll/CMakeLists.txt [iso-8859-1] Tue Sep 10 16:49:44 2013 @@ -32,4 +32,5 @@ 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()
Modified: trunk/rostests/winetests/ntdll/directory.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ntdll/directory.... ============================================================================== --- trunk/rostests/winetests/ntdll/directory.c [iso-8859-1] (original) +++ trunk/rostests/winetests/ntdll/directory.c [iso-8859-1] Tue Sep 10 16:49:44 2013 @@ -162,11 +162,12 @@ }
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; @@ -175,6 +176,8 @@ int i;
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, @@ -185,9 +188,9 @@ 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 @@ 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 @@ } 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 @@ 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 @@ } 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);
Modified: trunk/rostests/winetests/ntdll/file.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ntdll/file.c?rev... ============================================================================== --- trunk/rostests/winetests/ntdll/file.c [iso-8859-1] (original) +++ trunk/rostests/winetests/ntdll/file.c [iso-8859-1] Tue Sep 10 16:49:44 2013 @@ -72,7 +72,7 @@ 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 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 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 ); @@ -786,16 +793,6 @@ ok( !apc_count, "apc was called\n" ); 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 );
@@ -859,9 +856,10 @@ NTSTATUS status; IO_STATUS_BLOCK iosb; DWORD written; - char buffer[128]; - - GetTempFileNameA( ".", "foo", 0, buffer ); + char path[MAX_PATH], buffer[MAX_PATH]; + + 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 @@ { NTSTATUS res; ULONG count; - - res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, 3 ); + SIZE_T size = 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 @@ 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 @@ 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; @@ -1630,6 +1783,52 @@ 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_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 ); } @@ -1662,7 +1861,6 @@ /*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 @@ 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);
@@ -1718,6 +1917,420 @@
SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE); 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) @@ -1756,6 +2369,7 @@ 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 @@ 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(); +}
Modified: trunk/rostests/winetests/ntdll/info.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ntdll/info.c?rev... ============================================================================== --- trunk/rostests/winetests/ntdll/info.c [iso-8859-1] (original) +++ trunk/rostests/winetests/ntdll/info.c [iso-8859-1] Tue Sep 10 16:49:44 2013 @@ -505,18 +505,51 @@ { NTSTATUS status; ULONG ReturnLength; - SYSTEM_CACHE_INFORMATION sci; - - status = pNtQuerySystemInformation(SystemCacheInformation, &sci, 0, &ReturnLength); - ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status); - - 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); - - 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); + BYTE buffer[128]; + SYSTEM_CACHE_INFORMATION *sci = (SYSTEM_CACHE_INFORMATION *) buffer; + ULONG expected; + INT i; + + /* 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); + } + + /* 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); + } + } + + /* 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)
Modified: trunk/rostests/winetests/ntdll/om.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ntdll/om.c?rev=6... ============================================================================== --- trunk/rostests/winetests/ntdll/om.c [iso-8859-1] (original) +++ trunk/rostests/winetests/ntdll/om.c [iso-8859-1] Tue Sep 10 16:49:44 2013 @@ -30,6 +30,9 @@ 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 *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 @@ 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 @@ 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 @@ 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 @@ 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"); +}
Modified: trunk/rostests/winetests/ntdll/rtlstr.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ntdll/rtlstr.c?r... ============================================================================== --- trunk/rostests/winetests/ntdll/rtlstr.c [iso-8859-1] (original) +++ trunk/rostests/winetests/ntdll/rtlstr.c [iso-8859-1] Tue Sep 10 16:49:44 2013 @@ -29,6 +29,9 @@ #include "ntdll_test.h" #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; @@ -64,6 +67,7 @@ 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,9 +136,9 @@ 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) { @@ -191,6 +195,12 @@ WCHAR *teststring2; 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)); @@ -406,6 +416,12 @@ 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; @@ -1179,6 +1195,12 @@ NTSTATUS result; 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) { @@ -1710,6 +1732,12 @@ 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 @@ 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;
@@ -1857,6 +1891,12 @@ { UNICODE_STRING str; NTSTATUS ret; + + if (!pRtlStringFromGUID) + { + win_skip("RtlStringFromGUID is not available\n"); + return; + }
str.Length = str.MaximumLength = 0; str.Buffer = NULL; @@ -1865,6 +1905,70 @@ ok(ret == 0, "expected ret=0, got 0x%0x\n", ret); ok(str.Buffer && !lstrcmpiW(str.Buffer, szGuid), "Endianness broken\n"); 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) @@ -1887,22 +1991,17 @@ 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(); +}