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/CMakeList…
==============================================================================
--- 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?re…
==============================================================================
--- 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?re…
==============================================================================
--- 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=…
==============================================================================
--- 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?…
==============================================================================
--- 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();
+}