mirror of
https://github.com/reactos/reactos.git
synced 2025-05-06 10:28:45 +00:00
[NTDLL_WINETEST]
* Sync with Wine 1.7.1. svn path=/trunk/; revision=60007
This commit is contained in:
parent
515b54ee2a
commit
ac467dd40b
6 changed files with 1080 additions and 62 deletions
|
@ -32,4 +32,5 @@ add_importlibs(ntdll_winetest user32 msvcrt kernel32 ntdll)
|
|||
add_cd_file(TARGET ntdll_winetest DESTINATION reactos/bin FOR all)
|
||||
if(NOT MSVC)
|
||||
allow_warnings(ntdll_winetest)
|
||||
add_target_compile_flags(ntdll_winetest "-Wno-format")
|
||||
endif()
|
||||
|
|
|
@ -162,11 +162,12 @@ static void tally_test_file(FILE_BOTH_DIRECTORY_INFORMATION *dir_info)
|
|||
}
|
||||
|
||||
static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char *testdirA,
|
||||
UNICODE_STRING *mask,
|
||||
BOOLEAN single_entry, BOOLEAN restart_flag)
|
||||
{
|
||||
HANDLE dirh;
|
||||
IO_STATUS_BLOCK io;
|
||||
UINT data_pos;
|
||||
UINT data_pos, data_size;
|
||||
UINT data_len; /* length of dir data */
|
||||
BYTE data[8192]; /* directory data */
|
||||
FILE_BOTH_DIRECTORY_INFORMATION *dir_info;
|
||||
|
@ -176,6 +177,8 @@ static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char
|
|||
|
||||
reset_found_files();
|
||||
|
||||
data_size = mask ? offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[256] ) : sizeof(data);
|
||||
|
||||
/* Read the directory and note which files are found */
|
||||
status = pNtOpenFile( &dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, attr, &io, FILE_OPEN,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT|FILE_OPEN_FOR_BACKUP_INTENT|FILE_DIRECTORY_FILE);
|
||||
|
@ -185,9 +188,9 @@ static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char
|
|||
return;
|
||||
}
|
||||
|
||||
pNtQueryDirectoryFile( dirh, NULL, NULL, NULL, &io, data, sizeof(data),
|
||||
FileBothDirectoryInformation, single_entry, NULL, restart_flag );
|
||||
ok (U(io).Status == STATUS_SUCCESS, "filed to query directory; status %x\n", U(io).Status);
|
||||
pNtQueryDirectoryFile( dirh, NULL, NULL, NULL, &io, data, data_size,
|
||||
FileBothDirectoryInformation, single_entry, mask, restart_flag );
|
||||
ok (U(io).Status == STATUS_SUCCESS, "failed to query directory; status %x\n", U(io).Status);
|
||||
data_len = io.Information;
|
||||
ok (data_len >= sizeof(FILE_BOTH_DIRECTORY_INFORMATION), "not enough data in directory\n");
|
||||
|
||||
|
@ -199,11 +202,11 @@ static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char
|
|||
tally_test_file(dir_info);
|
||||
|
||||
if (dir_info->NextEntryOffset == 0) {
|
||||
pNtQueryDirectoryFile( dirh, 0, NULL, NULL, &io, data, sizeof(data),
|
||||
FileBothDirectoryInformation, single_entry, NULL, FALSE );
|
||||
pNtQueryDirectoryFile( dirh, 0, NULL, NULL, &io, data, data_size,
|
||||
FileBothDirectoryInformation, single_entry, mask, FALSE );
|
||||
if (U(io).Status == STATUS_NO_MORE_FILES)
|
||||
break;
|
||||
ok (U(io).Status == STATUS_SUCCESS, "filed to query directory; status %x\n", U(io).Status);
|
||||
ok (U(io).Status == STATUS_SUCCESS, "failed to query directory; status %x\n", U(io).Status);
|
||||
data_len = io.Information;
|
||||
if (data_len < sizeof(FILE_BOTH_DIRECTORY_INFORMATION))
|
||||
break;
|
||||
|
@ -215,10 +218,16 @@ static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char
|
|||
}
|
||||
ok(numfiles < max_test_dir_size, "too many loops\n");
|
||||
|
||||
for (i=0; testfiles[i].name; i++)
|
||||
ok(testfiles[i].nfound == 1, "Wrong number %d of %s files found (ReturnSingleEntry=%d,RestartScan=%d)\n",
|
||||
testfiles[i].nfound, testfiles[i].description, single_entry, restart_flag);
|
||||
|
||||
if (mask)
|
||||
for (i=0; testfiles[i].name; i++)
|
||||
ok(testfiles[i].nfound == (testfiles[i].nameW == mask->Buffer),
|
||||
"Wrong number %d of %s files found (single_entry=%d,mask=%s)\n",
|
||||
testfiles[i].nfound, testfiles[i].description, single_entry,
|
||||
wine_dbgstr_wn(mask->Buffer, mask->Length/sizeof(WCHAR) ));
|
||||
else
|
||||
for (i=0; testfiles[i].name; i++)
|
||||
ok(testfiles[i].nfound == 1, "Wrong number %d of %s files found (single_entry=%d,restart=%d)\n",
|
||||
testfiles[i].nfound, testfiles[i].description, single_entry, restart_flag);
|
||||
pNtClose(dirh);
|
||||
}
|
||||
|
||||
|
@ -228,6 +237,7 @@ static void test_NtQueryDirectoryFile(void)
|
|||
UNICODE_STRING ntdirname;
|
||||
char testdirA[MAX_PATH];
|
||||
WCHAR testdirW[MAX_PATH];
|
||||
int i;
|
||||
|
||||
/* Clean up from prior aborted run, if any, then set up test files */
|
||||
ok(GetTempPathA(MAX_PATH, testdirA), "couldn't get temp dir\n");
|
||||
|
@ -243,10 +253,23 @@ static void test_NtQueryDirectoryFile(void)
|
|||
}
|
||||
InitializeObjectAttributes(&attr, &ntdirname, OBJ_CASE_INSENSITIVE, 0, NULL);
|
||||
|
||||
test_flags_NtQueryDirectoryFile(&attr, testdirA, FALSE, TRUE);
|
||||
test_flags_NtQueryDirectoryFile(&attr, testdirA, FALSE, FALSE);
|
||||
test_flags_NtQueryDirectoryFile(&attr, testdirA, TRUE, TRUE);
|
||||
test_flags_NtQueryDirectoryFile(&attr, testdirA, TRUE, FALSE);
|
||||
test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, FALSE, TRUE);
|
||||
test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, FALSE, FALSE);
|
||||
test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, TRUE, TRUE);
|
||||
test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, TRUE, FALSE);
|
||||
|
||||
for (i = 0; testfiles[i].name; i++)
|
||||
{
|
||||
UNICODE_STRING mask;
|
||||
|
||||
if (testfiles[i].nameW[0] == '.') continue; /* . and .. as masks are broken on Windows */
|
||||
mask.Buffer = testfiles[i].nameW;
|
||||
mask.Length = mask.MaximumLength = lstrlenW(testfiles[i].nameW) * sizeof(WCHAR);
|
||||
test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, FALSE, TRUE);
|
||||
test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, FALSE, FALSE);
|
||||
test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, TRUE, TRUE);
|
||||
test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, TRUE, FALSE);
|
||||
}
|
||||
|
||||
done:
|
||||
tear_down_attribute_test(testdirA);
|
||||
|
|
|
@ -72,7 +72,7 @@ static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_AT
|
|||
static NTSTATUS (WINAPI *pNtOpenIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
|
||||
static NTSTATUS (WINAPI *pNtQueryIoCompletion)(HANDLE, IO_COMPLETION_INFORMATION_CLASS, PVOID, ULONG, PULONG);
|
||||
static NTSTATUS (WINAPI *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER);
|
||||
static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, ULONG);
|
||||
static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, SIZE_T);
|
||||
static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
|
||||
static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
|
||||
static NTSTATUS (WINAPI *pNtQueryDirectoryFile)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,
|
||||
|
@ -81,7 +81,7 @@ static NTSTATUS (WINAPI *pNtQueryVolumeInformationFile)(HANDLE,PIO_STATUS_BLOCK,
|
|||
|
||||
static inline BOOL is_signaled( HANDLE obj )
|
||||
{
|
||||
return WaitForSingleObject( obj, 0 ) == 0;
|
||||
return WaitForSingleObject( obj, 0 ) == WAIT_OBJECT_0;
|
||||
}
|
||||
|
||||
#define PIPENAME "\\\\.\\pipe\\ntdll_tests_file.c"
|
||||
|
@ -101,10 +101,11 @@ static BOOL create_pipe( HANDLE *read, HANDLE *write, ULONG flags, ULONG size )
|
|||
|
||||
static HANDLE create_temp_file( ULONG flags )
|
||||
{
|
||||
char buffer[MAX_PATH];
|
||||
char path[MAX_PATH], buffer[MAX_PATH];
|
||||
HANDLE handle;
|
||||
|
||||
GetTempFileNameA( ".", "foo", 0, buffer );
|
||||
GetTempPathA( MAX_PATH, path );
|
||||
GetTempFileNameA( path, "foo", 0, buffer );
|
||||
handle = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
||||
flags | FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
|
||||
|
@ -505,7 +506,8 @@ static void read_file_test(void)
|
|||
ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
WriteFile( write, buffer, 1, &written, NULL );
|
||||
ret = WriteFile( write, buffer, 1, &written, NULL );
|
||||
ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
|
||||
/* iosb updated here by async i/o */
|
||||
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
|
||||
ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
|
||||
|
@ -530,7 +532,8 @@ static void read_file_test(void)
|
|||
ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
WriteFile( write, buffer, 1, &written, NULL );
|
||||
ret = WriteFile( write, buffer, 1, &written, NULL );
|
||||
ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
|
||||
/* iosb updated here by async i/o */
|
||||
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
|
||||
ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
|
||||
|
@ -548,7 +551,8 @@ static void read_file_test(void)
|
|||
U(iosb).Status = 0xdeadbabe;
|
||||
iosb.Information = 0xdeadbeef;
|
||||
ResetEvent( event );
|
||||
WriteFile( write, buffer, 1, &written, NULL );
|
||||
ret = WriteFile( write, buffer, 1, &written, NULL );
|
||||
ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
|
||||
status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
|
||||
ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
|
||||
ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
|
||||
|
@ -571,7 +575,8 @@ static void read_file_test(void)
|
|||
ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
WriteFile( write, buffer, 1, &written, NULL );
|
||||
ret = WriteFile( write, buffer, 1, &written, NULL );
|
||||
ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
|
||||
/* partial read is good enough */
|
||||
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
|
||||
ok( is_signaled( event ), "event is signaled\n" );
|
||||
|
@ -777,6 +782,8 @@ static void read_file_test(void)
|
|||
iosb.Information = 0xdeadbeef;
|
||||
offset.QuadPart = strlen(text) + 2;
|
||||
status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
|
||||
todo_wine
|
||||
ok(status == STATUS_PENDING || broken(status == STATUS_END_OF_FILE) /* before Vista */, "expected STATUS_PENDING, got %#x\n", status);
|
||||
if (status == STATUS_PENDING) /* vista */
|
||||
{
|
||||
WaitForSingleObject( event, 1000 );
|
||||
|
@ -787,16 +794,6 @@ static void read_file_test(void)
|
|||
SleepEx( 1, TRUE ); /* alertable sleep */
|
||||
ok( apc_count == 1, "apc was not called\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
|
||||
ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
|
||||
ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
|
||||
ok( !is_signaled( event ), "event is signaled\n" );
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
SleepEx( 1, TRUE ); /* alertable sleep */
|
||||
ok( !apc_count, "apc was called\n" );
|
||||
}
|
||||
CloseHandle( handle );
|
||||
|
||||
/* now a non-overlapped file */
|
||||
|
@ -859,9 +856,10 @@ static void append_file_test(void)
|
|||
NTSTATUS status;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
DWORD written;
|
||||
char buffer[128];
|
||||
char path[MAX_PATH], buffer[MAX_PATH];
|
||||
|
||||
GetTempFileNameA( ".", "foo", 0, buffer );
|
||||
GetTempPathA( MAX_PATH, path );
|
||||
GetTempFileNameA( path, "foo", 0, buffer );
|
||||
/* It is possible to open a file with only FILE_APPEND_DATA access flags.
|
||||
It matches the O_WRONLY|O_APPEND open() posix behavior */
|
||||
handle = CreateFileA(buffer, FILE_APPEND_DATA, 0, NULL, CREATE_ALWAYS,
|
||||
|
@ -990,8 +988,11 @@ static void test_iocp_setcompletion(HANDLE h)
|
|||
{
|
||||
NTSTATUS res;
|
||||
ULONG count;
|
||||
SIZE_T size = 3;
|
||||
|
||||
res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, 3 );
|
||||
if (sizeof(size) > 4) size |= (ULONGLONG)0x12345678 << 32;
|
||||
|
||||
res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size );
|
||||
ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
|
||||
|
||||
count = get_pending_msgs(h);
|
||||
|
@ -1000,7 +1001,7 @@ static void test_iocp_setcompletion(HANDLE h)
|
|||
if (get_msg(h))
|
||||
{
|
||||
ok( completionKey == CKEY_FIRST, "Invalid completion key: %lx\n", completionKey );
|
||||
ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
|
||||
ok( ioSb.Information == size, "Invalid ioSb.Information: %lu\n", ioSb.Information );
|
||||
ok( U(ioSb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
|
||||
ok( completionValue == CVALUE_FIRST, "Invalid completion value: %lx\n", completionValue );
|
||||
}
|
||||
|
@ -1299,6 +1300,158 @@ static void test_file_both_information(void)
|
|||
CloseHandle( h );
|
||||
}
|
||||
|
||||
static void test_file_disposition_information(void)
|
||||
{
|
||||
char buffer[MAX_PATH + 16];
|
||||
DWORD dirpos;
|
||||
HANDLE handle, handle2;
|
||||
NTSTATUS res;
|
||||
IO_STATUS_BLOCK io;
|
||||
FILE_DISPOSITION_INFORMATION fdi;
|
||||
BOOL fileDeleted;
|
||||
|
||||
/* cannot set disposition on file not opened with delete access */
|
||||
GetTempFileNameA( ".", "dis", 0, buffer );
|
||||
handle = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
|
||||
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
|
||||
res = pNtQueryInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
|
||||
ok( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "Unexpected NtQueryInformationFile result (expected STATUS_INVALID_INFO_CLASS, got %x)\n", res );
|
||||
fdi.DoDeleteFile = TRUE;
|
||||
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
|
||||
todo_wine
|
||||
ok( res == STATUS_ACCESS_DENIED, "unexpected FileDispositionInformation result (expected STATUS_ACCESS_DENIED, got %x)\n", res );
|
||||
CloseHandle( handle );
|
||||
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "File shouldn't have been deleted\n" );
|
||||
DeleteFileA( buffer );
|
||||
|
||||
/* can set disposition on file opened with proper access */
|
||||
GetTempFileNameA( ".", "dis", 0, buffer );
|
||||
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
|
||||
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
|
||||
fdi.DoDeleteFile = TRUE;
|
||||
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
|
||||
todo_wine
|
||||
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
|
||||
CloseHandle( handle );
|
||||
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
todo_wine
|
||||
ok( fileDeleted, "File should have been deleted\n" );
|
||||
DeleteFileA( buffer );
|
||||
|
||||
/* cannot set disposition on readonly file */
|
||||
GetTempFileNameA( ".", "dis", 0, buffer );
|
||||
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
|
||||
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
|
||||
fdi.DoDeleteFile = TRUE;
|
||||
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
|
||||
todo_wine
|
||||
ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
|
||||
CloseHandle( handle );
|
||||
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "File shouldn't have been deleted\n" );
|
||||
SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
|
||||
DeleteFileA( buffer );
|
||||
|
||||
/* can set disposition on file and then reset it */
|
||||
GetTempFileNameA( ".", "dis", 0, buffer );
|
||||
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
|
||||
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
|
||||
fdi.DoDeleteFile = TRUE;
|
||||
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
|
||||
todo_wine
|
||||
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
|
||||
fdi.DoDeleteFile = FALSE;
|
||||
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
|
||||
todo_wine
|
||||
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
|
||||
CloseHandle( handle );
|
||||
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "File shouldn't have been deleted\n" );
|
||||
DeleteFileA( buffer );
|
||||
|
||||
/* Delete-on-close flag doesn't change file disposition until a handle is closed */
|
||||
GetTempFileNameA( ".", "dis", 0, buffer );
|
||||
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
|
||||
fdi.DoDeleteFile = FALSE;
|
||||
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
|
||||
todo_wine
|
||||
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
|
||||
CloseHandle( handle );
|
||||
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( fileDeleted, "File should have been deleted\n" );
|
||||
DeleteFileA( buffer );
|
||||
|
||||
/* Delete-on-close flag sets disposition when a handle is closed and then it could be changed back */
|
||||
GetTempFileNameA( ".", "dis", 0, buffer );
|
||||
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
|
||||
ok( DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &handle2, 0, FALSE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
|
||||
CloseHandle( handle );
|
||||
fdi.DoDeleteFile = FALSE;
|
||||
res = pNtSetInformationFile( handle2, &io, &fdi, sizeof fdi, FileDispositionInformation );
|
||||
todo_wine
|
||||
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
|
||||
CloseHandle( handle2 );
|
||||
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( fileDeleted, "File should have been deleted\n" );
|
||||
DeleteFileA( buffer );
|
||||
|
||||
/* can set disposition on a directory opened with proper access */
|
||||
GetTempFileNameA( ".", "dis", 0, buffer );
|
||||
DeleteFileA( buffer );
|
||||
ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
|
||||
handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||
ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
|
||||
fdi.DoDeleteFile = TRUE;
|
||||
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
|
||||
todo_wine
|
||||
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
|
||||
CloseHandle( handle );
|
||||
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
todo_wine
|
||||
ok( fileDeleted, "Directory should have been deleted\n" );
|
||||
RemoveDirectoryA( buffer );
|
||||
|
||||
/* RemoveDirectory sets directory disposition and it can be undone */
|
||||
GetTempFileNameA( ".", "dis", 0, buffer );
|
||||
DeleteFileA( buffer );
|
||||
ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
|
||||
handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||
ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
|
||||
RemoveDirectoryA( buffer );
|
||||
fdi.DoDeleteFile = FALSE;
|
||||
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
|
||||
todo_wine
|
||||
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
|
||||
CloseHandle( handle );
|
||||
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
|
||||
RemoveDirectoryA( buffer );
|
||||
|
||||
/* cannot set disposition on a non-empty directory */
|
||||
GetTempFileNameA( ".", "dis", 0, buffer );
|
||||
DeleteFileA( buffer );
|
||||
ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
|
||||
handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||
ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
|
||||
dirpos = lstrlenA( buffer );
|
||||
lstrcpyA( buffer + dirpos, "\\tst" );
|
||||
handle2 = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
|
||||
CloseHandle( handle2 );
|
||||
fdi.DoDeleteFile = TRUE;
|
||||
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
|
||||
todo_wine
|
||||
ok( res == STATUS_DIRECTORY_NOT_EMPTY, "unexpected FileDispositionInformation result (expected STATUS_DIRECTORY_NOT_EMPTY, got %x)\n", res );
|
||||
DeleteFileA( buffer );
|
||||
buffer[dirpos] = '\0';
|
||||
CloseHandle( handle );
|
||||
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
|
||||
RemoveDirectoryA( buffer );
|
||||
}
|
||||
|
||||
static void test_iocompletion(void)
|
||||
{
|
||||
HANDLE h = INVALID_HANDLE_VALUE;
|
||||
|
@ -1634,6 +1787,52 @@ todo_wine
|
|||
CloseHandle( dir );
|
||||
}
|
||||
|
||||
static void test_query_attribute_information_file(void)
|
||||
{
|
||||
NTSTATUS status;
|
||||
HANDLE dir;
|
||||
WCHAR path[MAX_PATH];
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
IO_STATUS_BLOCK io;
|
||||
UNICODE_STRING nameW;
|
||||
FILE_FS_ATTRIBUTE_INFORMATION *ffai;
|
||||
BYTE buf[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
|
||||
|
||||
GetWindowsDirectoryW( path, MAX_PATH );
|
||||
pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = 0;
|
||||
attr.ObjectName = &nameW;
|
||||
attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||
attr.SecurityDescriptor = NULL;
|
||||
attr.SecurityQualityOfService = NULL;
|
||||
|
||||
status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT );
|
||||
ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
|
||||
pRtlFreeUnicodeString( &nameW );
|
||||
|
||||
ZeroMemory( buf, sizeof(buf) );
|
||||
U(io).Status = 0xdadadada;
|
||||
io.Information = 0xcacacaca;
|
||||
|
||||
status = pNtQueryVolumeInformationFile( dir, &io, buf, sizeof(buf), FileFsAttributeInformation );
|
||||
|
||||
ffai = (FILE_FS_ATTRIBUTE_INFORMATION *)buf;
|
||||
|
||||
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", status);
|
||||
ok(U(io).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %d\n", U(io).Status);
|
||||
ok(ffai->FileSystemAttribute != 0, "Missing FileSystemAttribute\n");
|
||||
ok(ffai->MaximumComponentNameLength != 0, "Missing MaximumComponentNameLength\n");
|
||||
ok(ffai->FileSystemNameLength != 0, "Missing FileSystemNameLength\n");
|
||||
|
||||
trace("FileSystemAttribute: %x MaximumComponentNameLength: %x FileSystemName: %s\n",
|
||||
ffai->FileSystemAttribute, ffai->MaximumComponentNameLength,
|
||||
wine_dbgstr_wn(ffai->FileSystemName, ffai->FileSystemNameLength / sizeof(WCHAR)));
|
||||
|
||||
CloseHandle( dir );
|
||||
}
|
||||
|
||||
static void test_NtCreateFile(void)
|
||||
{
|
||||
static const struct test_data
|
||||
|
@ -1662,7 +1861,6 @@ static void test_NtCreateFile(void)
|
|||
/*18*/{ FILE_SUPERSEDE, 0, 0, FILE_CREATED, FILE_ATTRIBUTE_ARCHIVE, TRUE }
|
||||
};
|
||||
static const WCHAR fooW[] = {'f','o','o',0};
|
||||
static const WCHAR dotW[] = {'.',0};
|
||||
NTSTATUS status;
|
||||
HANDLE handle;
|
||||
WCHAR path[MAX_PATH];
|
||||
|
@ -1671,7 +1869,8 @@ static void test_NtCreateFile(void)
|
|||
UNICODE_STRING nameW;
|
||||
DWORD ret, i;
|
||||
|
||||
GetTempFileNameW(dotW, fooW, 0, path);
|
||||
GetTempPathW(MAX_PATH, path);
|
||||
GetTempFileNameW(path, fooW, 0, path);
|
||||
DeleteFileW(path);
|
||||
pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
|
||||
|
||||
|
@ -1720,6 +1919,420 @@ static void test_NtCreateFile(void)
|
|||
DeleteFileW( path );
|
||||
}
|
||||
|
||||
static void test_read_write(void)
|
||||
{
|
||||
static const char contents[] = "1234567890abcd";
|
||||
char buf[256];
|
||||
HANDLE hfile;
|
||||
OVERLAPPED ovl;
|
||||
IO_STATUS_BLOCK iob;
|
||||
DWORD ret, bytes, status;
|
||||
LARGE_INTEGER offset;
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
|
||||
ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
|
||||
ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
|
||||
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
|
||||
ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
|
||||
ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
|
||||
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
|
||||
|
||||
hfile = create_temp_file(0);
|
||||
if (!hfile) return;
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
|
||||
ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#x\n", status);
|
||||
ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
|
||||
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
|
||||
ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
|
||||
ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
|
||||
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), NULL, NULL);
|
||||
ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
|
||||
ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
|
||||
ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
|
||||
|
||||
bytes = 0xdeadbeef;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
|
||||
ok(ret, "ReadFile error %d\n", GetLastError());
|
||||
ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
|
||||
ok(bytes == 0, "bytes %u\n", bytes);
|
||||
|
||||
SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
|
||||
|
||||
bytes = 0;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
|
||||
ok(ret, "ReadFile error %d\n", GetLastError());
|
||||
ok(bytes == sizeof(contents), "bytes %u\n", bytes);
|
||||
ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
|
||||
|
||||
SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
|
||||
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
|
||||
ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
|
||||
ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
|
||||
ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
|
||||
|
||||
SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
|
||||
|
||||
bytes = 0;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
|
||||
ok(ret, "ReadFile error %d\n", GetLastError());
|
||||
ok(bytes == sizeof(contents), "bytes %u\n", bytes);
|
||||
ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
|
||||
ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
|
||||
|
||||
SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
|
||||
|
||||
bytes = 0;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
|
||||
ok(ret, "WriteFile error %d\n", GetLastError());
|
||||
ok(bytes == sizeof(contents), "bytes %u\n", bytes);
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
|
||||
ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
|
||||
todo_wine
|
||||
ok(iob.Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", iob.Status);
|
||||
todo_wine
|
||||
ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
|
||||
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
|
||||
ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
|
||||
todo_wine
|
||||
ok(iob.Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", iob.Status);
|
||||
todo_wine
|
||||
ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
|
||||
|
||||
SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
|
||||
|
||||
bytes = 0;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
|
||||
ok(ret, "ReadFile error %d\n", GetLastError());
|
||||
ok(bytes == sizeof(contents), "bytes %u\n", bytes);
|
||||
ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
|
||||
ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
|
||||
todo_wine
|
||||
ok(iob.Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", iob.Status);
|
||||
todo_wine
|
||||
ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
|
||||
ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
|
||||
ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
|
||||
ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
|
||||
ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
offset.QuadPart = sizeof(contents) - 4;
|
||||
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
|
||||
ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
|
||||
ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
|
||||
ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
|
||||
ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
|
||||
ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
|
||||
ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
|
||||
ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
|
||||
ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
|
||||
|
||||
S(U(ovl)).Offset = sizeof(contents) - 4;
|
||||
S(U(ovl)).OffsetHigh = 0;
|
||||
ovl.hEvent = 0;
|
||||
bytes = 0;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
|
||||
ok(ret, "WriteFile error %d\n", GetLastError());
|
||||
ok(bytes == 4, "bytes %u\n", bytes);
|
||||
|
||||
S(U(ovl)).Offset = 0;
|
||||
S(U(ovl)).OffsetHigh = 0;
|
||||
ovl.Internal = -1;
|
||||
ovl.InternalHigh = -1;
|
||||
ovl.hEvent = 0;
|
||||
bytes = 0;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
|
||||
ok(ret, "ReadFile error %d\n", GetLastError());
|
||||
ok(bytes == sizeof(contents), "bytes %u\n", bytes);
|
||||
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
|
||||
ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
|
||||
ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
|
||||
ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
|
||||
|
||||
CloseHandle(hfile);
|
||||
|
||||
hfile = create_temp_file(FILE_FLAG_OVERLAPPED);
|
||||
if (!hfile) return;
|
||||
|
||||
bytes = 0xdeadbeef;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
|
||||
todo_wine
|
||||
ok(!ret, "WriteFile should fail\n");
|
||||
todo_wine
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
todo_wine
|
||||
ok(bytes == 0, "bytes %u\n", bytes);
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), NULL, NULL);
|
||||
todo_wine
|
||||
ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
|
||||
todo_wine
|
||||
ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
|
||||
todo_wine
|
||||
ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
|
||||
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
|
||||
todo_wine
|
||||
ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
|
||||
todo_wine
|
||||
ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
|
||||
todo_wine
|
||||
ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
|
||||
todo_wine
|
||||
ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* see below */, "expected STATUS_PENDING, got %#x\n", status);
|
||||
ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
|
||||
ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
|
||||
/* even fully updated XP passes this test, but it looks like some VMs
|
||||
* in a testbot get never updated, so overlapped IO is broken. Instead
|
||||
* of fighting with broken tests and adding a bunch of broken() statements
|
||||
* it's better to skip further tests completely.
|
||||
*/
|
||||
if (status != STATUS_PENDING)
|
||||
{
|
||||
todo_wine
|
||||
win_skip("broken overlapped IO implementation, update your OS\n");
|
||||
CloseHandle(hfile);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = WaitForSingleObject(hfile, 3000);
|
||||
ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
|
||||
|
||||
bytes = 0xdeadbeef;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
|
||||
ok(!ret, "ReadFile should fail\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
ok(bytes == 0, "bytes %u\n", bytes);
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
|
||||
ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
|
||||
ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
|
||||
ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
|
||||
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
|
||||
ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
|
||||
ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
|
||||
ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
|
||||
|
||||
offset.QuadPart = sizeof(contents);
|
||||
S(U(ovl)).Offset = offset.u.LowPart;
|
||||
S(U(ovl)).OffsetHigh = offset.u.HighPart;
|
||||
ovl.Internal = -1;
|
||||
ovl.InternalHigh = -1;
|
||||
ovl.hEvent = 0;
|
||||
bytes = 0xdeadbeef;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
|
||||
ok(!ret, "ReadFile should fail\n");
|
||||
ok(GetLastError() == ERROR_IO_PENDING || broken(GetLastError() == ERROR_HANDLE_EOF), "expected ERROR_IO_PENDING, got %d\n", GetLastError());
|
||||
/* even fully updated XP passes this test, but it looks like some VMs
|
||||
* in a testbot get never updated, so overlapped IO is broken. Instead
|
||||
* of fighting with broken tests and adding a bunch of broken() statements
|
||||
* it's better to skip further tests completely.
|
||||
*/
|
||||
if (GetLastError() != ERROR_IO_PENDING)
|
||||
{
|
||||
win_skip("broken overlapped IO implementation, update your OS\n");
|
||||
CloseHandle(hfile);
|
||||
return;
|
||||
}
|
||||
ok(bytes == 0, "bytes %u\n", bytes);
|
||||
ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
|
||||
ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
|
||||
|
||||
bytes = 0xdeadbeef;
|
||||
ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
|
||||
ok(!ret, "GetOverlappedResult should report FALSE\n");
|
||||
ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
|
||||
ok(bytes == 0, "expected 0, read %u\n", bytes);
|
||||
ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
|
||||
ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
offset.QuadPart = sizeof(contents);
|
||||
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
|
||||
ok(status == STATUS_PENDING, "expected STATUS_PENDING, got %#x\n", status);
|
||||
ok(iob.Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", iob.Status);
|
||||
ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
|
||||
|
||||
S(U(ovl)).Offset = offset.u.LowPart;
|
||||
S(U(ovl)).OffsetHigh = offset.u.HighPart;
|
||||
ovl.Internal = iob.Status;
|
||||
ovl.InternalHigh = iob.Information;
|
||||
ovl.hEvent = 0;
|
||||
bytes = 0xdeadbeef;
|
||||
ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
|
||||
ok(!ret, "GetOverlappedResult should report FALSE\n");
|
||||
ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
|
||||
ok(bytes == 0, "expected 0, read %u\n", bytes);
|
||||
ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
|
||||
ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
|
||||
|
||||
SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
|
||||
|
||||
S(U(ovl)).Offset = 0;
|
||||
S(U(ovl)).OffsetHigh = 0;
|
||||
ovl.Internal = -1;
|
||||
ovl.InternalHigh = -1;
|
||||
ovl.hEvent = 0;
|
||||
bytes = 0;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
|
||||
ok(!ret, "ReadFile should fail\n");
|
||||
ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
|
||||
ok(bytes == 0, "bytes %u\n", bytes);
|
||||
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
|
||||
ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
|
||||
|
||||
bytes = 0xdeadbeef;
|
||||
ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
|
||||
ok(ret, "GetOverlappedResult error %d\n", GetLastError());
|
||||
ok(bytes == sizeof(contents), "bytes %u\n", bytes);
|
||||
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
|
||||
ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
|
||||
ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
offset.QuadPart = sizeof(contents) - 4;
|
||||
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
|
||||
ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* before Vista */, "expected STATUS_PENDING, got %#x\n", status);
|
||||
ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
|
||||
ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
|
||||
|
||||
ret = WaitForSingleObject(hfile, 3000);
|
||||
ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
|
||||
|
||||
iob.Status = -1;
|
||||
iob.Information = -1;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
|
||||
ok(status == STATUS_PENDING, "expected STATUS_PENDING, got %#x\n", status);
|
||||
ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
|
||||
ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
|
||||
|
||||
ret = WaitForSingleObject(hfile, 3000);
|
||||
ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
|
||||
ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
|
||||
ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
|
||||
|
||||
S(U(ovl)).Offset = sizeof(contents) - 4;
|
||||
S(U(ovl)).OffsetHigh = 0;
|
||||
ovl.Internal = -1;
|
||||
ovl.InternalHigh = -1;
|
||||
ovl.hEvent = 0;
|
||||
bytes = 0;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
|
||||
ok(!ret || broken(ret) /* before Vista */, "WriteFile should fail\n");
|
||||
ok(GetLastError() == ERROR_IO_PENDING || broken(GetLastError() == 0xdeadbeef) /* before Vista */, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
|
||||
ok(bytes == 0 || broken(bytes == 4) /* before Vista */, "bytes %u\n", bytes);
|
||||
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
|
||||
ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
|
||||
|
||||
bytes = 0xdeadbeef;
|
||||
ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
|
||||
ok(ret, "GetOverlappedResult error %d\n", GetLastError());
|
||||
ok(bytes == 4, "bytes %u\n", bytes);
|
||||
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
|
||||
ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
|
||||
|
||||
S(U(ovl)).Offset = 0;
|
||||
S(U(ovl)).OffsetHigh = 0;
|
||||
ovl.Internal = -1;
|
||||
ovl.InternalHigh = -1;
|
||||
ovl.hEvent = 0;
|
||||
bytes = 0;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
|
||||
ok(!ret, "ReadFile should fail\n");
|
||||
ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
|
||||
ok(bytes == 0, "bytes %u\n", bytes);
|
||||
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
|
||||
ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
|
||||
|
||||
bytes = 0xdeadbeef;
|
||||
ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
|
||||
ok(ret, "GetOverlappedResult error %d\n", GetLastError());
|
||||
ok(bytes == sizeof(contents), "bytes %u\n", bytes);
|
||||
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
|
||||
ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
|
||||
ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
|
||||
ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
|
||||
|
||||
CloseHandle(hfile);
|
||||
}
|
||||
|
||||
START_TEST(file)
|
||||
{
|
||||
HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
|
||||
|
@ -1756,6 +2369,7 @@ START_TEST(file)
|
|||
pNtQueryDirectoryFile = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
|
||||
pNtQueryVolumeInformationFile = (void *)GetProcAddress(hntdll, "NtQueryVolumeInformationFile");
|
||||
|
||||
test_read_write();
|
||||
test_NtCreateFile();
|
||||
create_file_test();
|
||||
open_file_test();
|
||||
|
@ -1769,5 +2383,7 @@ START_TEST(file)
|
|||
test_file_both_information();
|
||||
test_file_name_information();
|
||||
test_file_all_name_information();
|
||||
test_file_disposition_information();
|
||||
test_query_volume_information_file();
|
||||
test_query_attribute_information_file();
|
||||
}
|
||||
|
|
|
@ -505,18 +505,51 @@ static void test_query_cache(void)
|
|||
{
|
||||
NTSTATUS status;
|
||||
ULONG ReturnLength;
|
||||
SYSTEM_CACHE_INFORMATION sci;
|
||||
BYTE buffer[128];
|
||||
SYSTEM_CACHE_INFORMATION *sci = (SYSTEM_CACHE_INFORMATION *) buffer;
|
||||
ULONG expected;
|
||||
INT i;
|
||||
|
||||
status = pNtQuerySystemInformation(SystemCacheInformation, &sci, 0, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
/* the large SYSTEM_CACHE_INFORMATION on WIN64 is not documented */
|
||||
expected = sizeof(SYSTEM_CACHE_INFORMATION);
|
||||
for (i = sizeof(buffer); i>= expected; i--)
|
||||
{
|
||||
ReturnLength = 0xdeadbeef;
|
||||
status = pNtQuerySystemInformation(SystemCacheInformation, sci, i, &ReturnLength);
|
||||
ok(!status && (ReturnLength == expected),
|
||||
"%d: got 0x%x and %u (expected STATUS_SUCCESS and %u)\n", i, status, ReturnLength, expected);
|
||||
}
|
||||
|
||||
status = pNtQuerySystemInformation(SystemCacheInformation, &sci, sizeof(sci), &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(sci) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
/* buffer too small for the full result.
|
||||
Up to win7, the function succeeds with a partial result. */
|
||||
status = pNtQuerySystemInformation(SystemCacheInformation, sci, i, &ReturnLength);
|
||||
if (!status)
|
||||
{
|
||||
expected = offsetof(SYSTEM_CACHE_INFORMATION, MinimumWorkingSet);
|
||||
for (; i>= expected; i--)
|
||||
{
|
||||
ReturnLength = 0xdeadbeef;
|
||||
status = pNtQuerySystemInformation(SystemCacheInformation, sci, i, &ReturnLength);
|
||||
ok(!status && (ReturnLength == expected),
|
||||
"%d: got 0x%x and %u (expected STATUS_SUCCESS and %u)\n", i, status, ReturnLength, expected);
|
||||
}
|
||||
}
|
||||
|
||||
status = pNtQuerySystemInformation(SystemCacheInformation, &sci, sizeof(sci) + 2, &ReturnLength);
|
||||
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok( sizeof(sci) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
|
||||
/* buffer too small for the result, this call will always fail */
|
||||
ReturnLength = 0xdeadbeef;
|
||||
status = pNtQuerySystemInformation(SystemCacheInformation, sci, i, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH &&
|
||||
((ReturnLength == expected) || broken(!ReturnLength) || broken(ReturnLength == 0xfffffff0)),
|
||||
"%d: got 0x%x and %u (expected STATUS_INFO_LENGTH_MISMATCH and %u)\n", i, status, ReturnLength, expected);
|
||||
|
||||
if (0) {
|
||||
/* this crashes on some vista / win7 machines */
|
||||
ReturnLength = 0xdeadbeef;
|
||||
status = pNtQuerySystemInformation(SystemCacheInformation, sci, 0, &ReturnLength);
|
||||
ok( status == STATUS_INFO_LENGTH_MISMATCH &&
|
||||
((ReturnLength == expected) || broken(!ReturnLength) || broken(ReturnLength == 0xfffffff0)),
|
||||
"0: got 0x%x and %u (expected STATUS_INFO_LENGTH_MISMATCH and %u)\n", status, ReturnLength, expected);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_query_interrupt(void)
|
||||
|
|
|
@ -30,6 +30,9 @@ static NTSTATUS (WINAPI *pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPC
|
|||
static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
|
||||
static VOID (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
|
||||
static NTSTATUS (WINAPI *pNtCreateEvent) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, BOOLEAN, BOOLEAN);
|
||||
static NTSTATUS (WINAPI *pNtOpenEvent) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES);
|
||||
static NTSTATUS (WINAPI *pNtPulseEvent) ( HANDLE, PULONG );
|
||||
static NTSTATUS (WINAPI *pNtQueryEvent) ( HANDLE, EVENT_INFORMATION_CLASS, PVOID, ULONG, PULONG );
|
||||
static NTSTATUS (WINAPI *pNtCreateMutant)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, BOOLEAN );
|
||||
static NTSTATUS (WINAPI *pNtOpenMutant) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES );
|
||||
static NTSTATUS (WINAPI *pNtCreateSemaphore)( PHANDLE, ACCESS_MASK,const POBJECT_ATTRIBUTES,LONG,LONG );
|
||||
|
@ -46,8 +49,15 @@ static NTSTATUS (WINAPI *pNtOpenSymbolicLinkObject)(PHANDLE, ACCESS_MASK, POBJEC
|
|||
static NTSTATUS (WINAPI *pNtCreateSymbolicLinkObject)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PUNICODE_STRING);
|
||||
static NTSTATUS (WINAPI *pNtQuerySymbolicLinkObject)(HANDLE,PUNICODE_STRING,PULONG);
|
||||
static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,ULONG,PULONG);
|
||||
static NTSTATUS (WINAPI *pNtReleaseSemaphore)(HANDLE handle, ULONG count, PULONG previous);
|
||||
static NTSTATUS (WINAPI *pNtReleaseSemaphore)(HANDLE, ULONG, PULONG);
|
||||
static NTSTATUS (WINAPI *pNtCreateKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, ULONG );
|
||||
static NTSTATUS (WINAPI *pNtOpenKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES * );
|
||||
static NTSTATUS (WINAPI *pNtWaitForKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
|
||||
static NTSTATUS (WINAPI *pNtReleaseKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
|
||||
|
||||
#define KEYEDEVENT_WAIT 0x0001
|
||||
#define KEYEDEVENT_WAKE 0x0002
|
||||
#define KEYEDEVENT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x0003)
|
||||
|
||||
static void test_case_sensitive (void)
|
||||
{
|
||||
|
@ -798,6 +808,230 @@ static void test_type_mismatch(void)
|
|||
pNtClose( h );
|
||||
}
|
||||
|
||||
static void test_event(void)
|
||||
{
|
||||
HANDLE Event;
|
||||
HANDLE Event2;
|
||||
NTSTATUS status;
|
||||
UNICODE_STRING str;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
EVENT_BASIC_INFORMATION info;
|
||||
static const WCHAR eventName[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s','\\','t','e','s','t','E','v','e','n','t',0};
|
||||
|
||||
pRtlInitUnicodeString(&str, eventName);
|
||||
InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
|
||||
|
||||
status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, 1, 0);
|
||||
ok( status == STATUS_SUCCESS, "NtCreateEvent failed %08x\n", status );
|
||||
|
||||
status = pNtPulseEvent(Event, NULL);
|
||||
ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status );
|
||||
|
||||
status = pNtQueryEvent(Event, EventBasicInformation, &info, sizeof(info), NULL);
|
||||
ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
|
||||
ok( info.EventType == 1 && info.EventState == 0,
|
||||
"NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType, info.EventState );
|
||||
|
||||
status = pNtOpenEvent(&Event2, GENERIC_ALL, &attr);
|
||||
ok( status == STATUS_SUCCESS, "NtOpenEvent failed %08x\n", status );
|
||||
|
||||
status = pNtClose(Event);
|
||||
|
||||
status = pNtQueryEvent(Event2, EventBasicInformation, &info, sizeof(info), NULL);
|
||||
ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
|
||||
ok( info.EventType == 1 && info.EventState == 0,
|
||||
"NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType, info.EventState );
|
||||
|
||||
status = pNtClose(Event2);
|
||||
}
|
||||
|
||||
static const WCHAR keyed_nameW[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s',
|
||||
'\\','W','i','n','e','T','e','s','t','E','v','e','n','t',0};
|
||||
|
||||
static DWORD WINAPI keyed_event_thread( void *arg )
|
||||
{
|
||||
HANDLE handle;
|
||||
NTSTATUS status;
|
||||
LARGE_INTEGER timeout;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
UNICODE_STRING str;
|
||||
ULONG_PTR i;
|
||||
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = 0;
|
||||
attr.ObjectName = &str;
|
||||
attr.Attributes = 0;
|
||||
attr.SecurityDescriptor = NULL;
|
||||
attr.SecurityQualityOfService = NULL;
|
||||
RtlInitUnicodeString( &str, keyed_nameW );
|
||||
|
||||
status = pNtOpenKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS, &attr );
|
||||
ok( !status, "NtOpenKeyedEvent failed %x\n", status );
|
||||
|
||||
for (i = 0; i < 20; i++)
|
||||
{
|
||||
if (i & 1)
|
||||
status = pNtWaitForKeyedEvent( handle, (void *)(i * 2), 0, NULL );
|
||||
else
|
||||
status = pNtReleaseKeyedEvent( handle, (void *)(i * 2), 0, NULL );
|
||||
ok( status == STATUS_SUCCESS, "%li: failed %x\n", i, status );
|
||||
Sleep( 20 - i );
|
||||
}
|
||||
|
||||
status = pNtReleaseKeyedEvent( handle, (void *)0x1234, 0, NULL );
|
||||
ok( status == STATUS_SUCCESS, "NtReleaseKeyedEvent %x\n", status );
|
||||
|
||||
timeout.QuadPart = -10000;
|
||||
status = pNtWaitForKeyedEvent( handle, (void *)0x5678, 0, &timeout );
|
||||
ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
|
||||
status = pNtReleaseKeyedEvent( handle, (void *)0x9abc, 0, &timeout );
|
||||
ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
|
||||
|
||||
NtClose( handle );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_keyed_events(void)
|
||||
{
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
UNICODE_STRING str;
|
||||
HANDLE handle, event, thread;
|
||||
NTSTATUS status;
|
||||
LARGE_INTEGER timeout;
|
||||
ULONG_PTR i;
|
||||
|
||||
if (!pNtCreateKeyedEvent)
|
||||
{
|
||||
win_skip( "Keyed events not supported\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = 0;
|
||||
attr.ObjectName = &str;
|
||||
attr.Attributes = 0;
|
||||
attr.SecurityDescriptor = NULL;
|
||||
attr.SecurityQualityOfService = NULL;
|
||||
RtlInitUnicodeString( &str, keyed_nameW );
|
||||
|
||||
status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS | SYNCHRONIZE, &attr, 0 );
|
||||
ok( !status, "NtCreateKeyedEvent failed %x\n", status );
|
||||
|
||||
status = WaitForSingleObject( handle, 1000 );
|
||||
ok( status == 0, "WaitForSingleObject %x\n", status );
|
||||
|
||||
timeout.QuadPart = -100000;
|
||||
status = pNtWaitForKeyedEvent( handle, (void *)255, 0, &timeout );
|
||||
ok( status == STATUS_INVALID_PARAMETER_1, "NtWaitForKeyedEvent %x\n", status );
|
||||
status = pNtReleaseKeyedEvent( handle, (void *)255, 0, &timeout );
|
||||
ok( status == STATUS_INVALID_PARAMETER_1, "NtReleaseKeyedEvent %x\n", status );
|
||||
|
||||
status = pNtWaitForKeyedEvent( handle, (void *)254, 0, &timeout );
|
||||
ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
|
||||
status = pNtReleaseKeyedEvent( handle, (void *)254, 0, &timeout );
|
||||
ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
|
||||
|
||||
status = pNtWaitForKeyedEvent( handle, NULL, 0, &timeout );
|
||||
ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
|
||||
status = pNtReleaseKeyedEvent( handle, NULL, 0, &timeout );
|
||||
ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
|
||||
|
||||
status = pNtWaitForKeyedEvent( (HANDLE)0xdeadbeef, (void *)9, 0, &timeout );
|
||||
ok( status == STATUS_INVALID_PARAMETER_1, "NtWaitForKeyedEvent %x\n", status );
|
||||
status = pNtReleaseKeyedEvent( (HANDLE)0xdeadbeef, (void *)9, 0, &timeout );
|
||||
ok( status == STATUS_INVALID_PARAMETER_1, "NtReleaseKeyedEvent %x\n", status );
|
||||
|
||||
status = pNtWaitForKeyedEvent( (HANDLE)0xdeadbeef, (void *)8, 0, &timeout );
|
||||
ok( status == STATUS_INVALID_HANDLE, "NtWaitForKeyedEvent %x\n", status );
|
||||
status = pNtReleaseKeyedEvent( (HANDLE)0xdeadbeef, (void *)8, 0, &timeout );
|
||||
ok( status == STATUS_INVALID_HANDLE, "NtReleaseKeyedEvent %x\n", status );
|
||||
|
||||
thread = CreateThread( NULL, 0, keyed_event_thread, 0, 0, NULL );
|
||||
for (i = 0; i < 20; i++)
|
||||
{
|
||||
if (i & 1)
|
||||
status = pNtReleaseKeyedEvent( handle, (void *)(i * 2), 0, NULL );
|
||||
else
|
||||
status = pNtWaitForKeyedEvent( handle, (void *)(i * 2), 0, NULL );
|
||||
ok( status == STATUS_SUCCESS, "%li: failed %x\n", i, status );
|
||||
Sleep( i );
|
||||
}
|
||||
status = pNtWaitForKeyedEvent( handle, (void *)0x1234, 0, &timeout );
|
||||
ok( status == STATUS_SUCCESS, "NtWaitForKeyedEvent %x\n", status );
|
||||
status = pNtWaitForKeyedEvent( handle, (void *)0x5678, 0, &timeout );
|
||||
ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
|
||||
status = pNtReleaseKeyedEvent( handle, (void *)0x9abc, 0, &timeout );
|
||||
ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
|
||||
|
||||
ok( WaitForSingleObject( thread, 30000 ) == 0, "wait failed\n" );
|
||||
|
||||
NtClose( handle );
|
||||
|
||||
/* test access rights */
|
||||
|
||||
status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_WAIT, &attr, 0 );
|
||||
ok( !status, "NtCreateKeyedEvent failed %x\n", status );
|
||||
status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
|
||||
ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
|
||||
status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
|
||||
ok( status == STATUS_ACCESS_DENIED, "NtReleaseKeyedEvent %x\n", status );
|
||||
NtClose( handle );
|
||||
|
||||
status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_WAKE, &attr, 0 );
|
||||
ok( !status, "NtCreateKeyedEvent failed %x\n", status );
|
||||
status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
|
||||
ok( status == STATUS_ACCESS_DENIED, "NtWaitForKeyedEvent %x\n", status );
|
||||
status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
|
||||
ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
|
||||
NtClose( handle );
|
||||
|
||||
status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS, &attr, 0 );
|
||||
ok( !status, "NtCreateKeyedEvent failed %x\n", status );
|
||||
status = WaitForSingleObject( handle, 1000 );
|
||||
ok( status == WAIT_FAILED && GetLastError() == ERROR_ACCESS_DENIED,
|
||||
"WaitForSingleObject %x err %u\n", status, GetLastError() );
|
||||
status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
|
||||
ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
|
||||
status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
|
||||
ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
|
||||
NtClose( handle );
|
||||
|
||||
/* GENERIC_READ gives wait access */
|
||||
status = pNtCreateKeyedEvent( &handle, GENERIC_READ, &attr, 0 );
|
||||
ok( !status, "NtCreateKeyedEvent failed %x\n", status );
|
||||
status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
|
||||
ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
|
||||
status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
|
||||
ok( status == STATUS_ACCESS_DENIED, "NtReleaseKeyedEvent %x\n", status );
|
||||
NtClose( handle );
|
||||
|
||||
/* GENERIC_WRITE gives wake access */
|
||||
status = pNtCreateKeyedEvent( &handle, GENERIC_WRITE, &attr, 0 );
|
||||
ok( !status, "NtCreateKeyedEvent failed %x\n", status );
|
||||
status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
|
||||
ok( status == STATUS_ACCESS_DENIED, "NtWaitForKeyedEvent %x\n", status );
|
||||
status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
|
||||
ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
|
||||
|
||||
/* it's not an event */
|
||||
status = pNtPulseEvent( handle, NULL );
|
||||
ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtPulseEvent %x\n", status );
|
||||
|
||||
status = pNtCreateEvent( &event, GENERIC_ALL, &attr, FALSE, FALSE );
|
||||
ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_OBJECT_TYPE_MISMATCH,
|
||||
"CreateEvent %x\n", status );
|
||||
|
||||
NtClose( handle );
|
||||
|
||||
status = pNtCreateEvent( &event, GENERIC_ALL, &attr, FALSE, FALSE );
|
||||
ok( status == 0, "CreateEvent %x\n", status );
|
||||
status = pNtWaitForKeyedEvent( event, (void *)8, 0, &timeout );
|
||||
ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtWaitForKeyedEvent %x\n", status );
|
||||
status = pNtReleaseKeyedEvent( event, (void *)8, 0, &timeout );
|
||||
ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtReleaseKeyedEvent %x\n", status );
|
||||
NtClose( event );
|
||||
}
|
||||
|
||||
START_TEST(om)
|
||||
{
|
||||
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
||||
|
@ -815,6 +1049,9 @@ START_TEST(om)
|
|||
pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
|
||||
pNtCreateEvent = (void *)GetProcAddress(hntdll, "NtCreateEvent");
|
||||
pNtCreateMutant = (void *)GetProcAddress(hntdll, "NtCreateMutant");
|
||||
pNtOpenEvent = (void *)GetProcAddress(hntdll, "NtOpenEvent");
|
||||
pNtQueryEvent = (void *)GetProcAddress(hntdll, "NtQueryEvent");
|
||||
pNtPulseEvent = (void *)GetProcAddress(hntdll, "NtPulseEvent");
|
||||
pNtOpenMutant = (void *)GetProcAddress(hntdll, "NtOpenMutant");
|
||||
pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
|
||||
pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
|
||||
|
@ -830,6 +1067,10 @@ START_TEST(om)
|
|||
pNtCreateSection = (void *)GetProcAddress(hntdll, "NtCreateSection");
|
||||
pNtQueryObject = (void *)GetProcAddress(hntdll, "NtQueryObject");
|
||||
pNtReleaseSemaphore = (void *)GetProcAddress(hntdll, "NtReleaseSemaphore");
|
||||
pNtCreateKeyedEvent = (void *)GetProcAddress(hntdll, "NtCreateKeyedEvent");
|
||||
pNtOpenKeyedEvent = (void *)GetProcAddress(hntdll, "NtOpenKeyedEvent");
|
||||
pNtWaitForKeyedEvent = (void *)GetProcAddress(hntdll, "NtWaitForKeyedEvent");
|
||||
pNtReleaseKeyedEvent = (void *)GetProcAddress(hntdll, "NtReleaseKeyedEvent");
|
||||
|
||||
test_case_sensitive();
|
||||
test_namespace_pipe();
|
||||
|
@ -838,4 +1079,9 @@ START_TEST(om)
|
|||
test_symboliclink();
|
||||
test_query_object();
|
||||
test_type_mismatch();
|
||||
test_event();
|
||||
if (winetest_interactive)
|
||||
test_keyed_events();
|
||||
else
|
||||
skip("Skipping test_keyed_events(). ROSTESTS-118.\n");
|
||||
}
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
#include "winnls.h"
|
||||
#include "guiddef.h"
|
||||
|
||||
#define HASH_STRING_ALGORITHM_X65599 1
|
||||
#define HASH_STRING_ALGORITHM_INVALID 0xffffffff
|
||||
|
||||
/* Function ptrs for ntdll calls */
|
||||
static HMODULE hntdll = 0;
|
||||
static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING, PCANSI_STRING, BOOLEAN);
|
||||
|
@ -64,6 +67,7 @@ static NTSTATUS (WINAPI *pRtlValidateUnicodeString)(LONG, UNICODE_STRING *);
|
|||
static NTSTATUS (WINAPI *pRtlGUIDFromString)(const UNICODE_STRING*,GUID*);
|
||||
static NTSTATUS (WINAPI *pRtlStringFromGUID)(const GUID*, UNICODE_STRING*);
|
||||
static BOOLEAN (WINAPI *pRtlIsTextUnicode)(LPVOID, INT, INT *);
|
||||
static NTSTATUS (WINAPI *pRtlHashUnicodeString)(PCUNICODE_STRING,BOOLEAN,ULONG,ULONG*);
|
||||
|
||||
/*static VOID (WINAPI *pRtlFreeOemString)(PSTRING);*/
|
||||
/*static VOID (WINAPI *pRtlCopyUnicodeString)(UNICODE_STRING *, const UNICODE_STRING *);*/
|
||||
|
@ -132,10 +136,10 @@ static void InitFunctionPtrs(void)
|
|||
pRtlGUIDFromString = (void *)GetProcAddress(hntdll, "RtlGUIDFromString");
|
||||
pRtlStringFromGUID = (void *)GetProcAddress(hntdll, "RtlStringFromGUID");
|
||||
pRtlIsTextUnicode = (void *)GetProcAddress(hntdll, "RtlIsTextUnicode");
|
||||
pRtlHashUnicodeString = (void*)GetProcAddress(hntdll, "RtlHashUnicodeString");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void test_RtlInitString(void)
|
||||
{
|
||||
static const char teststring[] = "Some Wild String";
|
||||
|
@ -192,6 +196,12 @@ static void test_RtlInitUnicodeStringEx(void)
|
|||
UNICODE_STRING uni;
|
||||
NTSTATUS result;
|
||||
|
||||
if (!pRtlInitUnicodeStringEx)
|
||||
{
|
||||
win_skip("RtlInitUnicodeStringEx is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
teststring2 = HeapAlloc(GetProcessHeap(), 0, (TESTSTRING2_LEN + 1) * sizeof(WCHAR));
|
||||
memset(teststring2, 'X', TESTSTRING2_LEN * sizeof(WCHAR));
|
||||
teststring2[TESTSTRING2_LEN] = '\0';
|
||||
|
@ -406,6 +416,12 @@ static void test_RtlDuplicateUnicodeString(void)
|
|||
NTSTATUS result;
|
||||
unsigned int test_num;
|
||||
|
||||
if (!pRtlDuplicateUnicodeString)
|
||||
{
|
||||
win_skip("RtlDuplicateUnicodeString is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (test_num = 0; test_num < NB_DUPL_USTR; test_num++) {
|
||||
source_str.Length = dupl_ustr[test_num].source_Length;
|
||||
source_str.MaximumLength = dupl_ustr[test_num].source_MaximumLength;
|
||||
|
@ -1180,6 +1196,12 @@ static void test_RtlFindCharInUnicodeString(void)
|
|||
unsigned int idx;
|
||||
unsigned int test_num;
|
||||
|
||||
if (!pRtlFindCharInUnicodeString)
|
||||
{
|
||||
win_skip("RtlFindCharInUnicodeString is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (test_num = 0; test_num < NB_FIND_CH_IN_USTR; test_num++) {
|
||||
if (find_ch_in_ustr[test_num].main_str != NULL) {
|
||||
main_str.Length = strlen(find_ch_in_ustr[test_num].main_str) * sizeof(WCHAR);
|
||||
|
@ -1710,6 +1732,12 @@ static void test_RtlIsTextUnicode(void)
|
|||
int flags;
|
||||
int i;
|
||||
|
||||
if (!pRtlIsTextUnicode)
|
||||
{
|
||||
win_skip("RtlIsTextUnicode is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ok(!pRtlIsTextUnicode(ascii, sizeof(ascii), NULL), "ASCII text detected as Unicode\n");
|
||||
|
||||
res = pRtlIsTextUnicode(unicode, sizeof(unicode), NULL);
|
||||
|
@ -1839,6 +1867,12 @@ static void test_RtlGUIDFromString(void)
|
|||
UNICODE_STRING str;
|
||||
NTSTATUS ret;
|
||||
|
||||
if (!pRtlGUIDFromString)
|
||||
{
|
||||
win_skip("RtlGUIDFromString is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
str.Length = str.MaximumLength = sizeof(szGuid) - sizeof(WCHAR);
|
||||
str.Buffer = (LPWSTR)szGuid;
|
||||
|
||||
|
@ -1858,6 +1892,12 @@ static void test_RtlStringFromGUID(void)
|
|||
UNICODE_STRING str;
|
||||
NTSTATUS ret;
|
||||
|
||||
if (!pRtlStringFromGUID)
|
||||
{
|
||||
win_skip("RtlStringFromGUID is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
str.Length = str.MaximumLength = 0;
|
||||
str.Buffer = NULL;
|
||||
|
||||
|
@ -1867,6 +1907,70 @@ static void test_RtlStringFromGUID(void)
|
|||
pRtlFreeUnicodeString(&str);
|
||||
}
|
||||
|
||||
struct hash_unicodestring_test {
|
||||
WCHAR str[50];
|
||||
BOOLEAN case_insensitive;
|
||||
ULONG hash;
|
||||
};
|
||||
|
||||
static const struct hash_unicodestring_test hash_test[] = {
|
||||
{ {'T',0}, FALSE, 0x00000054 },
|
||||
{ {'T','e','s','t',0}, FALSE, 0x766bb952 },
|
||||
{ {'T','e','S','t',0}, FALSE, 0x764bb172 },
|
||||
{ {'t','e','s','t',0}, FALSE, 0x4745d132 },
|
||||
{ {'t','e','s','t',0}, TRUE, 0x6689c132 },
|
||||
{ {'T','E','S','T',0}, TRUE, 0x6689c132 },
|
||||
{ {'T','E','S','T',0}, FALSE, 0x6689c132 },
|
||||
{ {'a','b','c','d','e','f',0}, FALSE, 0x971318c3 },
|
||||
{ { 0 } }
|
||||
};
|
||||
|
||||
static void test_RtlHashUnicodeString(void)
|
||||
{
|
||||
static const WCHAR strW[] = {'T','e','s','t',0,'1',0};
|
||||
const struct hash_unicodestring_test *ptr;
|
||||
UNICODE_STRING str;
|
||||
NTSTATUS status;
|
||||
ULONG hash;
|
||||
|
||||
if (!pRtlHashUnicodeString)
|
||||
{
|
||||
win_skip("RtlHashUnicodeString is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
status = pRtlHashUnicodeString(NULL, FALSE, HASH_STRING_ALGORITHM_X65599, &hash);
|
||||
ok(status == STATUS_INVALID_PARAMETER, "got status 0x%08x\n", status);
|
||||
|
||||
RtlInitUnicodeString(&str, strW);
|
||||
status = pRtlHashUnicodeString(&str, FALSE, HASH_STRING_ALGORITHM_X65599, NULL);
|
||||
ok(status == STATUS_INVALID_PARAMETER, "got status 0x%08x\n", status);
|
||||
|
||||
status = pRtlHashUnicodeString(&str, FALSE, HASH_STRING_ALGORITHM_INVALID, &hash);
|
||||
ok(status == STATUS_INVALID_PARAMETER, "got status 0x%08x\n", status);
|
||||
|
||||
/* embedded null */
|
||||
str.Buffer = (PWSTR)strW;
|
||||
str.Length = sizeof(strW) - sizeof(WCHAR);
|
||||
str.MaximumLength = sizeof(strW);
|
||||
status = pRtlHashUnicodeString(&str, FALSE, HASH_STRING_ALGORITHM_X65599, &hash);
|
||||
ok(status == STATUS_SUCCESS, "got status 0x%08x\n", status);
|
||||
ok(hash == 0x32803083, "got 0x%08x\n", hash);
|
||||
|
||||
ptr = hash_test;
|
||||
while (*ptr->str)
|
||||
{
|
||||
RtlInitUnicodeString(&str, ptr->str);
|
||||
hash = 0;
|
||||
status = pRtlHashUnicodeString(&str, ptr->case_insensitive, HASH_STRING_ALGORITHM_X65599, &hash);
|
||||
ok(status == STATUS_SUCCESS, "got status 0x%08x for %s\n", status, wine_dbgstr_w(ptr->str));
|
||||
ok(hash == ptr->hash, "got wrong hash 0x%08x, expected 0x%08x, for %s, mode %d\n", hash, ptr->hash,
|
||||
wine_dbgstr_w(ptr->str), ptr->case_insensitive);
|
||||
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(rtlstr)
|
||||
{
|
||||
InitFunctionPtrs();
|
||||
|
@ -1887,22 +1991,17 @@ START_TEST(rtlstr)
|
|||
test_RtlAppendUnicodeStringToString();
|
||||
}
|
||||
|
||||
if (pRtlInitUnicodeStringEx)
|
||||
test_RtlInitUnicodeStringEx();
|
||||
if (pRtlDuplicateUnicodeString)
|
||||
test_RtlDuplicateUnicodeString();
|
||||
if (pRtlFindCharInUnicodeString)
|
||||
test_RtlFindCharInUnicodeString();
|
||||
if (pRtlGUIDFromString)
|
||||
test_RtlGUIDFromString();
|
||||
if (pRtlStringFromGUID)
|
||||
test_RtlStringFromGUID();
|
||||
if (pRtlIsTextUnicode)
|
||||
test_RtlIsTextUnicode();
|
||||
test_RtlInitUnicodeStringEx();
|
||||
test_RtlDuplicateUnicodeString();
|
||||
test_RtlFindCharInUnicodeString();
|
||||
test_RtlGUIDFromString();
|
||||
test_RtlStringFromGUID();
|
||||
test_RtlIsTextUnicode();
|
||||
if(0)
|
||||
{
|
||||
test_RtlUpcaseUnicodeChar();
|
||||
test_RtlUpcaseUnicodeString();
|
||||
test_RtlDowncaseUnicodeString();
|
||||
}
|
||||
test_RtlHashUnicodeString();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue