[NTDLL_WINETEST] Sync with Wine Staging 2.16. CORE-13762

This commit is contained in:
Amine Khaldi
2017-10-23 13:48:05 +01:00
parent ab3045c504
commit f7932ba2de
18 changed files with 6782 additions and 701 deletions
@@ -1,7 +1,7 @@
include_directories(BEFORE ${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine)
remove_definitions(-DWINVER=0x502 -D_WIN32_IE=0x600 -D_WIN32_WINNT=0x502)
add_definitions(-D__WINESRC__)
add_definitions(-D__WINESRC__ -DWINETEST_USE_DBGSTR_LONGLONG)
list(APPEND SOURCE
atom.c
@@ -17,6 +17,7 @@ list(APPEND SOURCE
path.c
pipe.c
port.c
process.c
reg.c
rtl.c
rtlbitmap.c
+528 -62
View File
@@ -34,16 +34,20 @@
#define WIN32_NO_STATUS
#include "wine/test.h"
#include "winnls.h"
#include "wine/winternl.h"
static NTSTATUS (WINAPI *pNtClose)( PHANDLE );
static NTSTATUS (WINAPI *pNtOpenFile) ( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, ULONG, ULONG );
static NTSTATUS (WINAPI *pNtQueryDirectoryFile)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,
PVOID,ULONG,FILE_INFORMATION_CLASS,BOOLEAN,PUNICODE_STRING,BOOLEAN);
static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,LONG,FILE_INFORMATION_CLASS);
static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,FILE_INFORMATION_CLASS);
static BOOLEAN (WINAPI *pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING,LPCSTR);
static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)( LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR* );
static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
static VOID (WINAPI *pRtlFreeUnicodeString)( PUNICODE_STRING );
static LONG (WINAPI *pRtlCompareUnicodeString)( const UNICODE_STRING*, const UNICODE_STRING*,BOOLEAN );
static NTSTATUS (WINAPI *pRtlMultiByteToUnicodeN)( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
LPCSTR src, DWORD srclen );
static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirection)( BOOLEAN enable );
@@ -53,47 +57,56 @@ static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirectionEx)( ULONG disable, ULONG *
static struct testfile_s {
BOOL attr_done; /* set if attributes were tested for this file already */
const DWORD attr; /* desired attribute */
const char *name; /* filename to use */
WCHAR name[20]; /* filename to use */
const char *target; /* what to point to (only for reparse pts) */
const char *description; /* for error messages */
int nfound; /* How many were found (expect 1) */
WCHAR nameW[20]; /* unicode version of name (filled in later) */
} testfiles[] = {
{ 0, FILE_ATTRIBUTE_NORMAL, "n.tmp", NULL, "normal" },
{ 0, FILE_ATTRIBUTE_HIDDEN, "h.tmp", NULL, "hidden" },
{ 0, FILE_ATTRIBUTE_SYSTEM, "s.tmp", NULL, "system" },
{ 0, FILE_ATTRIBUTE_DIRECTORY, "d.tmp", NULL, "directory" },
{ 0, FILE_ATTRIBUTE_DIRECTORY, ".", NULL, ". directory" },
{ 0, FILE_ATTRIBUTE_DIRECTORY, "..", NULL, ".. directory" },
{ 0, 0, NULL }
{ 0, FILE_ATTRIBUTE_NORMAL, {'l','o','n','g','f','i','l','e','n','a','m','e','.','t','m','p'}, "normal" },
{ 0, FILE_ATTRIBUTE_NORMAL, {'n','.','t','m','p',}, "normal" },
{ 0, FILE_ATTRIBUTE_HIDDEN, {'h','.','t','m','p',}, "hidden" },
{ 0, FILE_ATTRIBUTE_SYSTEM, {'s','.','t','m','p',}, "system" },
{ 0, FILE_ATTRIBUTE_DIRECTORY, {'d','.','t','m','p',}, "directory" },
{ 0, FILE_ATTRIBUTE_NORMAL, {0xe9,'a','.','t','m','p'}, "normal" },
{ 0, FILE_ATTRIBUTE_NORMAL, {0xc9,'b','.','t','m','p'}, "normal" },
{ 0, FILE_ATTRIBUTE_NORMAL, {'e','a','.','t','m','p'}, "normal" },
{ 0, FILE_ATTRIBUTE_DIRECTORY, {'.'}, ". directory" },
{ 0, FILE_ATTRIBUTE_DIRECTORY, {'.','.'}, ".. directory" }
};
static const int max_test_dir_size = 20; /* size of above plus some for .. etc */
static const int test_dir_count = sizeof(testfiles) / sizeof(testfiles[0]);
static const int max_test_dir_size = sizeof(testfiles) / sizeof(testfiles[0]) + 5; /* size of above plus some for .. etc */
static const WCHAR dummyW[] = {'d','u','m','m','y',0};
static const WCHAR dotW[] = {'.',0};
static const WCHAR dotdotW[] = {'.','.',0};
static const WCHAR backslashW[] = {'\\',0};
/* Create a test directory full of attribute test files, clear counts */
static void set_up_attribute_test(const char *testdirA)
static void set_up_attribute_test(const WCHAR *testdir)
{
int i;
BOOL ret;
ret = CreateDirectoryA(testdirA, NULL);
ok(ret, "couldn't create dir '%s', error %d\n", testdirA, GetLastError());
ret = CreateDirectoryW(testdir, NULL);
ok(ret, "couldn't create dir %s, error %d\n", wine_dbgstr_w(testdir), GetLastError());
for (i=0; testfiles[i].name; i++) {
char buf[MAX_PATH];
pRtlMultiByteToUnicodeN(testfiles[i].nameW, sizeof(testfiles[i].nameW), NULL, testfiles[i].name, strlen(testfiles[i].name)+1);
for (i=0; i < test_dir_count; i++) {
WCHAR buf[MAX_PATH];
if (strcmp(testfiles[i].name, ".") == 0 || strcmp(testfiles[i].name, "..") == 0)
if (lstrcmpW(testfiles[i].name, dotW) == 0 || lstrcmpW(testfiles[i].name, dotdotW) == 0)
continue;
sprintf(buf, "%s\\%s", testdirA, testfiles[i].name);
lstrcpyW( buf, testdir );
lstrcatW( buf, backslashW );
lstrcatW( buf, testfiles[i].name );
if (testfiles[i].attr & FILE_ATTRIBUTE_DIRECTORY) {
ret = CreateDirectoryA(buf, NULL);
ok(ret, "couldn't create dir '%s', error %d\n", buf, GetLastError());
ret = CreateDirectoryW(buf, NULL);
ok(ret, "couldn't create dir %s, error %d\n", wine_dbgstr_w(buf), GetLastError());
} else {
HANDLE h = CreateFileA(buf,
HANDLE h = CreateFileW(buf,
GENERIC_READ|GENERIC_WRITE,
0, NULL, CREATE_ALWAYS,
testfiles[i].attr, 0);
ok( h != INVALID_HANDLE_VALUE, "failed to create temp file '%s'\n", buf );
ok( h != INVALID_HANDLE_VALUE, "failed to create temp file %s\n", wine_dbgstr_w(buf) );
CloseHandle(h);
}
}
@@ -103,32 +116,34 @@ static void reset_found_files(void)
{
int i;
for (i = 0; testfiles[i].name; i++)
for (i = 0; i < test_dir_count; i++)
testfiles[i].nfound = 0;
}
/* Remove the given test directory and the attribute test files, if any */
static void tear_down_attribute_test(const char *testdirA)
static void tear_down_attribute_test(const WCHAR *testdir)
{
int i;
for (i=0; testfiles[i].name; i++) {
for (i = 0; i < test_dir_count; i++) {
int ret;
char buf[MAX_PATH];
if (strcmp(testfiles[i].name, ".") == 0 || strcmp(testfiles[i].name, "..") == 0)
WCHAR buf[MAX_PATH];
if (lstrcmpW(testfiles[i].name, dotW) == 0 || lstrcmpW(testfiles[i].name, dotdotW) == 0)
continue;
sprintf(buf, "%s\\%s", testdirA, testfiles[i].name);
lstrcpyW( buf, testdir );
lstrcatW( buf, backslashW );
lstrcatW( buf, testfiles[i].name );
if (testfiles[i].attr & FILE_ATTRIBUTE_DIRECTORY) {
ret = RemoveDirectoryA(buf);
ret = RemoveDirectoryW(buf);
ok(ret || (GetLastError() == ERROR_PATH_NOT_FOUND),
"Failed to rmdir %s, error %d\n", buf, GetLastError());
"Failed to rmdir %s, error %d\n", wine_dbgstr_w(buf), GetLastError());
} else {
ret = DeleteFileA(buf);
ret = DeleteFileW(buf);
ok(ret || (GetLastError() == ERROR_PATH_NOT_FOUND),
"Failed to rm %s, error %d\n", buf, GetLastError());
"Failed to rm %s, error %d\n", wine_dbgstr_w(buf), GetLastError());
}
}
RemoveDirectoryA(testdirA);
RemoveDirectoryW(testdir);
}
/* Match one found file against testfiles[], increment count if found */
@@ -141,35 +156,37 @@ static void tally_test_file(FILE_BOTH_DIRECTORY_INFORMATION *dir_info)
WCHAR *nameW = dir_info->FileName;
int namelen = dir_info->FileNameLength / sizeof(WCHAR);
for (i=0; testfiles[i].name; i++) {
int len = strlen(testfiles[i].name);
if (namelen != len || memcmp(nameW, testfiles[i].nameW, len*sizeof(WCHAR)))
for (i = 0; i < test_dir_count; i++) {
int len = lstrlenW(testfiles[i].name);
if (namelen != len || memcmp(nameW, testfiles[i].name, len*sizeof(WCHAR)))
continue;
if (!testfiles[i].attr_done) {
ok (attrib == (testfiles[i].attr & attribmask), "file %s: expected %s (%x), got %x (is your linux new enough?)\n", testfiles[i].name, testfiles[i].description, testfiles[i].attr, attrib);
ok (attrib == (testfiles[i].attr & attribmask), "file %s: expected %s (%x), got %x (is your linux new enough?)\n", wine_dbgstr_w(testfiles[i].name), testfiles[i].description, testfiles[i].attr, attrib);
testfiles[i].attr_done = TRUE;
}
testfiles[i].nfound++;
break;
}
ok(testfiles[i].name != NULL, "unexpected file found\n");
ok(i < test_dir_count, "unexpected file found %s\n", wine_dbgstr_wn(dir_info->FileName, namelen));
}
static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char *testdirA,
UNICODE_STRING *mask,
BOOLEAN single_entry, BOOLEAN restart_flag)
{
HANDLE dirh;
UNICODE_STRING dummy_mask;
HANDLE dirh, new_dirh;
IO_STATUS_BLOCK io;
UINT data_pos, data_size;
UINT data_len; /* length of dir data */
BYTE data[8192]; /* directory data */
FILE_BOTH_DIRECTORY_INFORMATION *dir_info;
DWORD status;
NTSTATUS status;
int numfiles;
int i;
reset_found_files();
pRtlInitUnicodeString( &dummy_mask, dummyW );
data_size = mask ? offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[256] ) : sizeof(data);
@@ -182,12 +199,18 @@ static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char
return;
}
pNtQueryDirectoryFile( dirh, NULL, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, single_entry, mask, restart_flag );
U(io).Status = 0xdeadbeef;
status = pNtQueryDirectoryFile( dirh, NULL, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, single_entry, mask, restart_flag );
ok (status == STATUS_SUCCESS, "failed to query directory; status %x\n", status);
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");
DuplicateHandle( GetCurrentProcess(), dirh, GetCurrentProcess(), &new_dirh,
0, FALSE, DUPLICATE_SAME_ACCESS );
pNtClose(dirh);
data_pos = 0;
numfiles = 0;
while ((data_pos < data_len) && (numfiles < max_test_dir_size)) {
@@ -196,11 +219,12 @@ 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, data_size,
FileBothDirectoryInformation, single_entry, mask, FALSE );
if (U(io).Status == STATUS_NO_MORE_FILES)
break;
ok (U(io).Status == STATUS_SUCCESS, "failed to query directory; status %x\n", U(io).Status);
U(io).Status = 0xdeadbeef;
status = pNtQueryDirectoryFile( new_dirh, 0, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, single_entry, &dummy_mask, FALSE );
ok (U(io).Status == status, "wrong status %x / %x\n", status, U(io).Status);
if (status == STATUS_NO_MORE_FILES) break;
ok (status == STATUS_SUCCESS, "failed to query directory; status %x\n", status);
data_len = io.Information;
if (data_len < sizeof(FILE_BOTH_DIRECTORY_INFORMATION))
break;
@@ -213,33 +237,238 @@ static void test_flags_NtQueryDirectoryFile(OBJECT_ATTRIBUTES *attr, const char
ok(numfiles < max_test_dir_size, "too many loops\n");
if (mask)
for (i=0; testfiles[i].name; i++)
ok(testfiles[i].nfound == (testfiles[i].nameW == mask->Buffer),
for (i = 0; i < test_dir_count; i++)
ok(testfiles[i].nfound == (testfiles[i].name == 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++)
for (i = 0; i < test_dir_count; 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);
pNtClose(new_dirh);
}
static void test_directory_sort( const WCHAR *testdir )
{
OBJECT_ATTRIBUTES attr;
UNICODE_STRING ntdirname;
IO_STATUS_BLOCK io;
UINT data_pos, data_len, count;
BYTE data[8192];
WCHAR prev[MAX_PATH], name[MAX_PATH];
UNICODE_STRING prev_str, name_str;
FILE_BOTH_DIRECTORY_INFORMATION *info;
NTSTATUS status;
HANDLE handle;
int res;
if (!pRtlDosPathNameToNtPathName_U( testdir, &ntdirname, NULL, NULL ))
{
ok(0, "RtlDosPathNametoNtPathName_U failed\n");
return;
}
InitializeObjectAttributes( &attr, &ntdirname, OBJ_CASE_INSENSITIVE, 0, NULL );
status = pNtOpenFile( &handle, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE );
ok(status == STATUS_SUCCESS, "failed to open dir %s\n", wine_dbgstr_w(testdir) );
U(io).Status = 0xdeadbeef;
status = pNtQueryDirectoryFile( handle, NULL, NULL, NULL, &io, data, sizeof(data),
FileBothDirectoryInformation, FALSE, NULL, TRUE );
ok( status == STATUS_SUCCESS, "failed to query directory; status %x\n", status );
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" );
data_pos = 0;
count = 0;
while (data_pos < data_len)
{
info = (FILE_BOTH_DIRECTORY_INFORMATION *)(data + data_pos);
memcpy( name, info->FileName, info->FileNameLength );
name[info->FileNameLength / sizeof(WCHAR)] = 0;
switch (count)
{
case 0: /* first entry must be '.' */
ok( !lstrcmpW( name, dotW ), "wrong name %s\n", wine_dbgstr_w( name ));
break;
case 1: /* second entry must be '..' */
ok( !lstrcmpW( name, dotdotW ), "wrong name %s\n", wine_dbgstr_w( name ));
break;
case 2: /* nothing to compare against */
break;
default:
pRtlInitUnicodeString( &prev_str, prev );
pRtlInitUnicodeString( &name_str, name );
res = pRtlCompareUnicodeString( &prev_str, &name_str, TRUE );
ok( res < 0, "wrong result %d %s %s\n", res, wine_dbgstr_w( prev ), wine_dbgstr_w( name ));
break;
}
count++;
lstrcpyW( prev, name );
if (info->NextEntryOffset == 0)
{
U(io).Status = 0xdeadbeef;
status = pNtQueryDirectoryFile( handle, 0, NULL, NULL, &io, data, sizeof(data),
FileBothDirectoryInformation, FALSE, NULL, FALSE );
ok (U(io).Status == status, "wrong status %x / %x\n", status, U(io).Status);
if (status == STATUS_NO_MORE_FILES) break;
ok( status == STATUS_SUCCESS, "failed to query directory; status %x\n", status );
data_len = io.Information;
data_pos = 0;
}
else data_pos += info->NextEntryOffset;
}
pNtClose( handle );
pRtlFreeUnicodeString( &ntdirname );
}
static void test_NtQueryDirectoryFile_classes( HANDLE handle, UNICODE_STRING *mask )
{
IO_STATUS_BLOCK io;
UINT data_size;
ULONG data[256];
NTSTATUS status;
int class;
for (class = 0; class < FileMaximumInformation; class++)
{
U(io).Status = 0xdeadbeef;
U(io).Information = 0xdeadbeef;
data_size = 0;
memset( data, 0x55, sizeof(data) );
status = pNtQueryDirectoryFile( handle, 0, NULL, NULL, &io, data, data_size,
class, FALSE, mask, TRUE );
ok( U(io).Status == 0xdeadbeef, "%u: wrong status %x\n", class, U(io).Status );
ok( U(io).Information == 0xdeadbeef, "%u: wrong info %lx\n", class, U(io).Information );
ok(data[0] == 0x55555555, "%u: wrong offset %x\n", class, data[0] );
switch (class)
{
case FileIdGlobalTxDirectoryInformation:
case FileIdExtdDirectoryInformation:
case FileIdExtdBothDirectoryInformation:
if (status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED) continue;
/* fall through */
case FileDirectoryInformation:
case FileFullDirectoryInformation:
case FileBothDirectoryInformation:
case FileNamesInformation:
case FileIdBothDirectoryInformation:
case FileIdFullDirectoryInformation:
case FileObjectIdInformation:
case FileQuotaInformation:
case FileReparsePointInformation:
ok( status == STATUS_INFO_LENGTH_MISMATCH, "%u: wrong status %x\n", class, status );
break;
default:
ok( status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED,
"%u: wrong status %x\n", class, status );
continue;
}
for (data_size = 1; data_size < sizeof(data); data_size++)
{
status = pNtQueryDirectoryFile( handle, 0, NULL, NULL, &io, data, data_size,
class, FALSE, mask, TRUE );
if (status == STATUS_BUFFER_OVERFLOW)
{
ok( U(io).Status == STATUS_BUFFER_OVERFLOW, "%u: wrong status %x\n", class, U(io).Status );
ok( U(io).Information == data_size, "%u: wrong info %lx\n", class, U(io).Information );
ok(data[0] == 0, "%u: wrong offset %x\n", class, data[0] );
}
else
{
ok( U(io).Status == 0xdeadbeef, "%u: wrong status %x\n", class, U(io).Status );
ok( U(io).Information == 0xdeadbeef, "%u: wrong info %lx\n", class, U(io).Information );
ok(data[0] == 0x55555555, "%u: wrong offset %x\n", class, data[0] );
}
if (status != STATUS_INFO_LENGTH_MISMATCH) break;
}
switch (class)
{
case FileDirectoryInformation:
ok( status == STATUS_BUFFER_OVERFLOW, "%u: wrong status %x\n", class, status );
ok( data_size == ((offsetof( FILE_DIRECTORY_INFORMATION, FileName[1] ) + 7) & ~7),
"%u: wrong size %u\n", class, data_size );
break;
case FileFullDirectoryInformation:
ok( status == STATUS_BUFFER_OVERFLOW, "%u: wrong status %x\n", class, status );
ok( data_size == ((offsetof( FILE_FULL_DIRECTORY_INFORMATION, FileName[1] ) + 7) & ~7),
"%u: wrong size %u\n", class, data_size );
break;
case FileBothDirectoryInformation:
ok( status == STATUS_BUFFER_OVERFLOW, "%u: wrong status %x\n", class, status );
ok( data_size == ((offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[1] ) + 7) & ~7),
"%u: wrong size %u\n", class, data_size );
break;
case FileNamesInformation:
ok( status == STATUS_BUFFER_OVERFLOW, "%u: wrong status %x\n", class, status );
ok( data_size == ((offsetof( FILE_NAMES_INFORMATION, FileName[1] ) + 7) & ~7),
"%u: wrong size %u\n", class, data_size );
break;
case FileIdBothDirectoryInformation:
ok( status == STATUS_BUFFER_OVERFLOW, "%u: wrong status %x\n", class, status );
ok( data_size == ((offsetof( FILE_ID_BOTH_DIRECTORY_INFORMATION, FileName[1] ) + 7) & ~7),
"%u: wrong size %u\n", class, data_size );
break;
case FileIdFullDirectoryInformation:
ok( status == STATUS_BUFFER_OVERFLOW, "%u: wrong status %x\n", class, status );
ok( data_size == ((offsetof( FILE_ID_FULL_DIRECTORY_INFORMATION, FileName[1] ) + 7) & ~7),
"%u: wrong size %u\n", class, data_size );
break;
case FileIdGlobalTxDirectoryInformation:
ok( status == STATUS_BUFFER_OVERFLOW, "%u: wrong status %x\n", class, status );
ok( data_size == ((offsetof( FILE_ID_GLOBAL_TX_DIR_INFORMATION, FileName[1] ) + 7) & ~7),
"%u: wrong size %u\n", class, data_size );
break;
case FileObjectIdInformation:
ok( status == STATUS_INVALID_INFO_CLASS, "%u: wrong status %x\n", class, status );
ok( data_size == sizeof(FILE_OBJECTID_INFORMATION), "%u: wrong size %u\n", class, data_size );
break;
case FileQuotaInformation:
ok( status == STATUS_INVALID_INFO_CLASS, "%u: wrong status %x\n", class, status );
ok( data_size == sizeof(FILE_QUOTA_INFORMATION), "%u: wrong size %u\n", class, data_size );
break;
case FileReparsePointInformation:
ok( status == STATUS_INVALID_INFO_CLASS, "%u: wrong status %x\n", class, status );
ok( data_size == sizeof(FILE_REPARSE_POINT_INFORMATION), "%u: wrong size %u\n", class, data_size );
break;
}
}
}
static void test_NtQueryDirectoryFile(void)
{
OBJECT_ATTRIBUTES attr;
UNICODE_STRING ntdirname;
UNICODE_STRING ntdirname, mask;
char testdirA[MAX_PATH];
WCHAR testdirW[MAX_PATH];
int i;
IO_STATUS_BLOCK io;
WCHAR short_name[12];
UINT data_size;
BYTE data[8192];
FILE_BOTH_DIRECTORY_INFORMATION *next, *fbdi = (FILE_BOTH_DIRECTORY_INFORMATION*)data;
FILE_POSITION_INFORMATION pos_info;
FILE_NAMES_INFORMATION *names;
const WCHAR *filename = fbdi->FileName;
NTSTATUS status;
HANDLE dirh;
/* Clean up from prior aborted run, if any, then set up test files */
ok(GetTempPathA(MAX_PATH, testdirA), "couldn't get temp dir\n");
strcat(testdirA, "NtQueryDirectoryFile.tmp");
tear_down_attribute_test(testdirA);
set_up_attribute_test(testdirA);
pRtlMultiByteToUnicodeN(testdirW, sizeof(testdirW), NULL, testdirA, strlen(testdirA)+1);
tear_down_attribute_test(testdirW);
set_up_attribute_test(testdirW);
if (!pRtlDosPathNameToNtPathName_U(testdirW, &ntdirname, NULL, NULL))
{
ok(0, "RtlDosPathNametoNtPathName_U failed\n");
@@ -252,21 +481,250 @@ static void test_NtQueryDirectoryFile(void)
test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, TRUE, TRUE);
test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, TRUE, FALSE);
for (i = 0; testfiles[i].name; i++)
for (i = 0; i < test_dir_count; 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);
if (testfiles[i].name[0] == '.') continue; /* . and .. as masks are broken on Windows */
mask.Buffer = testfiles[i].name;
mask.Length = mask.MaximumLength = lstrlenW(testfiles[i].name) * 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);
}
/* short path passed as mask */
status = pNtOpenFile(&dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE);
ok(status == STATUS_SUCCESS, "failed to open dir '%s'\n", testdirA);
if (status != STATUS_SUCCESS) {
skip("can't test if we can't open the directory\n");
return;
}
status = pNtQueryInformationFile( dirh, &io, &pos_info, sizeof(pos_info), FilePositionInformation );
ok( status == STATUS_SUCCESS, "NtQueryInformationFile failed %x\n", status );
ok( pos_info.CurrentByteOffset.QuadPart == 0, "wrong pos %s\n",
wine_dbgstr_longlong(pos_info.CurrentByteOffset.QuadPart));
pos_info.CurrentByteOffset.QuadPart = 0xbeef;
status = pNtSetInformationFile( dirh, &io, &pos_info, sizeof(pos_info), FilePositionInformation );
ok( status == STATUS_SUCCESS, "NtQueryInformationFile failed %x\n", status );
status = pNtQueryInformationFile( dirh, &io, &pos_info, sizeof(pos_info), FilePositionInformation );
ok( status == STATUS_SUCCESS, "NtQueryInformationFile failed %x\n", status );
ok( pos_info.CurrentByteOffset.QuadPart == 0xbeef, "wrong pos %s\n",
wine_dbgstr_longlong(pos_info.CurrentByteOffset.QuadPart));
mask.Buffer = testfiles[0].name;
mask.Length = mask.MaximumLength = lstrlenW(testfiles[0].name) * sizeof(WCHAR);
data_size = offsetof(FILE_BOTH_DIRECTORY_INFORMATION, FileName[256]);
U(io).Status = 0xdeadbeef;
status = pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, TRUE, &mask, FALSE);
ok(status == STATUS_SUCCESS, "failed to query directory; status %x\n", status);
ok(U(io).Status == STATUS_SUCCESS, "failed to query directory; status %x\n", U(io).Status);
ok(fbdi->ShortName[0], "ShortName is empty\n");
status = pNtQueryInformationFile( dirh, &io, &pos_info, sizeof(pos_info), FilePositionInformation );
ok( status == STATUS_SUCCESS, "NtQueryInformationFile failed %x\n", status );
ok( pos_info.CurrentByteOffset.QuadPart == 0xbeef, "wrong pos %s\n",
wine_dbgstr_longlong(pos_info.CurrentByteOffset.QuadPart) );
mask.Length = mask.MaximumLength = fbdi->ShortNameLength;
memcpy(short_name, fbdi->ShortName, mask.Length);
mask.Buffer = short_name;
U(io).Status = 0xdeadbeef;
U(io).Information = 0xdeadbeef;
status = pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, TRUE, &mask, TRUE);
ok(status == STATUS_SUCCESS, "failed to query directory status %x\n", status);
ok(U(io).Status == STATUS_SUCCESS, "failed to query directory status %x\n", U(io).Status);
ok(U(io).Information == offsetof(FILE_BOTH_DIRECTORY_INFORMATION, FileName[lstrlenW(testfiles[0].name)]),
"wrong info %lx\n", U(io).Information);
ok(fbdi->FileNameLength == lstrlenW(testfiles[0].name)*sizeof(WCHAR) &&
!memcmp(fbdi->FileName, testfiles[0].name, fbdi->FileNameLength),
"incorrect long file name: %s\n", wine_dbgstr_wn(fbdi->FileName,
fbdi->FileNameLength/sizeof(WCHAR)));
status = pNtQueryInformationFile( dirh, &io, &pos_info, sizeof(pos_info), FilePositionInformation );
ok( status == STATUS_SUCCESS, "NtQueryInformationFile failed %x\n", status );
ok( pos_info.CurrentByteOffset.QuadPart == 0xbeef, "wrong pos %s\n",
wine_dbgstr_longlong(pos_info.CurrentByteOffset.QuadPart) );
/* tests with short buffer */
memset( data, 0x55, data_size );
U(io).Status = 0xdeadbeef;
U(io).Information = 0xdeadbeef;
data_size = offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[1] );
status = pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, TRUE, &mask, TRUE);
ok( status == STATUS_BUFFER_OVERFLOW, "wrong status %x\n", status );
ok( U(io).Status == STATUS_BUFFER_OVERFLOW, "wrong status %x\n", U(io).Status );
ok( U(io).Information == data_size || broken( U(io).Information == 0),
"wrong info %lx\n", U(io).Information );
ok( fbdi->NextEntryOffset == 0, "wrong offset %x\n", fbdi->NextEntryOffset );
ok( fbdi->FileNameLength == lstrlenW(testfiles[0].name) * sizeof(WCHAR),
"wrong length %x\n", fbdi->FileNameLength );
ok( filename[0] == testfiles[0].name[0], "incorrect long file name: %s\n",
wine_dbgstr_wn(fbdi->FileName, fbdi->FileNameLength/sizeof(WCHAR)));
ok( filename[1] == 0x5555, "incorrect long file name: %s\n",
wine_dbgstr_wn(fbdi->FileName, fbdi->FileNameLength/sizeof(WCHAR)));
test_NtQueryDirectoryFile_classes( dirh, &mask );
/* mask may or may not be ignored when restarting the search */
pRtlInitUnicodeString( &mask, dummyW );
U(io).Status = 0xdeadbeef;
data_size = offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[256] );
status = pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, TRUE, &mask, TRUE);
ok( status == STATUS_SUCCESS || status == STATUS_NO_MORE_FILES, "wrong status %x\n", status );
ok( U(io).Status == status, "wrong status %x / %x\n", U(io).Status, status );
if (!status)
ok( fbdi->FileNameLength == lstrlenW(testfiles[0].name)*sizeof(WCHAR) &&
!memcmp(fbdi->FileName, testfiles[0].name, fbdi->FileNameLength),
"incorrect long file name: %s\n",
wine_dbgstr_wn(fbdi->FileName, fbdi->FileNameLength/sizeof(WCHAR)));
pNtClose(dirh);
status = pNtOpenFile(&dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE);
ok(status == STATUS_SUCCESS, "failed to open dir '%s'\n", testdirA);
memset( data, 0x55, data_size );
data_size = sizeof(data);
U(io).Status = 0xdeadbeef;
U(io).Information = 0xdeadbeef;
status = pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, FALSE, NULL, TRUE);
ok(status == STATUS_SUCCESS, "wrong status %x\n", status);
ok(U(io).Status == STATUS_SUCCESS, "wrong status %x\n", U(io).Status);
ok(U(io).Information > 0 && U(io).Information < data_size, "wrong info %lx\n", U(io).Information);
ok( fbdi->NextEntryOffset == ((offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[1] ) + 7) & ~7),
"wrong offset %x\n", fbdi->NextEntryOffset );
ok( fbdi->FileNameLength == sizeof(WCHAR), "wrong length %x\n", fbdi->FileNameLength );
ok( fbdi->FileName[0] == '.', "incorrect long file name: %s\n",
wine_dbgstr_wn(fbdi->FileName, fbdi->FileNameLength/sizeof(WCHAR)));
next = (FILE_BOTH_DIRECTORY_INFORMATION *)(data + fbdi->NextEntryOffset);
ok( next->NextEntryOffset == ((offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[2] ) + 7) & ~7),
"wrong offset %x\n", next->NextEntryOffset );
ok( next->FileNameLength == 2 * sizeof(WCHAR), "wrong length %x\n", next->FileNameLength );
filename = next->FileName;
ok( filename[0] == '.' && filename[1] == '.', "incorrect long file name: %s\n",
wine_dbgstr_wn(next->FileName, next->FileNameLength/sizeof(WCHAR)));
data_size = fbdi->NextEntryOffset + offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[1] ),
memset( data, 0x55, data_size );
U(io).Status = 0xdeadbeef;
U(io).Information = 0xdeadbeef;
status = pNtQueryDirectoryFile( dirh, 0, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, FALSE, NULL, TRUE );
ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
ok( U(io).Status == STATUS_SUCCESS, "wrong status %x\n", U(io).Status );
ok( U(io).Information == offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[1] ),
"wrong info %lx\n", U(io).Information );
ok( fbdi->NextEntryOffset == 0, "wrong offset %x\n", fbdi->NextEntryOffset );
ok( fbdi->FileNameLength == sizeof(WCHAR), "wrong length %x\n", fbdi->FileNameLength );
ok( fbdi->FileName[0] == '.', "incorrect long file name: %s\n",
wine_dbgstr_wn(fbdi->FileName, fbdi->FileNameLength/sizeof(WCHAR)));
next = (FILE_BOTH_DIRECTORY_INFORMATION *)&fbdi->FileName[1];
ok( next->NextEntryOffset == 0x55555555, "wrong offset %x\n", next->NextEntryOffset );
data_size = fbdi->NextEntryOffset + offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[2] ),
memset( data, 0x55, data_size );
U(io).Status = 0xdeadbeef;
U(io).Information = 0xdeadbeef;
status = pNtQueryDirectoryFile( dirh, 0, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, FALSE, NULL, TRUE );
ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
ok( U(io).Status == STATUS_SUCCESS, "wrong status %x\n", U(io).Status );
ok( U(io).Information == offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[1] ),
"wrong info %lx\n", U(io).Information );
ok( fbdi->NextEntryOffset == 0, "wrong offset %x\n", fbdi->NextEntryOffset );
data_size = ((offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[1] ) + 7) & ~7) +
offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[2] );
memset( data, 0x55, data_size );
U(io).Status = 0xdeadbeef;
U(io).Information = 0xdeadbeef;
status = pNtQueryDirectoryFile( dirh, 0, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, FALSE, NULL, TRUE );
ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
ok( U(io).Status == STATUS_SUCCESS, "wrong status %x\n", U(io).Status );
ok( U(io).Information == data_size, "wrong info %lx / %x\n", U(io).Information, data_size );
ok( fbdi->NextEntryOffset == ((offsetof( FILE_BOTH_DIRECTORY_INFORMATION, FileName[1] ) + 7) & ~7),
"wrong offset %x\n", fbdi->NextEntryOffset );
ok( fbdi->FileNameLength == sizeof(WCHAR), "wrong length %x\n", fbdi->FileNameLength );
ok( fbdi->FileName[0] == '.', "incorrect long file name: %s\n",
wine_dbgstr_wn(fbdi->FileName, fbdi->FileNameLength/sizeof(WCHAR)));
next = (FILE_BOTH_DIRECTORY_INFORMATION *)(data + fbdi->NextEntryOffset);
ok( next->NextEntryOffset == 0, "wrong offset %x\n", next->NextEntryOffset );
ok( next->FileNameLength == 2 * sizeof(WCHAR), "wrong length %x\n", next->FileNameLength );
filename = next->FileName;
ok( filename[0] == '.' && filename[1] == '.', "incorrect long file name: %s\n",
wine_dbgstr_wn(next->FileName, next->FileNameLength/sizeof(WCHAR)));
data_size = ((offsetof( FILE_NAMES_INFORMATION, FileName[1] ) + 7) & ~7) +
offsetof( FILE_NAMES_INFORMATION, FileName[2] );
memset( data, 0x55, data_size );
U(io).Status = 0xdeadbeef;
U(io).Information = 0xdeadbeef;
status = pNtQueryDirectoryFile( dirh, 0, NULL, NULL, &io, data, data_size,
FileNamesInformation, FALSE, NULL, TRUE );
ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
ok( U(io).Status == STATUS_SUCCESS, "wrong status %x\n", U(io).Status );
ok( U(io).Information == data_size, "wrong info %lx / %x\n", U(io).Information, data_size );
names = (FILE_NAMES_INFORMATION *)data;
ok( names->NextEntryOffset == ((offsetof( FILE_NAMES_INFORMATION, FileName[1] ) + 7) & ~7),
"wrong offset %x\n", names->NextEntryOffset );
ok( names->FileNameLength == sizeof(WCHAR), "wrong length %x\n", names->FileNameLength );
ok( names->FileName[0] == '.', "incorrect long file name: %s\n",
wine_dbgstr_wn(names->FileName, names->FileNameLength/sizeof(WCHAR)));
names = (FILE_NAMES_INFORMATION *)(data + names->NextEntryOffset);
ok( names->NextEntryOffset == 0, "wrong offset %x\n", names->NextEntryOffset );
ok( names->FileNameLength == 2 * sizeof(WCHAR), "wrong length %x\n", names->FileNameLength );
filename = names->FileName;
ok( filename[0] == '.' && filename[1] == '.', "incorrect long file name: %s\n",
wine_dbgstr_wn(names->FileName, names->FileNameLength/sizeof(WCHAR)));
pNtClose(dirh);
/* create new handle to change mask */
status = pNtOpenFile(&dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE);
ok(status == STATUS_SUCCESS, "failed to open dir '%s'\n", testdirA);
pRtlInitUnicodeString( &mask, dummyW );
U(io).Status = 0xdeadbeef;
data_size = sizeof(data);
status = pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, TRUE, &mask, TRUE);
ok(status == STATUS_NO_SUCH_FILE, "wrong status %x\n", status);
ok(U(io).Status == 0xdeadbeef, "wrong status %x\n", U(io).Status);
U(io).Status = 0xdeadbeef;
status = pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, TRUE, NULL, FALSE);
ok(status == STATUS_NO_MORE_FILES, "wrong status %x\n", status);
ok(U(io).Status == STATUS_NO_MORE_FILES, "wrong status %x\n", U(io).Status);
U(io).Status = 0xdeadbeef;
status = pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, TRUE, NULL, TRUE);
ok(status == STATUS_NO_MORE_FILES, "wrong status %x\n", status);
ok(U(io).Status == STATUS_NO_MORE_FILES, "wrong status %x\n", U(io).Status);
pNtClose(dirh);
U(io).Status = 0xdeadbeef;
status = pNtQueryDirectoryFile( (HANDLE)0xbeef, 0, NULL, NULL, &io, data, data_size,
FileBothDirectoryInformation, TRUE, NULL, TRUE );
ok(status == STATUS_INVALID_HANDLE, "wrong status %x\n", status);
ok(U(io).Status == 0xdeadbeef, "wrong status %x\n", U(io).Status);
done:
tear_down_attribute_test(testdirA);
test_directory_sort( testdirW );
tear_down_attribute_test( testdirW );
pRtlFreeUnicodeString(&ntdirname);
}
@@ -403,6 +861,8 @@ static void test_redirection(void)
ok( status == STATUS_ACCESS_VIOLATION, "RtlWow64EnableFsRedirectionEx failed with status %x\n", status );
status = pRtlWow64EnableFsRedirectionEx( TRUE, (void*)1 );
ok( status == STATUS_ACCESS_VIOLATION, "RtlWow64EnableFsRedirectionEx failed with status %x\n", status );
status = pRtlWow64EnableFsRedirectionEx( TRUE, (void*)0xDEADBEEF );
ok( status == STATUS_ACCESS_VIOLATION, "RtlWow64EnableFsRedirectionEx failed with status %x\n", status );
status = pRtlWow64EnableFsRedirection( FALSE );
ok( !status, "RtlWow64EnableFsRedirectionEx failed status %x\n", status );
@@ -415,6 +875,7 @@ static void test_redirection(void)
START_TEST(directory)
{
WCHAR sysdir[MAX_PATH];
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
if (!hntdll)
{
@@ -425,14 +886,19 @@ START_TEST(directory)
pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
pNtQueryDirectoryFile = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
pNtSetInformationFile = (void *)GetProcAddress(hntdll, "NtSetInformationFile");
pRtlCreateUnicodeStringFromAsciiz = (void *)GetProcAddress(hntdll, "RtlCreateUnicodeStringFromAsciiz");
pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
pRtlCompareUnicodeString = (void *)GetProcAddress(hntdll, "RtlCompareUnicodeString");
pRtlMultiByteToUnicodeN = (void *)GetProcAddress(hntdll,"RtlMultiByteToUnicodeN");
pRtlWow64EnableFsRedirection = (void *)GetProcAddress(hntdll,"RtlWow64EnableFsRedirection");
pRtlWow64EnableFsRedirectionEx = (void *)GetProcAddress(hntdll,"RtlWow64EnableFsRedirectionEx");
GetSystemDirectoryW( sysdir, MAX_PATH );
test_directory_sort( sysdir );
test_NtQueryDirectoryFile();
test_NtQueryDirectoryFile_case();
test_redirection();
File diff suppressed because it is too large Load Diff
+453 -297
View File
@@ -94,6 +94,7 @@ static NTSTATUS (WINAPI *pNtWriteFile)(HANDLE hFile, HANDLE hEvent,
static NTSTATUS (WINAPI *pNtCancelIoFile)(HANDLE hFile, PIO_STATUS_BLOCK io_status);
static NTSTATUS (WINAPI *pNtCancelIoFileEx)(HANDLE hFile, PIO_STATUS_BLOCK iosb, PIO_STATUS_BLOCK io_status);
static NTSTATUS (WINAPI *pNtClose)( PHANDLE );
static NTSTATUS (WINAPI *pNtFsControlFile) (HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, PVOID apc_context, PIO_STATUS_BLOCK io, ULONG code, PVOID in_buffer, ULONG in_size, PVOID out_buffer, ULONG out_size);
static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
static NTSTATUS (WINAPI *pNtOpenIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
@@ -106,6 +107,7 @@ static NTSTATUS (WINAPI *pNtQueryDirectoryFile)(HANDLE,HANDLE,PIO_APC_ROUTINE,PV
PVOID,ULONG,FILE_INFORMATION_CLASS,BOOLEAN,PUNICODE_STRING,BOOLEAN);
static NTSTATUS (WINAPI *pNtQueryVolumeInformationFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,FS_INFORMATION_CLASS);
static NTSTATUS (WINAPI *pNtQueryFullAttributesFile)(const OBJECT_ATTRIBUTES*, FILE_NETWORK_OPEN_INFORMATION*);
static NTSTATUS (WINAPI *pNtFlushBuffersFile)(HANDLE, IO_STATUS_BLOCK*);
static NTSTATUS (WINAPI *pNtQueryEaFile)(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,BOOLEAN,PVOID,ULONG,PULONG,BOOLEAN);
static inline BOOL is_signaled( HANDLE obj )
@@ -113,31 +115,8 @@ static inline BOOL is_signaled( HANDLE obj )
return WaitForSingleObject( obj, 0 ) == WAIT_OBJECT_0;
}
static const char* debugstr_longlong(ULONGLONG ll)
{
static char str[17];
if (sizeof(ll) > sizeof(unsigned long) && ll >> 32)
sprintf(str, "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll);
else
sprintf(str, "%lx", (unsigned long)ll);
return str;
}
#define PIPENAME "\\\\.\\pipe\\ntdll_tests_file.c"
#define TEST_BUF_LEN 3
static BOOL create_pipe( HANDLE *read, HANDLE *write, ULONG flags, ULONG size )
{
*read = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_INBOUND | flags, PIPE_TYPE_BYTE | PIPE_WAIT,
1, size, size, NMPWAIT_USE_DEFAULT_WAIT, NULL);
ok(*read != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
*write = CreateFileA(PIPENAME, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
ok(*write != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
return TRUE;
}
static HANDLE create_temp_file( ULONG flags )
{
char path[MAX_PATH], buffer[MAX_PATH];
@@ -198,18 +177,22 @@ static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
static void create_file_test(void)
{
static const WCHAR notepadW[] = {'n','o','t','e','p','a','d','.','e','x','e',0};
static const WCHAR systemrootW[] = {'\\','S','y','s','t','e','m','R','o','o','t',
'\\','f','a','i','l','i','n','g',0};
static const WCHAR systemrootExplorerW[] = {'\\','S','y','s','t','e','m','R','o','o','t',
'\\','e','x','p','l','o','r','e','r','.','e','x','e',0};
static const WCHAR questionmarkInvalidNameW[] = {'a','f','i','l','e','?',0};
static const WCHAR pipeInvalidNameW[] = {'a','|','b',0};
static const WCHAR pathInvalidNtW[] = {'\\','\\','?','\\',0};
static const WCHAR pathInvalidNt2W[] = {'\\','?','?','\\',0};
static const WCHAR pathInvalidDosW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
static const char testdata[] = "Hello World";
static const WCHAR sepW[] = {'\\',0};
FILE_NETWORK_OPEN_INFORMATION info;
NTSTATUS status;
HANDLE dir, file;
WCHAR path[MAX_PATH];
WCHAR path[MAX_PATH], temp[MAX_PATH];
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
UNICODE_STRING nameW;
@@ -389,6 +372,25 @@ static void create_file_test(void)
status = pNtQueryFullAttributesFile( &attr, &info );
ok( status == STATUS_OBJECT_NAME_INVALID,
"query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
GetWindowsDirectoryW( path, MAX_PATH );
path[2] = 0;
ok( QueryDosDeviceW( path, temp, MAX_PATH ),
"QueryDosDeviceW failed with error %u\n", GetLastError() );
lstrcatW( temp, sepW );
lstrcatW( temp, path+3 );
lstrcatW( temp, sepW );
lstrcatW( temp, notepadW );
pRtlInitUnicodeString( &nameW, temp );
status = pNtQueryFullAttributesFile( &attr, &info );
ok( status == STATUS_SUCCESS,
"query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
pRtlInitUnicodeString( &nameW, systemrootExplorerW );
status = pNtQueryFullAttributesFile( &attr, &info );
ok( status == STATUS_SUCCESS,
"query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
}
static void open_file_test(void)
@@ -660,268 +662,14 @@ static void delete_file_test(void)
static void read_file_test(void)
{
const char text[] = "foobar";
HANDLE handle, read, write;
HANDLE handle;
IO_STATUS_BLOCK iosb;
NTSTATUS status;
IO_STATUS_BLOCK iosb, iosb2;
DWORD written;
int apc_count = 0;
char buffer[128];
LARGE_INTEGER offset;
HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
BOOL ret;
buffer[0] = 1;
if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
/* try read with no data */
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
ok( is_signaled( read ), "read handle is not signaled\n" );
status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( read ), "read handle is signaled\n" );
ok( !is_signaled( event ), "event is signaled\n" );
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" );
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 );
ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
ok( !is_signaled( read ), "read handle is signaled\n" );
ok( is_signaled( event ), "event is not signaled\n" );
ok( !apc_count, "apc was called\n" );
apc_count = 0;
SleepEx( 1, FALSE ); /* non-alertable sleep */
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc not called\n" );
/* with no event, the pipe handle itself gets signaled */
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
ok( !is_signaled( read ), "read handle is signaled\n" );
status = pNtReadFile( read, 0, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( read ), "read handle is signaled\n" );
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" );
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 );
ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
ok( is_signaled( read ), "read handle is not signaled\n" );
ok( !apc_count, "apc was called\n" );
apc_count = 0;
SleepEx( 1, FALSE ); /* non-alertable sleep */
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc not called\n" );
/* now read with data ready */
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
ResetEvent( event );
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 );
ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
ok( is_signaled( event ), "event is not signaled\n" );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, FALSE ); /* non-alertable sleep */
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc not called\n" );
/* try read with no data */
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
ok( is_signaled( event ), "event is not signaled\n" ); /* check that read resets the event */
status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( event ), "event is signaled\n" );
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" );
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 not signaled\n" );
ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc was not called\n" );
/* read from disconnected pipe */
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
CloseHandle( write );
status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
ok( status == STATUS_PIPE_BROKEN, "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( read );
/* read from closed handle */
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
SetEvent( event );
status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
ok( status == STATUS_INVALID_HANDLE, "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 not signaled\n" ); /* not reset on invalid handle */
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( !apc_count, "apc was called\n" );
/* disconnect while async read is in progress */
if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( event ), "event is signaled\n" );
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" );
CloseHandle( write );
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
ok( U(iosb).Status == STATUS_PIPE_BROKEN, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
ok( is_signaled( event ), "event is not signaled\n" );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc was not called\n" );
CloseHandle( read );
if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
ret = DuplicateHandle(GetCurrentProcess(), read, GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS);
ok(ret, "Failed to duplicate handle: %d\n", GetLastError());
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( event ), "event is signaled\n" );
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" );
/* Cancel by other handle */
status = pNtCancelIoFile( read, &iosb2 );
ok(status == STATUS_SUCCESS, "failed to cancel by different handle: %x\n", status);
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
ok( is_signaled( event ), "event is not signaled\n" );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc was not called\n" );
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( event ), "event is signaled\n" );
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" );
/* Close queued handle */
CloseHandle( read );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
status = pNtCancelIoFile( read, &iosb2 );
ok(status == STATUS_INVALID_HANDLE, "cancelled by closed handle?\n");
status = pNtCancelIoFile( handle, &iosb2 );
ok(status == STATUS_SUCCESS, "failed to cancel: %x\n", status);
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
ok( is_signaled( event ), "event is not signaled\n" );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc was not called\n" );
CloseHandle( handle );
CloseHandle( write );
if (pNtCancelIoFileEx)
{
/* Basic Cancel Ex */
if (!create_pipe( &read, &write, FILE_FLAG_OVERLAPPED, 4096 )) return;
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( event ), "event is signaled\n" );
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" );
status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
ok( is_signaled( event ), "event is not signaled\n" );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc was not called\n" );
/* Duplicate iosb */
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( event ), "event is signaled\n" );
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" );
status = pNtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( event ), "event is signaled\n" );
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" );
status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
ok( is_signaled( event ), "event is not signaled\n" );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 2, "apc was not called\n" );
CloseHandle( read );
CloseHandle( write );
}
/* now try a real file */
if (!(handle = create_temp_file( FILE_FLAG_OVERLAPPED ))) return;
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
@@ -1297,7 +1045,7 @@ static void test_iocp_fileio(HANDLE h)
ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information );
/* wine sends wrong status here */
todo_wine ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
}
}
@@ -1315,6 +1063,7 @@ static void test_iocp_fileio(HANDLE h)
{
OVERLAPPED o = {0,};
BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
int apc_count = 0;
DWORD read;
long count;
@@ -1343,6 +1092,58 @@ static void test_iocp_fileio(HANDLE h)
}
count = get_pending_msgs(h);
ok( !count, "Unexpected msg count: %ld\n", count );
/* using APCs on handle with associated completion port is not allowed */
res = NtReadFile( hPipeSrv, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %x\n", res);
}
CloseHandle( hPipeSrv );
CloseHandle( hPipeClt );
/* test associating a completion port with a handle after an async using APC is queued */
hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL );
ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" );
if (hPipeSrv == INVALID_HANDLE_VALUE )
return;
hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL );
ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" );
if (hPipeClt != INVALID_HANDLE_VALUE)
{
BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN];
int apc_count = 0;
DWORD read;
long count;
memset( send_buf, 0, TEST_BUF_LEN );
memset( recv_buf, 0xde, TEST_BUF_LEN );
count = get_pending_msgs(h);
ok( !count, "Unexpected msg count: %ld\n", count );
res = NtReadFile( hPipeSrv, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
ok(res == STATUS_PENDING, "NtReadFile returned %x\n", res);
U(iosb).Status = 0xdeadbeef;
res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation );
ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res );
ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status );
count = get_pending_msgs(h);
ok( !count, "Unexpected msg count: %ld\n", count );
WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
ok(!apc_count, "apc_count = %u\n", apc_count);
count = get_pending_msgs(h);
ok( !count, "Unexpected msg count: %ld\n", count );
SleepEx(1, TRUE); /* alertable sleep */
ok(apc_count == 1, "apc was not called\n");
count = get_pending_msgs(h);
ok( !count, "Unexpected msg count: %ld\n", count );
/* using APCs on handle with associated completion port is not allowed */
res = NtReadFile( hPipeSrv, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL );
ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %x\n", res);
}
CloseHandle( hPipeSrv );
@@ -1371,10 +1172,10 @@ static void test_file_full_size_information(void)
/* Test for FileFsSizeInformation */
ok(fsi.TotalAllocationUnits.QuadPart > 0,
"[fsi] TotalAllocationUnits expected positive, got 0x%s\n",
debugstr_longlong(fsi.TotalAllocationUnits.QuadPart));
wine_dbgstr_longlong(fsi.TotalAllocationUnits.QuadPart));
ok(fsi.AvailableAllocationUnits.QuadPart > 0,
"[fsi] AvailableAllocationUnits expected positive, got 0x%s\n",
debugstr_longlong(fsi.AvailableAllocationUnits.QuadPart));
wine_dbgstr_longlong(fsi.AvailableAllocationUnits.QuadPart));
/* Assume file system is NTFS */
ok(fsi.BytesPerSector == 512, "[fsi] BytesPerSector expected 512, got %d\n",fsi.BytesPerSector);
@@ -1382,21 +1183,21 @@ static void test_file_full_size_information(void)
ok(ffsi.TotalAllocationUnits.QuadPart > 0,
"[ffsi] TotalAllocationUnits expected positive, got negative value 0x%s\n",
debugstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
wine_dbgstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
ok(ffsi.CallerAvailableAllocationUnits.QuadPart > 0,
"[ffsi] CallerAvailableAllocationUnits expected positive, got negative value 0x%s\n",
debugstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
wine_dbgstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
ok(ffsi.ActualAvailableAllocationUnits.QuadPart > 0,
"[ffsi] ActualAvailableAllocationUnits expected positive, got negative value 0x%s\n",
debugstr_longlong(ffsi.ActualAvailableAllocationUnits.QuadPart));
wine_dbgstr_longlong(ffsi.ActualAvailableAllocationUnits.QuadPart));
ok(ffsi.TotalAllocationUnits.QuadPart == fsi.TotalAllocationUnits.QuadPart,
"[ffsi] TotalAllocationUnits error fsi:0x%s, ffsi:0x%s\n",
debugstr_longlong(fsi.TotalAllocationUnits.QuadPart),
debugstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
wine_dbgstr_longlong(fsi.TotalAllocationUnits.QuadPart),
wine_dbgstr_longlong(ffsi.TotalAllocationUnits.QuadPart));
ok(ffsi.CallerAvailableAllocationUnits.QuadPart == fsi.AvailableAllocationUnits.QuadPart,
"[ffsi] CallerAvailableAllocationUnits error fsi:0x%s, ffsi: 0x%s\n",
debugstr_longlong(fsi.AvailableAllocationUnits.QuadPart),
debugstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
wine_dbgstr_longlong(fsi.AvailableAllocationUnits.QuadPart),
wine_dbgstr_longlong(ffsi.CallerAvailableAllocationUnits.QuadPart));
/* Assume file system is NTFS */
ok(ffsi.BytesPerSector == 512, "[ffsi] BytesPerSector expected 512, got %d\n",ffsi.BytesPerSector);
@@ -1592,7 +1393,7 @@ static void test_file_rename_information(void)
res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
ok( !lstrcmpW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
HeapFree( GetProcessHeap(), 0, fni );
@@ -1762,7 +1563,7 @@ static void test_file_rename_information(void)
res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
ok( !lstrcmpW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
HeapFree( GetProcessHeap(), 0, fni );
@@ -2168,7 +1969,7 @@ static void test_file_rename_information(void)
res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
ok( !lstrcmpW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
ok( !lstrcmpiW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
HeapFree( GetProcessHeap(), 0, fni );
@@ -2181,6 +1982,7 @@ static void test_file_rename_information(void)
static void test_file_link_information(void)
{
static const WCHAR pipeW[] = {'\\','\\','.','\\','p','i','p','e','\\','w','i','n','e','_','t','e','s','t',0};
static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
static const WCHAR fooW[] = {'f','o','o',0};
WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
@@ -2224,7 +2026,7 @@ static void test_file_link_information(void)
res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
ok( !lstrcmpW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
HeapFree( GetProcessHeap(), 0, fni );
@@ -2394,7 +2196,7 @@ static void test_file_link_information(void)
res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
ok( !lstrcmpW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
HeapFree( GetProcessHeap(), 0, fni );
@@ -2797,12 +2599,36 @@ static void test_file_link_information(void)
res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
ok( !lstrcmpW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
ok( !lstrcmpiW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
HeapFree( GetProcessHeap(), 0, fni );
CloseHandle( handle );
CloseHandle( handle2 );
handle = CreateEventA( NULL, FALSE, FALSE, "wine_test_event" );
ok( !!handle, "Failed to create event: %u\n", GetLastError());
fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
ok( res == STATUS_OBJECT_TYPE_MISMATCH, "res expected STATUS_OBJECT_TYPE_MISMATCH, got %x\n", res );
HeapFree( GetProcessHeap(), 0, fni );
CloseHandle( handle );
handle = CreateNamedPipeW( pipeW, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE|PIPE_READMODE_BYTE, 10, 512, 512, 0, NULL);
ok( handle != INVALID_HANDLE_VALUE, "Failed to create named pipe: %u\n", GetLastError());
fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
ok( !lstrcmpiW(fni->FileName, pipeW + 8), "FileName expected %s, got %s\n",
wine_dbgstr_w(pipeW + 8), wine_dbgstr_w(fni->FileName) );
HeapFree( GetProcessHeap(), 0, fni );
CloseHandle( handle );
HeapFree( GetProcessHeap(), 0, fli );
delete_object( oldpath );
delete_object( newpath );
@@ -3349,6 +3175,213 @@ static void test_file_all_name_information(void)
HeapFree( GetProcessHeap(), 0, file_name );
}
static void test_file_completion_information(void)
{
static const char buf[] = "testdata";
FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info;
OVERLAPPED ov, *pov;
IO_STATUS_BLOCK io;
NTSTATUS status;
DWORD num_bytes;
HANDLE port, h;
ULONG_PTR key;
BOOL ret;
int i;
if (!(h = create_temp_file(0))) return;
status = pNtSetInformationFile(h, &io, &info, sizeof(info) - 1, FileIoCompletionNotificationInformation);
ok(status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_INVALID_INFO_CLASS /* XP */,
"expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
if (status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED)
{
win_skip("FileIoCompletionNotificationInformation class not supported\n");
CloseHandle(h);
return;
}
info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %08x\n", status);
CloseHandle(h);
if (!(h = create_temp_file(FILE_FLAG_OVERLAPPED))) return;
info.Flags = FILE_SKIP_SET_EVENT_ON_HANDLE;
status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
info.Flags = FILE_SKIP_SET_USER_EVENT_ON_FAST_IO;
status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
CloseHandle(h);
if (!(h = create_temp_file(FILE_FLAG_OVERLAPPED))) return;
info.Flags = ~0U;
status = pNtQueryInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
ok(!(info.Flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS), "got %08x\n", info.Flags);
memset(&ov, 0, sizeof(ov));
ov.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
port = CreateIoCompletionPort(h, NULL, 0xdeadbeef, 0);
ok(port != NULL, "CreateIoCompletionPort failed, error %u\n", GetLastError());
for (i = 0; i < 10; i++)
{
SetLastError(0xdeadbeef);
ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
if (ret || GetLastError() != ERROR_IO_PENDING) break;
ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
ok(ret, "GetOverlappedResult failed, error %u\n", GetLastError());
ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
ok(ret, "GetQueuedCompletionStatus failed, error %u\n", GetLastError());
ret = FALSE;
}
if (ret)
{
ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
key = 0;
pov = NULL;
ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
ok(ret, "GetQueuedCompletionStatus failed, error %u\n", GetLastError());
ok(key == 0xdeadbeef, "expected 0xdeadbeef, got %lx\n", key);
ok(pov == &ov, "expected %p, got %p\n", &ov, pov);
}
else
win_skip("WriteFile never returned TRUE\n");
info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
info.Flags = 0;
status = pNtQueryInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
ok((info.Flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS) != 0, "got %08x\n", info.Flags);
for (i = 0; i < 10; i++)
{
SetLastError(0xdeadbeef);
ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
if (ret || GetLastError() != ERROR_IO_PENDING) break;
ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
ok(ret, "GetOverlappedResult failed, error %u\n", GetLastError());
ret = FALSE;
}
if (ret)
{
ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
pov = (void *)0xdeadbeef;
ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 500);
ok(!ret, "GetQueuedCompletionStatus succeeded\n");
ok(pov == NULL, "expected NULL, got %p\n", pov);
}
else
win_skip("WriteFile never returned TRUE\n");
info.Flags = 0;
status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
info.Flags = 0;
status = pNtQueryInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
ok((info.Flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS) != 0, "got %08x\n", info.Flags);
for (i = 0; i < 10; i++)
{
SetLastError(0xdeadbeef);
ret = WriteFile(h, buf, sizeof(buf), &num_bytes, &ov);
if (ret || GetLastError() != ERROR_IO_PENDING) break;
ret = GetOverlappedResult(h, &ov, &num_bytes, TRUE);
ok(ret, "GetOverlappedResult failed, error %u\n", GetLastError());
ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
ok(ret, "GetQueuedCompletionStatus failed, error %u\n", GetLastError());
ret = FALSE;
}
if (ret)
{
ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
pov = (void *)0xdeadbeef;
ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
ok(!ret, "GetQueuedCompletionStatus succeeded\n");
ok(pov == NULL, "expected NULL, got %p\n", pov);
}
else
win_skip("WriteFile never returned TRUE\n");
CloseHandle(ov.hEvent);
CloseHandle(port);
CloseHandle(h);
}
static void test_file_id_information(void)
{
BY_HANDLE_FILE_INFORMATION info;
FILE_ID_INFORMATION fid;
IO_STATUS_BLOCK io;
NTSTATUS status;
DWORD *dwords;
HANDLE h;
BOOL ret;
if (!(h = create_temp_file(0))) return;
memset( &fid, 0x11, sizeof(fid) );
status = pNtQueryInformationFile( h, &io, &fid, sizeof(fid), FileIdInformation );
if (status == STATUS_NOT_IMPLEMENTED || status == STATUS_INVALID_INFO_CLASS)
{
win_skip( "FileIdInformation not supported\n" );
CloseHandle( h );
return;
}
memset( &info, 0x22, sizeof(info) );
ret = GetFileInformationByHandle( h, &info );
ok( ret, "GetFileInformationByHandle failed\n" );
dwords = (DWORD *)&fid.VolumeSerialNumber;
ok( dwords[0] == info.dwVolumeSerialNumber, "expected %08x, got %08x\n",
info.dwVolumeSerialNumber, dwords[0] );
ok( dwords[1] != 0x11111111, "expected != 0x11111111\n" );
dwords = (DWORD *)&fid.FileId;
ok( dwords[0] == info.nFileIndexLow, "expected %08x, got %08x\n", info.nFileIndexLow, dwords[0] );
ok( dwords[1] == info.nFileIndexHigh, "expected %08x, got %08x\n", info.nFileIndexHigh, dwords[1] );
ok( dwords[2] == 0, "expected 0, got %08x\n", dwords[2] );
ok( dwords[3] == 0, "expected 0, got %08x\n", dwords[3] );
CloseHandle( h );
}
static void test_file_access_information(void)
{
FILE_ACCESS_INFORMATION info;
IO_STATUS_BLOCK io;
NTSTATUS status;
HANDLE h;
if (!(h = create_temp_file(0))) return;
status = pNtQueryInformationFile( h, &io, &info, sizeof(info) - 1, FileAccessInformation );
ok( status == STATUS_INFO_LENGTH_MISMATCH, "expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status );
status = pNtQueryInformationFile( (HANDLE)0xdeadbeef, &io, &info, sizeof(info), FileAccessInformation );
ok( status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08x\n", status );
memset(&info, 0x11, sizeof(info));
status = pNtQueryInformationFile( h, &io, &info, sizeof(info), FileAccessInformation );
ok( status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status );
ok( info.AccessFlags == 0x13019f, "got %08x\n", info.AccessFlags );
CloseHandle( h );
}
static void test_query_volume_information_file(void)
{
NTSTATUS status;
@@ -3616,13 +3649,15 @@ static void test_read_write(void)
{
static const char contents[14] = "1234567890abcd";
char buf[256];
HANDLE hfile;
HANDLE hfile, event;
OVERLAPPED ovl;
IO_STATUS_BLOCK iob;
DWORD ret, bytes, status, off;
LARGE_INTEGER offset;
LONG i;
event = CreateEventA( NULL, TRUE, FALSE, NULL );
U(iob).Status = -1;
iob.Information = -1;
offset.QuadPart = 0;
@@ -3631,6 +3666,22 @@ static void test_read_write(void)
ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
U(iob).Status = -1;
iob.Information = -1;
offset.QuadPart = 0;
status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, NULL, sizeof(buf), &offset, NULL);
ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
U(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(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
U(iob).Status = -1;
iob.Information = -1;
offset.QuadPart = 0;
@@ -3649,6 +3700,15 @@ static void test_read_write(void)
ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
U(iob).Status = -1;
iob.Information = -1;
SetEvent(event);
status = pNtWriteFile(hfile, event, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#x\n", status);
ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
ok(!is_signaled(event), "event is not signaled\n");
U(iob).Status = -1;
iob.Information = -1;
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
@@ -3656,6 +3716,24 @@ static void test_read_write(void)
ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
U(iob).Status = -1;
iob.Information = -1;
SetEvent(event);
status = pNtReadFile(hfile, event, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
ok(is_signaled(event), "event is not signaled\n");
U(iob).Status = -1;
iob.Information = -1;
SetEvent(event);
status = pNtReadFile(hfile, event, NULL, NULL, &iob, (void*)0xdeadbeef, sizeof(contents), NULL, NULL);
ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
ok(is_signaled(event), "event is not signaled\n");
U(iob).Status = -1;
iob.Information = -1;
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, 7, NULL, NULL);
@@ -4321,9 +4399,80 @@ static void test_read_write(void)
off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
ok(off == 0, "expected 0, got %u\n", off);
CloseHandle(event);
CloseHandle(hfile);
}
static void test_ioctl(void)
{
HANDLE event = CreateEventA(NULL, TRUE, FALSE, NULL);
IO_STATUS_BLOCK iosb;
HANDLE file;
NTSTATUS status;
file = create_temp_file(FILE_FLAG_OVERLAPPED);
ok(file != INVALID_HANDLE_VALUE, "could not create temp file\n");
SetEvent(event);
status = pNtFsControlFile(file, event, NULL, NULL, &iosb, 0xdeadbeef, 0, 0, 0, 0);
todo_wine
ok(status == STATUS_INVALID_DEVICE_REQUEST, "NtFsControlFile returned %x\n", status);
ok(!is_signaled(event), "event is signaled\n");
status = pNtFsControlFile(file, (HANDLE)0xdeadbeef, NULL, NULL, &iosb, 0xdeadbeef, 0, 0, 0, 0);
ok(status == STATUS_INVALID_HANDLE, "NtFsControlFile returned %x\n", status);
CloseHandle(event);
CloseHandle(file);
}
static void test_flush_buffers_file(void)
{
char path[MAX_PATH], buffer[MAX_PATH];
HANDLE hfile, hfileread;
NTSTATUS status;
IO_STATUS_BLOCK io_status_block;
GetTempPathA(MAX_PATH, path);
GetTempFileNameA(path, "foo", 0, buffer);
hfile = CreateFileA(buffer, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, 0);
ok(hfile != INVALID_HANDLE_VALUE, "failed to create temp file.\n" );
hfileread = CreateFileA(buffer, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
ok(hfileread != INVALID_HANDLE_VALUE, "could not open temp file, error %d.\n", GetLastError());
status = pNtFlushBuffersFile(hfile, NULL);
todo_wine
ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
status = pNtFlushBuffersFile(hfile, (IO_STATUS_BLOCK *)0xdeadbeaf);
todo_wine
ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
status = pNtFlushBuffersFile(hfile, &io_status_block);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x.\n", status);
status = pNtFlushBuffersFile(hfileread, &io_status_block);
ok(status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %#x.\n", status);
status = pNtFlushBuffersFile(NULL, &io_status_block);
ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %#x.\n", status);
CloseHandle(hfileread);
CloseHandle(hfile);
hfile = CreateFileA(buffer, FILE_APPEND_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
ok(hfile != INVALID_HANDLE_VALUE, "could not open temp file, error %d.\n", GetLastError());
status = pNtFlushBuffersFile(hfile, &io_status_block);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x.\n", status);
CloseHandle(hfile);
DeleteFileA(buffer);
}
static void test_query_ea(void)
{
#define EA_BUFFER_SIZE 4097
@@ -4601,6 +4750,7 @@ START_TEST(file)
pNtCancelIoFile = (void *)GetProcAddress(hntdll, "NtCancelIoFile");
pNtCancelIoFileEx = (void *)GetProcAddress(hntdll, "NtCancelIoFileEx");
pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
pNtFsControlFile = (void *)GetProcAddress(hntdll, "NtFsControlFile");
pNtCreateIoCompletion = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
pNtOpenIoCompletion = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
pNtQueryIoCompletion = (void *)GetProcAddress(hntdll, "NtQueryIoCompletion");
@@ -4611,6 +4761,7 @@ START_TEST(file)
pNtQueryDirectoryFile = (void *)GetProcAddress(hntdll, "NtQueryDirectoryFile");
pNtQueryVolumeInformationFile = (void *)GetProcAddress(hntdll, "NtQueryVolumeInformationFile");
pNtQueryFullAttributesFile = (void *)GetProcAddress(hntdll, "NtQueryFullAttributesFile");
pNtFlushBuffersFile = (void *)GetProcAddress(hntdll, "NtFlushBuffersFile");
pNtQueryEaFile = (void *)GetProcAddress(hntdll, "NtQueryEaFile");
test_read_write();
@@ -4632,8 +4783,13 @@ START_TEST(file)
test_file_rename_information();
test_file_link_information();
test_file_disposition_information();
test_file_completion_information();
test_file_id_information();
test_file_access_information();
test_query_volume_information_file();
test_query_attribute_information_file();
test_ioctl();
test_flush_buffers_file();
test_query_ea();
test_junction_points();
}
+557 -72
View File
@@ -22,7 +22,9 @@
#include <winnls.h>
#include <stdio.h>
static NTSTATUS (WINAPI * pRtlDowncaseUnicodeString)(UNICODE_STRING *, const UNICODE_STRING *, BOOLEAN);
static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
static NTSTATUS (WINAPI * pNtQuerySystemInformationEx)(SYSTEM_INFORMATION_CLASS, void*, ULONG, void*, ULONG, ULONG*);
static NTSTATUS (WINAPI * pNtPowerInformation)(POWER_INFORMATION_LEVEL, PVOID, ULONG, PVOID, ULONG);
static NTSTATUS (WINAPI * pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
static NTSTATUS (WINAPI * pNtQueryInformationThread)(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG);
@@ -36,6 +38,7 @@ static NTSTATUS (WINAPI * pNtUnmapViewOfSection)(HANDLE,PVOID);
static NTSTATUS (WINAPI * pNtClose)(HANDLE);
static ULONG (WINAPI * pNtGetCurrentProcessorNumber)(void);
static BOOL (WINAPI * pIsWow64Process)(HANDLE, PBOOL);
static BOOL (WINAPI * pGetLogicalProcessorInformationEx)(LOGICAL_PROCESSOR_RELATIONSHIP,SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*,DWORD*);
static BOOL is_wow64;
@@ -56,12 +59,15 @@ static BOOL InitFunctionPtrs(void)
{
/* All needed functions are NT based, so using GetModuleHandle is a good check */
HMODULE hntdll = GetModuleHandleA("ntdll");
HMODULE hkernel32 = GetModuleHandleA("kernel32");
if (!hntdll)
{
win_skip("Not running on NT\n");
return FALSE;
}
NTDLL_GET_PROC(RtlDowncaseUnicodeString);
NTDLL_GET_PROC(NtQuerySystemInformation);
NTDLL_GET_PROC(NtPowerInformation);
NTDLL_GET_PROC(NtQueryInformationProcess);
@@ -78,8 +84,16 @@ static BOOL InitFunctionPtrs(void)
/* not present before XP */
pNtGetCurrentProcessorNumber = (void *) GetProcAddress(hntdll, "NtGetCurrentProcessorNumber");
pIsWow64Process = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process");
pIsWow64Process = (void *)GetProcAddress(hkernel32, "IsWow64Process");
if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
/* starting with Win7 */
pNtQuerySystemInformationEx = (void *) GetProcAddress(hntdll, "NtQuerySystemInformationEx");
if (!pNtQuerySystemInformationEx)
win_skip("NtQuerySystemInformationEx() is not supported, some tests will be skipped.\n");
pGetLogicalProcessorInformationEx = (void *) GetProcAddress(hkernel32, "GetLogicalProcessorInformationEx");
return TRUE;
}
@@ -288,7 +302,7 @@ static void test_query_process(void)
/* test ReturnLength */
ReturnLength = 0;
status = pNtQuerySystemInformation(SystemProcessInformation, NULL, 0, &ReturnLength);
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_LENGTH_MISMATCH got %08x\n", status);
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH got %08x\n", status);
ok( ReturnLength > 0 || broken(ReturnLength == 0) /* NT4, Win2K */,
"Expected a ReturnLength to show the needed length\n");
@@ -474,13 +488,15 @@ static void test_query_module(void)
static void test_query_handle(void)
{
NTSTATUS status;
ULONG ReturnLength;
ULONG ExpectedLength, ReturnLength;
ULONG SystemInformationLength = sizeof(SYSTEM_HANDLE_INFORMATION);
SYSTEM_HANDLE_INFORMATION* shi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
HANDLE event_handle;
HANDLE EventHandle;
BOOL found;
INT i;
event_handle = CreateEventA(NULL, FALSE, FALSE, NULL);
ok( event_handle != NULL, "CreateEventA failed %u\n", GetLastError() );
EventHandle = CreateEventA(NULL, FALSE, FALSE, NULL);
ok( EventHandle != NULL, "CreateEventA failed %u\n", GetLastError() );
/* Request the needed length : a SystemInformationLength greater than one struct sets ReturnLength */
ReturnLength = 0xdeadbeef;
@@ -490,34 +506,116 @@ static void test_query_handle(void)
SystemInformationLength = ReturnLength;
shi = HeapReAlloc(GetProcessHeap(), 0, shi , SystemInformationLength);
memset(shi, 0x55, SystemInformationLength);
ReturnLength = 0xdeadbeef;
status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
if (status != STATUS_INFO_LENGTH_MISMATCH) /* vista */
while (status == STATUS_INFO_LENGTH_MISMATCH) /* Vista / 2008 */
{
ULONG ExpectedLength = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION, Handle[shi->Count]);
unsigned int i;
BOOL found = FALSE;
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status );
ok( ReturnLength == ExpectedLength, "Expected length %u, got %u\n", ExpectedLength, ReturnLength );
ok( shi->Count > 1, "Expected more than 1 handles, got %u\n", shi->Count );
for (i = 0; i < shi->Count; i++)
{
if (shi->Handle[i].OwnerPid == GetCurrentProcessId() &&
(HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue == event_handle)
{
found = TRUE;
break;
}
}
ok( found, "Expected to find event handle in handle list\n" );
SystemInformationLength *= 2;
shi = HeapReAlloc(GetProcessHeap(), 0, shi, SystemInformationLength);
memset(shi, 0x55, SystemInformationLength);
status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
}
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status );
ExpectedLength = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION, Handle[shi->Count]);
ok( ReturnLength == ExpectedLength || broken(ReturnLength == ExpectedLength - sizeof(DWORD)), /* Vista / 2008 */
"Expected length %u, got %u\n", ExpectedLength, ReturnLength );
ok( shi->Count > 1, "Expected more than 1 handle, got %u\n", shi->Count );
ok( shi->Handle[1].HandleValue != 0x5555 || broken( shi->Handle[1].HandleValue == 0x5555 ), /* Vista / 2008 */
"Uninitialized second handle\n" );
if (shi->Handle[1].HandleValue == 0x5555)
{
win_skip("Skipping broken SYSTEM_HANDLE_INFORMATION\n");
CloseHandle(EventHandle);
goto done;
}
for (i = 0, found = FALSE; i < shi->Count && !found; i++)
found = (shi->Handle[i].OwnerPid == GetCurrentProcessId()) &&
((HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue == EventHandle);
ok( found, "Expected to find event handle %p (pid %x) in handle list\n", EventHandle, GetCurrentProcessId() );
if (!found)
for (i = 0; i < shi->Count; i++)
trace( "%d: handle %x pid %x\n", i, shi->Handle[i].HandleValue, shi->Handle[i].OwnerPid );
CloseHandle(EventHandle);
ReturnLength = 0xdeadbeef;
status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
while (status == STATUS_INFO_LENGTH_MISMATCH) /* Vista / 2008 */
{
SystemInformationLength *= 2;
shi = HeapReAlloc(GetProcessHeap(), 0, shi, SystemInformationLength);
status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
}
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status );
for (i = 0, found = FALSE; i < shi->Count && !found; i++)
found = (shi->Handle[i].OwnerPid == GetCurrentProcessId()) &&
((HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue == EventHandle);
ok( !found, "Unexpectedly found event handle in handle list\n" );
status = pNtQuerySystemInformation(SystemHandleInformation, NULL, SystemInformationLength, &ReturnLength);
ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status );
CloseHandle(event_handle);
done:
HeapFree( GetProcessHeap(), 0, shi);
}
static void test_query_handle_ex(void)
{
NTSTATUS status;
ULONG ExpectedLength, ReturnLength;
ULONG SystemInformationLength = sizeof(SYSTEM_HANDLE_INFORMATION_EX);
SYSTEM_HANDLE_INFORMATION_EX* shi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
HANDLE EventHandle;
BOOL found;
INT i;
EventHandle = CreateEventA(NULL, FALSE, FALSE, NULL);
ok( EventHandle != NULL, "CreateEventA failed %u\n", GetLastError() );
ReturnLength = 0xdeadbeef;
status = pNtQuerySystemInformation(SystemExtendedHandleInformation, shi, SystemInformationLength, &ReturnLength);
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
ok( ReturnLength != 0xdeadbeef, "Expected valid ReturnLength\n" );
SystemInformationLength = ReturnLength;
shi = HeapReAlloc(GetProcessHeap(), 0, shi , SystemInformationLength);
memset(shi, 0x55, SystemInformationLength);
ReturnLength = 0xdeadbeef;
status = pNtQuerySystemInformation(SystemExtendedHandleInformation, shi, SystemInformationLength, &ReturnLength);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status );
ExpectedLength = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION_EX, Handle[shi->Count]);
ok( ReturnLength == ExpectedLength, "Expected length %u, got %u\n", ExpectedLength, ReturnLength );
ok( shi->Count > 1, "Expected more than 1 handle, got %u\n", (DWORD)shi->Count );
for (i = 0, found = FALSE; i < shi->Count && !found; i++)
found = (shi->Handle[i].UniqueProcessId == GetCurrentProcessId()) &&
((HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue == EventHandle);
ok( found, "Expected to find event handle %p (pid %x) in handle list\n", EventHandle, GetCurrentProcessId() );
if (!found)
{
for (i = 0; i < shi->Count; i++)
trace( "%d: handle %x pid %x\n", i, (DWORD)shi->Handle[i].HandleValue, (DWORD)shi->Handle[i].UniqueProcessId );
}
CloseHandle(EventHandle);
ReturnLength = 0xdeadbeef;
status = pNtQuerySystemInformation(SystemExtendedHandleInformation, shi, SystemInformationLength, &ReturnLength);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status );
for (i = 0, found = FALSE; i < shi->Count && !found; i++)
found = (shi->Handle[i].UniqueProcessId == GetCurrentProcessId()) &&
((HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue == EventHandle);
ok( !found, "Unexpectedly found event handle in handle list\n" );
status = pNtQuerySystemInformation(SystemExtendedHandleInformation, NULL, SystemInformationLength, &ReturnLength);
ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status );
HeapFree( GetProcessHeap(), 0, shi);
}
@@ -684,6 +782,110 @@ static void test_query_logicalproc(void)
HeapFree(GetProcessHeap(), 0, slpi);
}
static void test_query_logicalprocex(void)
{
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infoex, *infoex2;
DWORD relationship, len2, len;
NTSTATUS status;
BOOL ret;
if (!pNtQuerySystemInformationEx)
return;
len = 0;
relationship = RelationProcessorCore;
status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), NULL, 0, &len);
ok(status == STATUS_INFO_LENGTH_MISMATCH, "got 0x%08x\n", status);
ok(len > 0, "got %u\n", len);
len = 0;
relationship = RelationAll;
status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), NULL, 0, &len);
ok(status == STATUS_INFO_LENGTH_MISMATCH, "got 0x%08x\n", status);
ok(len > 0, "got %u\n", len);
len2 = 0;
ret = pGetLogicalProcessorInformationEx(RelationAll, NULL, &len2);
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d, error %d\n", ret, GetLastError());
ok(len == len2, "got %u, expected %u\n", len2, len);
if (len && len == len2) {
int j, i;
infoex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
infoex2 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), infoex, len, &len);
ok(status == STATUS_SUCCESS, "got 0x%08x\n", status);
ret = pGetLogicalProcessorInformationEx(RelationAll, infoex2, &len2);
ok(ret, "got %d, error %d\n", ret, GetLastError());
ok(!memcmp(infoex, infoex2, len), "returned info data mismatch\n");
for(i = 0; status == STATUS_SUCCESS && i < len; ){
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *ex = (void*)(((char *)infoex) + i);
ok(ex->Relationship >= RelationProcessorCore && ex->Relationship <= RelationGroup,
"Got invalid relationship value: 0x%x\n", ex->Relationship);
if (!ex->Size)
{
ok(0, "got infoex[%u].Size=0\n", i);
break;
}
trace("infoex[%u].Size: %u\n", i, ex->Size);
switch(ex->Relationship){
case RelationProcessorCore:
case RelationProcessorPackage:
trace("infoex[%u].Relationship: 0x%x (Core == 0x0 or Package == 0x3)\n", i, ex->Relationship);
trace("infoex[%u].Processor.Flags: 0x%x\n", i, ex->Processor.Flags);
#ifndef __REACTOS__
trace("infoex[%u].Processor.EfficiencyClass: 0x%x\n", i, ex->Processor.EfficiencyClass);
#endif
trace("infoex[%u].Processor.GroupCount: 0x%x\n", i, ex->Processor.GroupCount);
for(j = 0; j < ex->Processor.GroupCount; ++j){
trace("infoex[%u].Processor.GroupMask[%u].Mask: 0x%lx\n", i, j, ex->Processor.GroupMask[j].Mask);
trace("infoex[%u].Processor.GroupMask[%u].Group: 0x%x\n", i, j, ex->Processor.GroupMask[j].Group);
}
break;
case RelationNumaNode:
trace("infoex[%u].Relationship: 0x%x (NumaNode)\n", i, ex->Relationship);
trace("infoex[%u].NumaNode.NodeNumber: 0x%x\n", i, ex->NumaNode.NodeNumber);
trace("infoex[%u].NumaNode.GroupMask.Mask: 0x%lx\n", i, ex->NumaNode.GroupMask.Mask);
trace("infoex[%u].NumaNode.GroupMask.Group: 0x%x\n", i, ex->NumaNode.GroupMask.Group);
break;
case RelationCache:
trace("infoex[%u].Relationship: 0x%x (Cache)\n", i, ex->Relationship);
trace("infoex[%u].Cache.Level: 0x%x\n", i, ex->Cache.Level);
trace("infoex[%u].Cache.Associativity: 0x%x\n", i, ex->Cache.Associativity);
trace("infoex[%u].Cache.LineSize: 0x%x\n", i, ex->Cache.LineSize);
trace("infoex[%u].Cache.CacheSize: 0x%x\n", i, ex->Cache.CacheSize);
trace("infoex[%u].Cache.Type: 0x%x\n", i, ex->Cache.Type);
trace("infoex[%u].Cache.GroupMask.Mask: 0x%lx\n", i, ex->Cache.GroupMask.Mask);
trace("infoex[%u].Cache.GroupMask.Group: 0x%x\n", i, ex->Cache.GroupMask.Group);
break;
case RelationGroup:
trace("infoex[%u].Relationship: 0x%x (Group)\n", i, ex->Relationship);
trace("infoex[%u].Group.MaximumGroupCount: 0x%x\n", i, ex->Group.MaximumGroupCount);
trace("infoex[%u].Group.ActiveGroupCount: 0x%x\n", i, ex->Group.ActiveGroupCount);
for(j = 0; j < ex->Group.ActiveGroupCount; ++j){
trace("infoex[%u].Group.GroupInfo[%u].MaximumProcessorCount: 0x%x\n", i, j, ex->Group.GroupInfo[j].MaximumProcessorCount);
trace("infoex[%u].Group.GroupInfo[%u].ActiveProcessorCount: 0x%x\n", i, j, ex->Group.GroupInfo[j].ActiveProcessorCount);
trace("infoex[%u].Group.GroupInfo[%u].ActiveProcessorMask: 0x%lx\n", i, j, ex->Group.GroupInfo[j].ActiveProcessorMask);
}
break;
default:
break;
}
i += ex->Size;
}
HeapFree(GetProcessHeap(), 0, infoex);
HeapFree(GetProcessHeap(), 0, infoex2);
}
}
static void test_query_processor_power_info(void)
{
NTSTATUS status;
@@ -904,12 +1106,32 @@ static void test_query_process_basic(void)
ok( pbi.UniqueProcessId > 0, "Expected a ProcessID > 0, got 0\n");
}
static void dump_vm_counters(const char *header, const VM_COUNTERS *pvi)
{
trace("%s:\n", header);
trace("PeakVirtualSize : %lu\n", pvi->PeakVirtualSize);
trace("VirtualSize : %lu\n", pvi->VirtualSize);
trace("PageFaultCount : %u\n", pvi->PageFaultCount);
trace("PeakWorkingSetSize : %lu\n", pvi->PeakWorkingSetSize);
trace("WorkingSetSize : %lu\n", pvi->WorkingSetSize);
trace("QuotaPeakPagedPoolUsage : %lu\n", pvi->QuotaPeakPagedPoolUsage);
trace("QuotaPagedPoolUsage : %lu\n", pvi->QuotaPagedPoolUsage);
trace("QuotaPeakNonPagePoolUsage : %lu\n", pvi->QuotaPeakNonPagedPoolUsage);
trace("QuotaNonPagePoolUsage : %lu\n", pvi->QuotaNonPagedPoolUsage);
trace("PagefileUsage : %lu\n", pvi->PagefileUsage);
trace("PeakPagefileUsage : %lu\n", pvi->PeakPagefileUsage);
}
static void test_query_process_vm(void)
{
NTSTATUS status;
ULONG ReturnLength;
VM_COUNTERS pvi;
ULONG old_size = FIELD_OFFSET(VM_COUNTERS,PrivatePageCount);
HANDLE process;
SIZE_T prev_size;
const SIZE_T alloc_size = 16 * 1024 * 1024;
void *ptr;
status = pNtQueryInformationProcess(NULL, ProcessVmCounters, NULL, sizeof(pvi), NULL);
ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
@@ -935,11 +1157,72 @@ static void test_query_process_vm(void)
ok( ReturnLength == old_size || ReturnLength == sizeof(pvi), "Inconsistent length %d\n", ReturnLength);
/* Check if we have some return values */
trace("WorkingSetSize : %ld\n", pvi.WorkingSetSize);
todo_wine
{
ok( pvi.WorkingSetSize > 0, "Expected a WorkingSetSize > 0\n");
}
dump_vm_counters("VM counters for GetCurrentProcess", &pvi);
ok( pvi.WorkingSetSize > 0, "Expected a WorkingSetSize > 0\n");
ok( pvi.PagefileUsage > 0, "Expected a PagefileUsage > 0\n");
process = OpenProcess(PROCESS_VM_READ, FALSE, GetCurrentProcessId());
status = pNtQueryInformationProcess(process, ProcessVmCounters, &pvi, sizeof(pvi), NULL);
ok( status == STATUS_ACCESS_DENIED, "Expected STATUS_ACCESS_DENIED, got %08x\n", status);
CloseHandle(process);
process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, GetCurrentProcessId());
status = pNtQueryInformationProcess(process, ProcessVmCounters, &pvi, sizeof(pvi), NULL);
ok( status == STATUS_SUCCESS || broken(!process) /* XP */, "Expected STATUS_SUCCESS, got %08x\n", status);
CloseHandle(process);
memset(&pvi, 0, sizeof(pvi));
process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
status = pNtQueryInformationProcess(process, ProcessVmCounters, &pvi, sizeof(pvi), NULL);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
/* Check if we have some return values */
dump_vm_counters("VM counters for GetCurrentProcessId", &pvi);
ok( pvi.WorkingSetSize > 0, "Expected a WorkingSetSize > 0\n");
ok( pvi.PagefileUsage > 0, "Expected a PagefileUsage > 0\n");
CloseHandle(process);
/* Check if we have real counters */
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(pvi), NULL);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
prev_size = pvi.VirtualSize;
if (winetest_debug > 1)
dump_vm_counters("VM counters before VirtualAlloc", &pvi);
ptr = VirtualAlloc(NULL, alloc_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
ok( ptr != NULL, "VirtualAlloc failed, err %u\n", GetLastError());
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(pvi), NULL);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
if (winetest_debug > 1)
dump_vm_counters("VM counters after VirtualAlloc", &pvi);
todo_wine ok( pvi.VirtualSize >= prev_size + alloc_size,
"Expected to be greater than %lu, got %lu\n", prev_size + alloc_size, pvi.VirtualSize);
VirtualFree( ptr, 0, MEM_RELEASE);
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(pvi), NULL);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
prev_size = pvi.VirtualSize;
if (winetest_debug > 1)
dump_vm_counters("VM counters before VirtualAlloc", &pvi);
ptr = VirtualAlloc(NULL, alloc_size, MEM_RESERVE, PAGE_READWRITE);
ok( ptr != NULL, "VirtualAlloc failed, err %u\n", GetLastError());
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(pvi), NULL);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
if (winetest_debug > 1)
dump_vm_counters("VM counters after VirtualAlloc(MEM_RESERVE)", &pvi);
todo_wine ok( pvi.VirtualSize >= prev_size + alloc_size,
"Expected to be greater than %lu, got %lu\n", prev_size + alloc_size, pvi.VirtualSize);
prev_size = pvi.VirtualSize;
ptr = VirtualAlloc(ptr, alloc_size, MEM_COMMIT, PAGE_READWRITE);
ok( ptr != NULL, "VirtualAlloc failed, err %u\n", GetLastError());
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(pvi), NULL);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
if (winetest_debug > 1)
dump_vm_counters("VM counters after VirtualAlloc(MEM_COMMIT)", &pvi);
ok( pvi.VirtualSize == prev_size,
"Expected to equal to %lu, got %lu\n", prev_size, pvi.VirtualSize);
VirtualFree( ptr, 0, MEM_RELEASE);
}
static void test_query_process_io(void)
@@ -975,7 +1258,7 @@ static void test_query_process_io(void)
ok( sizeof(pii) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
/* Check if we have some return values */
trace("OtherOperationCount : 0x%x%08x\n", (DWORD)(pii.OtherOperationCount >> 32), (DWORD)pii.OtherOperationCount);
trace("OtherOperationCount : 0x%s\n", wine_dbgstr_longlong(pii.OtherOperationCount));
todo_wine
{
ok( pii.OtherOperationCount > 0, "Expected an OtherOperationCount > 0\n");
@@ -1070,7 +1353,7 @@ static void test_query_process_debug_port(int argc, char **argv)
status = pNtQueryInformationProcess(NULL, ProcessDebugPort,
&debug_port, sizeof(debug_port), NULL);
ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %#x.\n", status);
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
&debug_port, sizeof(debug_port) - 1, NULL);
@@ -1111,6 +1394,40 @@ static void test_query_process_debug_port(int argc, char **argv)
ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
}
static void test_query_process_priority(void)
{
PROCESS_PRIORITY_CLASS priority[2];
ULONG ReturnLength;
DWORD orig_priority;
NTSTATUS status;
BOOL ret;
status = pNtQueryInformationProcess(NULL, ProcessPriorityClass, NULL, sizeof(priority[0]), NULL);
ok(status == STATUS_ACCESS_VIOLATION || broken(status == STATUS_INVALID_HANDLE) /* w2k3 */,
"Expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
status = pNtQueryInformationProcess(NULL, ProcessPriorityClass, &priority, sizeof(priority[0]), NULL);
ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessPriorityClass, &priority, 1, &ReturnLength);
ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessPriorityClass, &priority, sizeof(priority), &ReturnLength);
ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
orig_priority = GetPriorityClass(GetCurrentProcess());
ret = SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
ok(ret, "Failed to set priority class: %u\n", GetLastError());
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessPriorityClass, &priority, sizeof(priority[0]), &ReturnLength);
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
ok(priority[0].PriorityClass == PROCESS_PRIOCLASS_BELOW_NORMAL,
"Expected PROCESS_PRIOCLASS_BELOW_NORMAL, got %u\n", priority[0].PriorityClass);
ret = SetPriorityClass(GetCurrentProcess(), orig_priority);
ok(ret, "Failed to reset priority class: %u\n", GetLastError());
}
static void test_query_process_handlecount(void)
{
NTSTATUS status;
@@ -1293,27 +1610,27 @@ static void test_query_process_debug_object_handle(int argc, char **argv)
static void test_query_process_debug_flags(int argc, char **argv)
{
static const DWORD test_flags[] = { DEBUG_PROCESS,
DEBUG_ONLY_THIS_PROCESS,
DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS,
CREATE_SUSPENDED };
DWORD debug_flags = 0xdeadbeef;
char cmdline[MAX_PATH];
PROCESS_INFORMATION pi;
STARTUPINFOA si = { 0 };
NTSTATUS status;
DEBUG_EVENT ev;
DWORD result;
BOOL ret;
int i, j;
sprintf(cmdline, "%s %s %s", argv[0], argv[1], "debuggee");
/* test invalid arguments */
status = pNtQueryInformationProcess(NULL, ProcessDebugFlags, NULL, 0, NULL);
ok(status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INVALID_INFO_CLASS) /* WOW64 */,
"Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
si.cb = sizeof(si);
ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &si, &pi);
ok(ret, "CreateProcess failed, last error %#x.\n", GetLastError());
if (!ret) return;
status = pNtQueryInformationProcess(NULL, ProcessDebugFlags,
NULL, 0, NULL);
ok(status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INVALID_INFO_CLASS) /* NT4 */, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
status = pNtQueryInformationProcess(NULL, ProcessDebugFlags,
NULL, sizeof(debug_flags), NULL);
ok(status == STATUS_INVALID_HANDLE || status == STATUS_ACCESS_VIOLATION || broken(status == STATUS_INVALID_INFO_CLASS) /* W7PROX64 (32-bit) */,
status = pNtQueryInformationProcess(NULL, ProcessDebugFlags, NULL, sizeof(debug_flags), NULL);
ok(status == STATUS_INVALID_HANDLE || status == STATUS_ACCESS_VIOLATION || broken(status == STATUS_INVALID_INFO_CLASS) /* WOW64 */,
"Expected STATUS_INVALID_HANDLE, got %#x.\n", status);
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags,
@@ -1322,45 +1639,123 @@ static void test_query_process_debug_flags(int argc, char **argv)
status = pNtQueryInformationProcess(NULL, ProcessDebugFlags,
&debug_flags, sizeof(debug_flags), NULL);
ok(status == STATUS_INVALID_HANDLE || broken(status == STATUS_INVALID_INFO_CLASS) /* NT4 */, "Expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
ok(status == STATUS_INVALID_HANDLE || broken(status == STATUS_INVALID_INFO_CLASS) /* WOW64 */,
"Expected STATUS_INVALID_HANDLE, got %#x.\n", status);
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags,
&debug_flags, sizeof(debug_flags) - 1, NULL);
ok(status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INVALID_INFO_CLASS) /* NT4 */, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags,
&debug_flags, sizeof(debug_flags) + 1, NULL);
ok(status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INVALID_INFO_CLASS) /* NT4 */, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
/* test ProcessDebugFlags of current process */
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags,
&debug_flags, sizeof(debug_flags), NULL);
ok(!status || broken(status == STATUS_INVALID_INFO_CLASS) /* NT4 */, "NtQueryInformationProcess failed, status %#x.\n", status);
ok(debug_flags == TRUE|| broken(status == STATUS_INVALID_INFO_CLASS) /* NT4 */, "Expected flag TRUE, got %x.\n", debug_flags);
ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
ok(debug_flags == TRUE, "Expected flag TRUE, got %x.\n", debug_flags);
status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugFlags,
&debug_flags, sizeof(debug_flags), NULL);
ok(!status || broken(status == STATUS_INVALID_INFO_CLASS) /* NT4 */, "NtQueryInformationProcess failed, status %#x.\n", status);
ok(debug_flags == FALSE || broken(status == STATUS_INVALID_INFO_CLASS) /* NT4 */, "Expected flag FALSE, got %x.\n", debug_flags);
for (;;)
for (i = 0; i < sizeof(test_flags)/sizeof(test_flags[0]); i++)
{
DEBUG_EVENT ev;
DWORD expected_flags = !(test_flags[i] & DEBUG_ONLY_THIS_PROCESS);
sprintf(cmdline, "%s %s %s", argv[0], argv[1], "debuggee");
ret = WaitForDebugEvent(&ev, INFINITE);
ok(ret, "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
if (!ret) break;
si.cb = sizeof(si);
ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, test_flags[i], NULL, NULL, &si, &pi);
ok(ret, "CreateProcess failed, last error %#x.\n", GetLastError());
if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;
if (!(test_flags[i] & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)))
{
/* test ProcessDebugFlags before attaching with debugger */
status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugFlags,
&debug_flags, sizeof(debug_flags), NULL);
ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
ok(debug_flags == TRUE, "Expected flag TRUE, got %x.\n", debug_flags);
ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
if (!ret) break;
ret = DebugActiveProcess(pi.dwProcessId);
ok(ret, "DebugActiveProcess failed, last error %#x.\n", GetLastError());
expected_flags = FALSE;
}
/* test ProcessDebugFlags after attaching with debugger */
status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugFlags,
&debug_flags, sizeof(debug_flags), NULL);
ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
ok(debug_flags == expected_flags, "Expected flag %x, got %x.\n", expected_flags, debug_flags);
if (!(test_flags[i] & CREATE_SUSPENDED))
{
/* Continue a couple of times to make sure the process is fully initialized,
* otherwise Windows XP deadlocks in the following DebugActiveProcess(). */
for (;;)
{
ret = WaitForDebugEvent(&ev, 1000);
ok(ret, "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
if (!ret) break;
if (ev.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT) break;
ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
if (!ret) break;
}
result = SuspendThread(pi.hThread);
ok(result == 0, "Expected 0, got %u.\n", result);
}
ret = DebugActiveProcessStop(pi.dwProcessId);
ok(ret, "DebugActiveProcessStop failed, last error %#x.\n", GetLastError());
/* test ProcessDebugFlags after detaching debugger */
status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugFlags,
&debug_flags, sizeof(debug_flags), NULL);
ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
ok(debug_flags == expected_flags, "Expected flag %x, got %x.\n", expected_flags, debug_flags);
ret = DebugActiveProcess(pi.dwProcessId);
ok(ret, "DebugActiveProcess failed, last error %#x.\n", GetLastError());
/* test ProcessDebugFlags after re-attaching debugger */
status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugFlags,
&debug_flags, sizeof(debug_flags), NULL);
ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
ok(debug_flags == FALSE, "Expected flag FALSE, got %x.\n", debug_flags);
result = ResumeThread(pi.hThread);
todo_wine ok(result == 2, "Expected 2, got %u.\n", result);
/* Wait until the process is terminated. On Windows XP the process randomly
* gets stuck in a non-continuable exception, so stop after 100 iterations.
* On Windows 2003, the debugged process disappears (or stops?) without
* any EXIT_PROCESS_DEBUG_EVENT after a couple of events. */
for (j = 0; j < 100; j++)
{
ret = WaitForDebugEvent(&ev, 1000);
ok(ret || broken(GetLastError() == ERROR_SEM_TIMEOUT),
"WaitForDebugEvent failed, last error %#x.\n", GetLastError());
if (!ret) break;
if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;
ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
if (!ret) break;
}
ok(j < 100 || broken(j >= 100) /* Win XP */, "Expected less than 100 debug events.\n");
/* test ProcessDebugFlags after process has terminated */
status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugFlags,
&debug_flags, sizeof(debug_flags), NULL);
ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
ok(debug_flags == FALSE, "Expected flag FALSE, got %x.\n", debug_flags);
ret = CloseHandle(pi.hThread);
ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
ret = CloseHandle(pi.hProcess);
ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
}
ret = CloseHandle(pi.hThread);
ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
ret = CloseHandle(pi.hProcess);
ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
}
static void test_readvirtualmemory(void)
@@ -1439,7 +1834,7 @@ static void test_mapprotection(void)
status = pNtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &flags, sizeof(flags) );
ok( (status == STATUS_SUCCESS) || (status == STATUS_INVALID_INFO_CLASS), "Expected STATUS_SUCCESS, got %08x\n", status);
size.u.LowPart = 0x1000;
size.u.LowPart = 0x2000;
size.u.HighPart = 0;
status = pNtCreateSection ( &h,
STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE,
@@ -1453,7 +1848,7 @@ static void test_mapprotection(void)
offset.u.LowPart = 0;
offset.u.HighPart = 0;
count = 0x1000;
count = 0x2000;
addr = NULL;
status = pNtMapViewOfSection ( h, GetCurrentProcess(), &addr, 0, 0, &offset, &count, ViewShare, 0, PAGE_READWRITE);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
@@ -1476,7 +1871,7 @@ static void test_mapprotection(void)
ok( retlen == sizeof(info), "Expected STATUS_SUCCESS, got %08x\n", status);
ok((info.Protect & ~PAGE_NOCACHE) == PAGE_READWRITE, "addr.Protect is not PAGE_READWRITE, but 0x%x\n", info.Protect);
status = pNtUnmapViewOfSection (GetCurrentProcess(), addr);
status = pNtUnmapViewOfSection( GetCurrentProcess(), (char *)addr + 0x1050 );
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
pNtClose (h);
@@ -1488,12 +1883,17 @@ static void test_queryvirtualmemory(void)
{
NTSTATUS status;
SIZE_T readcount;
static const WCHAR windowsW[] = {'w','i','n','d','o','w','s'};
static const char teststring[] = "test string";
static char datatestbuf[42] = "abc";
static char rwtestbuf[42];
MEMORY_BASIC_INFORMATION mbi;
char stackbuf[42];
HMODULE module;
char buffer_name[sizeof(MEMORY_SECTION_NAME) + MAX_PATH * sizeof(WCHAR)];
MEMORY_SECTION_NAME *msn = (MEMORY_SECTION_NAME *)buffer_name;
BOOL found;
int i;
module = GetModuleHandleA( "ntdll.dll" );
trace("Check flags of the PE header of NTDLL.DLL at %p\n", module);
@@ -1567,6 +1967,43 @@ static void test_queryvirtualmemory(void)
"mbi.Protect is 0x%x\n", mbi.Protect);
}
else skip( "bss is outside of module\n" ); /* this can happen on Mac OS */
trace("Check section name of NTDLL.DLL with invalid size\n");
module = GetModuleHandleA( "ntdll.dll" );
memset(msn, 0, sizeof(*msn));
readcount = 0;
status = pNtQueryVirtualMemory(NtCurrentProcess(), module, MemorySectionName, msn, sizeof(*msn), &readcount);
ok( status == STATUS_BUFFER_OVERFLOW, "Expected STATUS_BUFFER_OVERFLOW, got %08x\n", status);
ok( readcount > 0, "Expected readcount to be > 0\n");
trace("Check section name of NTDLL.DLL with invalid size\n");
module = GetModuleHandleA( "ntdll.dll" );
memset(msn, 0, sizeof(*msn));
readcount = 0;
status = pNtQueryVirtualMemory(NtCurrentProcess(), module, MemorySectionName, msn, sizeof(*msn) - 1, &readcount);
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
ok( readcount > 0, "Expected readcount to be > 0\n");
trace("Check section name of NTDLL.DLL\n");
module = GetModuleHandleA( "ntdll.dll" );
memset(msn, 0x55, sizeof(*msn));
memset(buffer_name, 0x77, sizeof(buffer_name));
readcount = 0;
status = pNtQueryVirtualMemory(NtCurrentProcess(), module, MemorySectionName, msn, sizeof(buffer_name), &readcount);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
ok( readcount > 0, "Expected readcount to be > 0\n");
trace ("Section Name: %s\n", wine_dbgstr_w(msn->SectionFileName.Buffer));
pRtlDowncaseUnicodeString( &msn->SectionFileName, &msn->SectionFileName, FALSE );
for (found = FALSE, i = (msn->SectionFileName.Length - sizeof(windowsW)) / sizeof(WCHAR); i >= 0; i--)
found |= !memcmp( &msn->SectionFileName.Buffer[i], windowsW, sizeof(windowsW) );
ok( found, "Section name does not contain \"Windows\"\n");
trace("Check section name of non mapped memory\n");
memset(msn, 0, sizeof(*msn));
readcount = 0;
status = pNtQueryVirtualMemory(NtCurrentProcess(), &buffer_name, MemorySectionName, msn, sizeof(buffer_name), &readcount);
ok( status == STATUS_INVALID_ADDRESS, "Expected STATUS_INVALID_ADDRESS, got %08x\n", status);
ok( readcount == 0 || broken(readcount != 0) /* wow64 */, "Expected readcount to be 0\n");
}
static void test_affinity(void)
@@ -1780,6 +2217,39 @@ static void test_thread_start_address(void)
CloseHandle(thread);
}
static void test_query_data_alignment(void)
{
ULONG ReturnLength;
NTSTATUS status;
DWORD value;
value = 0xdeadbeef;
status = pNtQuerySystemInformation(SystemRecommendedSharedDataAlignment, &value, sizeof(value), &ReturnLength);
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
ok(sizeof(value) == ReturnLength, "Inconsistent length %u\n", ReturnLength);
ok(value == 64, "Expected 64, got %u\n", value);
}
static void test_working_set_limit(void)
{
DWORD_PTR lower = 0, upper = ~(DWORD_PTR)0;
MEMORY_BASIC_INFORMATION mbi;
SIZE_T readcount;
NTSTATUS status;
while (lower != upper)
{
DWORD_PTR check = (lower >> 1) + (upper >> 1) + (lower & upper & 1);
status = pNtQueryVirtualMemory(NtCurrentProcess(), (void *)check, MemoryBasicInformation,
&mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
if (status == STATUS_INVALID_PARAMETER) upper = check;
else lower = check + 1;
}
trace("working set limit is %p\n", (void *)upper);
ok(upper != ~(DWORD_PTR)0, "expected != ~(DWORD_PTR)0\n");
}
START_TEST(info)
{
char **argv;
@@ -1825,6 +2295,10 @@ START_TEST(info)
trace("Starting test_query_handle()\n");
test_query_handle();
/* 0x40 SystemHandleInformation */
trace("Starting test_query_handle_ex()\n");
test_query_handle_ex();
/* 0x15 SystemCacheInformation */
trace("Starting test_query_cache()\n");
test_query_cache();
@@ -1844,6 +2318,7 @@ START_TEST(info)
/* 0x49 SystemLogicalProcessorInformation */
trace("Starting test_query_logicalproc()\n");
test_query_logicalproc();
test_query_logicalprocex();
/* NtPowerInformation */
@@ -1873,6 +2348,10 @@ START_TEST(info)
trace("Starting test_process_debug_port()\n");
test_query_process_debug_port(argc, argv);
/* 0x12 ProcessPriorityClass */
trace("Starting test_query_process_priority()\n");
test_query_process_priority();
/* 0x14 ProcessHandleCount */
trace("Starting test_query_process_handlecount()\n");
test_query_process_handlecount();
@@ -1911,4 +2390,10 @@ START_TEST(info)
trace("Starting test_thread_start_address()\n");
test_thread_start_address();
trace("Starting test_query_data_alignment()\n");
test_query_data_alignment();
trace("Starting test_working_set_limit()\n");
test_working_set_limit();
}
+91 -27
View File
@@ -33,6 +33,8 @@ static VOID (WINAPI *pRtlFreeAnsiString)(PSTRING);
static NTSTATUS (WINAPI *pRtlInt64ToUnicodeString)(ULONGLONG, ULONG, UNICODE_STRING *);
static NTSTATUS (WINAPI *pRtlLargeIntegerToChar)(ULONGLONG *, ULONG, ULONG, PCHAR);
static NTSTATUS (WINAPI *pRtlUnicodeStringToAnsiString)(STRING *, const UNICODE_STRING *, BOOLEAN);
static void (WINAPI *p_alldvrm)(LONGLONG, LONGLONG);
static void (WINAPI *p_aulldvrm)(ULONGLONG, ULONGLONG);
static void InitFunctionPtrs(void)
@@ -45,6 +47,8 @@ static void InitFunctionPtrs(void)
pRtlInt64ToUnicodeString = (void *)GetProcAddress(hntdll, "RtlInt64ToUnicodeString");
pRtlLargeIntegerToChar = (void *)GetProcAddress(hntdll, "RtlLargeIntegerToChar");
pRtlUnicodeStringToAnsiString = (void *)GetProcAddress(hntdll, "RtlUnicodeStringToAnsiString");
p_alldvrm = (void *)GetProcAddress(hntdll, "_alldvrm");
p_aulldvrm = (void *)GetProcAddress(hntdll, "_aulldvrm");
} /* if */
}
@@ -113,10 +117,9 @@ static void test_RtlExtendedMagicDivide(void)
for (i = 0; i < NB_MAGIC_DIVIDE; i++) {
result = pRtlExtendedMagicDivide(magic_divide[i].a, magic_divide[i].b, magic_divide[i].shift);
ok(result == magic_divide[i].result,
"call failed: RtlExtendedMagicDivide(0x%x%08x, 0x%x%08x, %d) has result 0x%x%08x, expected 0x%x%08x\n",
(DWORD)(magic_divide[i].a >> 32), (DWORD)magic_divide[i].a, (DWORD)(magic_divide[i].b >> 32),
(DWORD)magic_divide[i].b, magic_divide[i].shift, (DWORD)(result >> 32), (DWORD)result,
(DWORD)(magic_divide[i].result >> 32), (DWORD)magic_divide[i].result);
"call failed: RtlExtendedMagicDivide(0x%s, 0x%s, %d) has result 0x%s, expected 0x%s\n",
wine_dbgstr_longlong(magic_divide[i].a), wine_dbgstr_longlong(magic_divide[i].b), magic_divide[i].shift,
wine_dbgstr_longlong(result), wine_dbgstr_longlong(magic_divide[i].result));
}
}
@@ -332,14 +335,12 @@ static void one_RtlInt64ToUnicodeString_test(int test_num, const largeint2str_t
} /* if */
} else {
ok(result == largeint2str->result,
"(test %d): RtlInt64ToUnicodeString(0x%x%08x, %d, [out]) has result %x, expected: %x\n",
test_num, (DWORD)(largeint2str->value >> 32), (DWORD)largeint2str->value,
largeint2str->base, result, largeint2str->result);
"(test %d): RtlInt64ToUnicodeString(0x%s, %d, [out]) has result %x, expected: %x\n",
test_num, wine_dbgstr_longlong(largeint2str->value), largeint2str->base, result, largeint2str->result);
if (result == STATUS_SUCCESS) {
ok(unicode_string.Buffer[unicode_string.Length/sizeof(WCHAR)] == '\0',
"(test %d): RtlInt64ToUnicodeString(0x%x%08x, %d, [out]) string \"%s\" is not NULL terminated\n",
test_num, (DWORD)(largeint2str->value >> 32), (DWORD)largeint2str->value,
largeint2str->base, ansi_str.Buffer);
"(test %d): RtlInt64ToUnicodeString(0x%s, %d, [out]) string \"%s\" is not NULL terminated\n",
test_num, wine_dbgstr_longlong(largeint2str->value), largeint2str->base, ansi_str.Buffer);
} /* if */
} /* if */
ok(memcmp(unicode_string.Buffer, expected_unicode_string.Buffer, LARGE_STRI_BUFFER_LENGTH * sizeof(WCHAR)) == 0,
@@ -347,12 +348,12 @@ static void one_RtlInt64ToUnicodeString_test(int test_num, const largeint2str_t
test_num, (DWORD)(largeint2str->value >>32), (DWORD)largeint2str->value, largeint2str->base,
ansi_str.Buffer, expected_ansi_str.Buffer);
ok(unicode_string.Length == expected_unicode_string.Length,
"(test %d): RtlInt64ToUnicodeString(0x%x%08x, %d, [out]) string has Length %d, expected: %d\n",
test_num, (DWORD)(largeint2str->value >> 32), (DWORD)largeint2str->value, largeint2str->base,
"(test %d): RtlInt64ToUnicodeString(0x%s, %d, [out]) string has Length %d, expected: %d\n",
test_num, wine_dbgstr_longlong(largeint2str->value), largeint2str->base,
unicode_string.Length, expected_unicode_string.Length);
ok(unicode_string.MaximumLength == expected_unicode_string.MaximumLength,
"(test %d): RtlInt64ToUnicodeString(0x%x%08x, %d, [out]) string has MaximumLength %d, expected: %d\n",
test_num, (DWORD)(largeint2str->value >> 32), (DWORD)largeint2str->value, largeint2str->base,
"(test %d): RtlInt64ToUnicodeString(0x%s, %d, [out]) string has MaximumLength %d, expected: %d\n",
test_num, wine_dbgstr_longlong(largeint2str->value), largeint2str->base,
unicode_string.MaximumLength, expected_unicode_string.MaximumLength);
pRtlFreeAnsiString(&expected_ansi_str);
pRtlFreeAnsiString(&ansi_str);
@@ -392,12 +393,12 @@ static void one_RtlLargeIntegerToChar_test(int test_num, const largeint2str_t *l
result = pRtlLargeIntegerToChar(&value, largeint2str->base, largeint2str->MaximumLength, dest_str);
} /* if */
ok(result == largeint2str->result,
"(test %d): RtlLargeIntegerToChar(0x%x%08x, %d, %d, [out]) has result %x, expected: %x\n",
test_num, (DWORD)(largeint2str->value >> 32), (DWORD)largeint2str->value, largeint2str->base,
"(test %d): RtlLargeIntegerToChar(0x%s, %d, %d, [out]) has result %x, expected: %x\n",
test_num, wine_dbgstr_longlong(largeint2str->value), largeint2str->base,
largeint2str->MaximumLength, result, largeint2str->result);
ok(memcmp(dest_str, largeint2str->Buffer, LARGE_STRI_BUFFER_LENGTH) == 0,
"(test %d): RtlLargeIntegerToChar(0x%x%08x, %d, %d, [out]) assigns string \"%s\", expected: \"%s\"\n",
test_num, (DWORD)(largeint2str->value >> 32), (DWORD)largeint2str->value, largeint2str->base,
"(test %d): RtlLargeIntegerToChar(0x%s, %d, %d, [out]) assigns string \"%s\", expected: \"%s\"\n",
test_num, wine_dbgstr_longlong(largeint2str->value), largeint2str->base,
largeint2str->MaximumLength, dest_str, largeint2str->Buffer);
}
@@ -415,30 +416,89 @@ static void test_RtlLargeIntegerToChar(void)
value = largeint2str[0].value;
result = pRtlLargeIntegerToChar(&value, 20, largeint2str[0].MaximumLength, NULL);
ok(result == STATUS_INVALID_PARAMETER,
"(test a): RtlLargeIntegerToChar(0x%x%08x, %d, %d, NULL) has result %x, expected: %x\n",
(DWORD)(largeint2str[0].value >> 32), (DWORD)largeint2str[0].value, 20,
"(test a): RtlLargeIntegerToChar(0x%s, %d, %d, NULL) has result %x, expected: %x\n",
wine_dbgstr_longlong(largeint2str[0].value), 20,
largeint2str[0].MaximumLength, result, STATUS_INVALID_PARAMETER);
result = pRtlLargeIntegerToChar(&value, 20, 0, NULL);
ok(result == STATUS_INVALID_PARAMETER,
"(test b): RtlLargeIntegerToChar(0x%x%08x, %d, %d, NULL) has result %x, expected: %x\n",
(DWORD)(largeint2str[0].value >> 32), (DWORD)largeint2str[0].value, 20,
"(test b): RtlLargeIntegerToChar(0x%s, %d, %d, NULL) has result %x, expected: %x\n",
wine_dbgstr_longlong(largeint2str[0].value), 20,
largeint2str[0].MaximumLength, result, STATUS_INVALID_PARAMETER);
result = pRtlLargeIntegerToChar(&value, largeint2str[0].base, 0, NULL);
ok(result == STATUS_BUFFER_OVERFLOW,
"(test c): RtlLargeIntegerToChar(0x%x%08x, %d, %d, NULL) has result %x, expected: %x\n",
(DWORD)(largeint2str[0].value >> 32), (DWORD)largeint2str[0].value,
largeint2str[0].base, 0, result, STATUS_BUFFER_OVERFLOW);
"(test c): RtlLargeIntegerToChar(0x%s, %d, %d, NULL) has result %x, expected: %x\n",
wine_dbgstr_longlong(largeint2str[0].value), largeint2str[0].base, 0, result, STATUS_BUFFER_OVERFLOW);
result = pRtlLargeIntegerToChar(&value, largeint2str[0].base, largeint2str[0].MaximumLength, NULL);
ok(result == STATUS_ACCESS_VIOLATION,
"(test d): RtlLargeIntegerToChar(0x%x%08x, %d, %d, NULL) has result %x, expected: %x\n",
(DWORD)(largeint2str[0].value >> 32), (DWORD)largeint2str[0].value,
"(test d): RtlLargeIntegerToChar(0x%s, %d, %d, NULL) has result %x, expected: %x\n",
wine_dbgstr_longlong(largeint2str[0].value),
largeint2str[0].base, largeint2str[0].MaximumLength, result, STATUS_ACCESS_VIOLATION);
}
#ifdef __i386__
#include "pshpack1.h"
struct lldvrm_thunk
{
BYTE push_ebx; /* pushl %ebx */
DWORD push_esp1; /* pushl 24(%esp) */
DWORD push_esp2; /* pushl 24(%esp) */
DWORD push_esp3; /* pushl 24(%esp) */
DWORD push_esp4; /* pushl 24(%esp) */
DWORD call; /* call 24(%esp) */
WORD mov_ecx_eax; /* movl %ecx,%eax */
WORD mov_ebx_edx; /* movl %ebx,%edx */
BYTE pop_ebx; /* popl %ebx */
BYTE ret; /* ret */
};
#include "poppack.h"
static void test__alldvrm(void)
{
struct lldvrm_thunk *thunk = VirtualAlloc(NULL, sizeof(*thunk), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
ULONGLONG (CDECL *call_lldvrm_func)(void *func, ULONGLONG, ULONGLONG) = (void *)thunk;
ULONGLONG ret;
memset(thunk, 0x90, sizeof(*thunk));
thunk->push_ebx = 0x53; /* pushl %ebx */
thunk->push_esp1 = 0x182474ff; /* pushl 24(%esp) */
thunk->push_esp2 = 0x182474ff; /* pushl 24(%esp) */
thunk->push_esp3 = 0x182474ff; /* pushl 24(%esp) */
thunk->push_esp4 = 0x182474ff; /* pushl 24(%esp) */
thunk->call = 0x182454ff; /* call 24(%esp) */
thunk->pop_ebx = 0x5b; /* popl %ebx */
thunk->ret = 0xc3; /* ret */
ret = call_lldvrm_func(p_alldvrm, 0x0123456701234567ULL, 3);
ok(ret == 0x61172255b66c77ULL, "got %x%08x\n", (DWORD)(ret >> 32), (DWORD)ret);
ret = call_lldvrm_func(p_alldvrm, 0x0123456701234567ULL, -3);
ok(ret == 0xff9ee8ddaa499389ULL, "got %x%08x\n", (DWORD)(ret >> 32), (DWORD)ret);
ret = call_lldvrm_func(p_aulldvrm, 0x0123456701234567ULL, 3);
ok(ret == 0x61172255b66c77ULL, "got %x%08x\n", (DWORD)(ret >> 32), (DWORD)ret);
ret = call_lldvrm_func(p_aulldvrm, 0x0123456701234567ULL, -3);
ok(ret == 0, "got %x%08x\n", (DWORD)(ret >> 32), (DWORD)ret);
thunk->mov_ecx_eax = 0xc889;
thunk->mov_ebx_edx = 0xda89;
ret = call_lldvrm_func(p_alldvrm, 0x0123456701234567ULL, 3);
ok(ret == 2, "got %x%08x\n", (DWORD)(ret >> 32), (DWORD)ret);
ret = call_lldvrm_func(p_alldvrm, 0x0123456701234567ULL, -3);
ok(ret == 2, "got %x%08x\n", (DWORD)(ret >> 32), (DWORD)ret);
ret = call_lldvrm_func(p_aulldvrm, 0x0123456701234567ULL, 3);
ok(ret == 2, "got %x%08x\n", (DWORD)(ret >> 32), (DWORD)ret);
ret = call_lldvrm_func(p_aulldvrm, 0x0123456701234567ULL, -3);
ok(ret == 0x123456701234567ULL, "got %x%08x\n", (DWORD)(ret >> 32), (DWORD)ret);
}
#endif /* __i386__ */
START_TEST(large_int)
{
InitFunctionPtrs();
@@ -449,4 +509,8 @@ START_TEST(large_int)
test_RtlInt64ToUnicodeString();
if (pRtlLargeIntegerToChar)
test_RtlLargeIntegerToChar();
#ifdef __i386__
test__alldvrm();
#endif /* __i386__ */
}
@@ -20,10 +20,6 @@
#include <stdarg.h>
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x500 /* For NTSTATUS */
#endif
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
File diff suppressed because it is too large Load Diff
+5 -4
View File
@@ -267,7 +267,7 @@ static void test_RtlGetFullPathName_U(void)
{ "c:/test/ .... .. ", "c:\\test\\", NULL},
{ "c:/test/..", "c:\\", NULL},
{ "c:/test/.. ", "c:\\test\\", NULL},
{ "c:/TEST", "c:\\test", "test"},
{ "c:/TEST", "c:\\TEST", "TEST"},
{ "c:/test/file", "c:\\test\\file", "file"},
{ "c:/test./file", "c:\\test\\file", "file"},
{ "c:/test.. /file", "c:\\test.. \\file","file"},
@@ -281,6 +281,7 @@ static void test_RtlGetFullPathName_U(void)
{ "c:///test\\..\\file\\..\\//", "c:\\", NULL},
{ "c:/test../file", "c:\\test.\\file", "file",
"c:\\test..\\file", "file"}, /* vista */
{ "c:\\test", "c:\\test", "test"},
{ NULL, NULL, NULL}
};
@@ -327,14 +328,14 @@ static void test_RtlGetFullPathName_U(void)
"Wrong result %d/%d for \"%s\"\n", ret, len, test->path );
ok(pRtlUnicodeToMultiByteN(rbufferA,MAX_PATH,&reslen,rbufferW,(lstrlenW(rbufferW) + 1) * sizeof(WCHAR)) == STATUS_SUCCESS,
"RtlUnicodeToMultiByteN failed\n");
ok(!lstrcmpiA(rbufferA,test->rname) || (test->alt_rname && !lstrcmpiA(rbufferA,test->alt_rname)),
ok(!lstrcmpA(rbufferA,test->rname) || (test->alt_rname && !lstrcmpA(rbufferA,test->alt_rname)),
"Got \"%s\" expected \"%s\"\n",rbufferA,test->rname);
if (file_part)
{
ok(pRtlUnicodeToMultiByteN(rfileA,MAX_PATH,&reslen,file_part,(lstrlenW(file_part) + 1) * sizeof(WCHAR)) == STATUS_SUCCESS,
"RtlUnicodeToMultiByteN failed\n");
ok((test->rfile && !lstrcmpiA(rfileA,test->rfile)) ||
(test->alt_rfile && !lstrcmpiA(rfileA,test->alt_rfile)),
ok((test->rfile && !lstrcmpA(rfileA,test->rfile)) ||
(test->alt_rfile && !lstrcmpA(rfileA,test->alt_rfile)),
"Got \"%s\" expected \"%s\"\n",rfileA,test->rfile);
}
else
+511 -16
View File
@@ -75,6 +75,7 @@ static NTSTATUS (WINAPI *pNtCreateNamedPipeFile) (PHANDLE handle, ULONG access,
static NTSTATUS (WINAPI *pNtQueryInformationFile) (IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass);
static NTSTATUS (WINAPI *pNtSetInformationFile) (HANDLE handle, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS class);
static NTSTATUS (WINAPI *pNtCancelIoFile) (HANDLE hFile, PIO_STATUS_BLOCK io_status);
static NTSTATUS (WINAPI *pNtCancelIoFileEx) (HANDLE hFile, IO_STATUS_BLOCK *iosb, IO_STATUS_BLOCK *io_status);
static void (WINAPI *pRtlInitUnicodeString) (PUNICODE_STRING target, PCWSTR source);
static HANDLE (WINAPI *pOpenThread)(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId);
@@ -95,6 +96,7 @@ static BOOL init_func_ptrs(void)
loadfunc(NtQueryInformationFile)
loadfunc(NtSetInformationFile)
loadfunc(NtCancelIoFile)
loadfunc(NtCancelIoFileEx)
loadfunc(RtlInitUnicodeString)
/* not fatal */
@@ -104,6 +106,11 @@ static BOOL init_func_ptrs(void)
return TRUE;
}
static inline BOOL is_signaled( HANDLE obj )
{
return WaitForSingleObject( obj, 0 ) == WAIT_OBJECT_0;
}
static const WCHAR testpipe[] = { '\\', '\\', '.', '\\', 'p', 'i', 'p', 'e', '\\',
't', 'e', 's', 't', 'p', 'i', 'p', 'e', 0 };
static const WCHAR testpipe_nt[] = { '\\', '?', '?', '\\', 'p', 'i', 'p', 'e', '\\',
@@ -133,6 +140,21 @@ static NTSTATUS create_pipe(PHANDLE handle, ULONG sharing, ULONG options)
return res;
}
static BOOL ioapc_called;
static void CALLBACK ioapc(void *arg, PIO_STATUS_BLOCK io, ULONG reserved)
{
ioapc_called = TRUE;
}
static NTSTATUS listen_pipe(HANDLE hPipe, HANDLE hEvent, PIO_STATUS_BLOCK iosb, BOOL use_apc)
{
int dummy;
ioapc_called = FALSE;
return pNtFsControlFile(hPipe, hEvent, use_apc ? &ioapc: NULL, use_apc ? &dummy: NULL, iosb, FSCTL_PIPE_LISTEN, 0, 0, 0, 0);
}
static void test_create_invalid(void)
{
IO_STATUS_BLOCK iosb;
@@ -200,6 +222,7 @@ static void test_create(void)
int j, k;
FILE_PIPE_LOCAL_INFORMATION info;
IO_STATUS_BLOCK iosb;
HANDLE hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
static const DWORD access[] = { 0, GENERIC_READ, GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE};
static const DWORD sharing[] = { FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE };
@@ -210,12 +233,15 @@ static void test_create(void)
HANDLE hclient;
BOOL should_succeed = TRUE;
res = create_pipe(&hserver, sharing[j], FILE_SYNCHRONOUS_IO_NONALERT);
res = create_pipe(&hserver, sharing[j], 0);
if (res) {
ok(0, "NtCreateNamedPipeFile returned %x, sharing: %x\n", res, sharing[j]);
continue;
}
res = listen_pipe(hserver, hEvent, &iosb, FALSE);
ok(res == STATUS_PENDING, "NtFsControlFile returned %x\n", res);
res = pNtQueryInformationFile(hserver, &iosb, &info, sizeof(info), (FILE_INFORMATION_CLASS)24);
ok(!res, "NtQueryInformationFile for server returned %x, sharing: %x\n", res, sharing[j]);
ok(info.NamedPipeConfiguration == pipe_config[j], "wrong duplex status for pipe: %d, expected %d\n",
@@ -245,21 +271,7 @@ static void test_create(void)
CloseHandle(hserver);
}
}
}
static BOOL ioapc_called;
static void CALLBACK ioapc(void *arg, PIO_STATUS_BLOCK io, ULONG reserved)
{
ioapc_called = TRUE;
}
static NTSTATUS listen_pipe(HANDLE hPipe, HANDLE hEvent, PIO_STATUS_BLOCK iosb, BOOL use_apc)
{
int dummy;
ioapc_called = FALSE;
return pNtFsControlFile(hPipe, hEvent, use_apc ? &ioapc: NULL, use_apc ? &dummy: NULL, iosb, FSCTL_PIPE_LISTEN, 0, 0, 0, 0);
CloseHandle(hEvent);
}
static void test_overlapped(void)
@@ -305,10 +317,12 @@ static void test_overlapped(void)
if (hClient != INVALID_HANDLE_VALUE)
{
SetEvent(hEvent);
memset(&iosb, 0x55, sizeof(iosb));
res = listen_pipe(hPipe, hEvent, &iosb, TRUE);
ok(res == STATUS_PIPE_CONNECTED, "NtFsControlFile returned %x\n", res);
ok(U(iosb).Status == 0x55555555, "iosb.Status got changed to %x\n", U(iosb).Status);
ok(!is_signaled(hEvent), "hEvent not signaled\n");
CloseHandle(hClient);
}
@@ -317,6 +331,73 @@ static void test_overlapped(void)
CloseHandle(hEvent);
}
static void test_completion(void)
{
static const char buf[] = "testdata";
FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info;
HANDLE port, pipe, client;
IO_STATUS_BLOCK iosb;
OVERLAPPED ov, *pov;
IO_STATUS_BLOCK io;
NTSTATUS status;
DWORD num_bytes;
ULONG_PTR key;
DWORD dwret;
BOOL ret;
memset(&ov, 0, sizeof(ov));
ov.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
ok(ov.hEvent != INVALID_HANDLE_VALUE, "CreateEvent failed, error %u\n", GetLastError());
status = create_pipe(&pipe, FILE_SHARE_READ | FILE_SHARE_WRITE, 0 /* OVERLAPPED */);
ok(!status, "NtCreateNamedPipeFile returned %x\n", status);
status = listen_pipe(pipe, ov.hEvent, &iosb, FALSE);
ok(status == STATUS_PENDING, "NtFsControlFile returned %x\n", status);
client = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
ok(client != INVALID_HANDLE_VALUE, "CreateFile failed, error %u\n", GetLastError());
dwret = WaitForSingleObject(ov.hEvent, 0);
ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", dwret);
port = CreateIoCompletionPort(client, NULL, 0xdeadbeef, 0);
ok(port != NULL, "CreateIoCompletionPort failed, error %u\n", GetLastError());
ret = WriteFile(client, buf, sizeof(buf), &num_bytes, &ov);
ok(ret, "WriteFile failed, error %u\n", GetLastError());
ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
key = 0;
pov = NULL;
ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
ok(ret, "GetQueuedCompletionStatus failed, error %u\n", GetLastError());
ok(key == 0xdeadbeef, "expected 0xdeadbeef, got %lx\n", key);
ok(pov == &ov, "expected %p, got %p\n", &ov, pov);
info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
status = pNtSetInformationFile(client, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
info.Flags = 0;
status = pNtQueryInformationFile(client, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
ok((info.Flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS) != 0, "got %08x\n", info.Flags);
ret = WriteFile(client, buf, sizeof(buf), &num_bytes, &ov);
ok(ret, "WriteFile failed, error %u\n", GetLastError());
ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
pov = (void *)0xdeadbeef;
ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
ok(!ret, "GetQueuedCompletionStatus succeeded\n");
ok(pov == NULL, "expected NULL, got %p\n", pov);
CloseHandle(ov.hEvent);
CloseHandle(client);
CloseHandle(pipe);
CloseHandle(port);
}
static BOOL userapc_called;
static void CALLBACK userapc(ULONG_PTR dwParam)
{
@@ -498,6 +579,21 @@ static void test_cancelio(void)
ok(ioapc_called, "IOAPC didn't run\n");
CloseHandle(hPipe);
res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, 0 /* OVERLAPPED */);
ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
memset(&iosb, 0x55, sizeof(iosb));
res = listen_pipe(hPipe, hEvent, &iosb, FALSE);
ok(res == STATUS_PENDING, "NtFsControlFile returned %x\n", res);
res = pNtCancelIoFileEx(hPipe, &iosb, &cancel_sb);
ok(!res, "NtCancelIoFileEx returned %x\n", res);
ok(U(iosb).Status == STATUS_CANCELLED, "Wrong iostatus %x\n", U(iosb).Status);
ok(WaitForSingleObject(hEvent, 0) == 0, "hEvent not signaled\n");
CloseHandle(hEvent);
CloseHandle(hPipe);
}
@@ -688,6 +784,389 @@ static void test_filepipeinfo(void)
CloseHandle(hServer);
}
static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
{
int *count = arg;
(*count)++;
ok( !reserved, "reserved is not 0: %x\n", reserved );
}
static void test_peek(HANDLE pipe, BOOL is_msgmode)
{
FILE_PIPE_PEEK_BUFFER buf;
IO_STATUS_BLOCK iosb;
HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
NTSTATUS status;
memset(&iosb, 0x55, sizeof(iosb));
status = NtFsControlFile(pipe, NULL, NULL, NULL, &iosb, FSCTL_PIPE_PEEK, NULL, 0, &buf, sizeof(buf));
ok(!status || status == STATUS_PENDING, "NtFsControlFile failed: %x\n", status);
ok(!iosb.Status, "iosb.Status = %x\n", iosb.Status);
ok(buf.ReadDataAvailable == 1, "ReadDataAvailable = %u\n", buf.ReadDataAvailable);
ResetEvent(event);
memset(&iosb, 0x55, sizeof(iosb));
status = NtFsControlFile(pipe, event, NULL, NULL, &iosb, FSCTL_PIPE_PEEK, NULL, 0, &buf, sizeof(buf));
ok(!status || status == STATUS_PENDING, "NtFsControlFile failed: %x\n", status);
ok(buf.ReadDataAvailable == 1, "ReadDataAvailable = %u\n", buf.ReadDataAvailable);
ok(!iosb.Status, "iosb.Status = %x\n", iosb.Status);
todo_wine_if(!is_msgmode)
ok(is_signaled(event), "event is not signaled\n");
CloseHandle(event);
}
#define PIPENAME "\\\\.\\pipe\\ntdll_tests_pipe.c"
static BOOL create_pipe_pair( HANDLE *read, HANDLE *write, ULONG flags, ULONG type, ULONG size )
{
const BOOL server_reader = flags & PIPE_ACCESS_INBOUND;
HANDLE client, server;
server = CreateNamedPipeA(PIPENAME, flags, PIPE_WAIT | type,
1, size, size, NMPWAIT_USE_DEFAULT_WAIT, NULL);
ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
client = CreateFileA(PIPENAME, server_reader ? GENERIC_WRITE : GENERIC_READ | FILE_WRITE_ATTRIBUTES, 0,
NULL, OPEN_EXISTING, flags & FILE_FLAG_OVERLAPPED, 0);
ok(client != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
if(server_reader)
{
*read = server;
*write = client;
}
else
{
if(type & PIPE_READMODE_MESSAGE)
{
DWORD read_mode = PIPE_READMODE_MESSAGE;
ok(SetNamedPipeHandleState(client, &read_mode, NULL, NULL), "Change mode\n");
}
*read = client;
*write = server;
}
return TRUE;
}
static void read_pipe_test(ULONG pipe_flags, ULONG pipe_type)
{
IO_STATUS_BLOCK iosb, iosb2;
HANDLE handle, read, write;
HANDLE event = CreateEventA( NULL, TRUE, FALSE, NULL );
int apc_count = 0;
char buffer[128];
DWORD written;
BOOL ret;
NTSTATUS status;
if (!create_pipe_pair( &read, &write, FILE_FLAG_OVERLAPPED | pipe_flags, pipe_type, 4096 )) return;
/* try read with no data */
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
ok( is_signaled( read ), "read handle is not signaled\n" );
status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( read ), "read handle is signaled\n" );
ok( !is_signaled( event ), "event is signaled\n" );
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" );
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 );
ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
ok( !is_signaled( read ), "read handle is signaled\n" );
ok( is_signaled( event ), "event is not signaled\n" );
ok( !apc_count, "apc was called\n" );
apc_count = 0;
SleepEx( 1, FALSE ); /* non-alertable sleep */
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc not called\n" );
/* with no event, the pipe handle itself gets signaled */
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
ok( !is_signaled( read ), "read handle is signaled\n" );
status = NtReadFile( read, 0, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( read ), "read handle is signaled\n" );
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" );
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 );
ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
ok( is_signaled( read ), "read handle is not signaled\n" );
ok( !apc_count, "apc was called\n" );
apc_count = 0;
SleepEx( 1, FALSE ); /* non-alertable sleep */
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc not called\n" );
/* now read with data ready */
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
ResetEvent( event );
ret = WriteFile( write, buffer, 1, &written, NULL );
ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
test_peek(read, pipe_type & PIPE_TYPE_MESSAGE);
status = NtReadFile( 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 );
ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
ok( is_signaled( event ), "event is not signaled\n" );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, FALSE ); /* non-alertable sleep */
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc not called\n" );
/* now partial read with data ready */
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
ResetEvent( event );
ret = WriteFile( write, buffer, 2, &written, NULL );
ok(ret && written == 2, "WriteFile error %d\n", GetLastError());
status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
if (pipe_type & PIPE_READMODE_MESSAGE)
{
ok( status == STATUS_BUFFER_OVERFLOW, "wrong status %x\n", status );
ok( U(iosb).Status == STATUS_BUFFER_OVERFLOW, "wrong status %x\n", U(iosb).Status );
}
else
{
ok( status == STATUS_SUCCESS, "wrong status %x\n", status );
ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
}
ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
ok( is_signaled( event ), "event is not signaled\n" );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, FALSE ); /* non-alertable sleep */
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc not called\n" );
apc_count = 0;
status = NtReadFile( 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 );
ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
ok( is_signaled( event ), "event is not signaled\n" );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, FALSE ); /* non-alertable sleep */
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc not called\n" );
/* try read with no data */
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
ok( is_signaled( event ), "event is not signaled\n" ); /* check that read resets the event */
status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( event ), "event is signaled\n" );
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" );
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 not signaled\n" );
ok( U(iosb).Status == 0, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 1, "wrong info %lu\n", iosb.Information );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc was not called\n" );
/* read from disconnected pipe */
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
CloseHandle( write );
status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
ok( status == STATUS_PIPE_BROKEN, "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( read );
/* read from disconnected pipe, with invalid event handle */
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
status = NtReadFile( read, (HANDLE)0xdeadbeef, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
ok( status == STATUS_INVALID_HANDLE, "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( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( !apc_count, "apc was called\n" );
CloseHandle( read );
/* read from closed handle */
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
SetEvent( event );
status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
ok( status == STATUS_INVALID_HANDLE, "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 not signaled\n" ); /* not reset on invalid handle */
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( !apc_count, "apc was called\n" );
/* disconnect while async read is in progress */
if (!create_pipe_pair( &read, &write, FILE_FLAG_OVERLAPPED | pipe_flags, pipe_type, 4096 )) return;
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( event ), "event is signaled\n" );
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" );
CloseHandle( write );
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
todo_wine_if(!(pipe_type & PIPE_TYPE_MESSAGE) && (pipe_flags & PIPE_ACCESS_OUTBOUND))
ok( U(iosb).Status == STATUS_PIPE_BROKEN, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
ok( is_signaled( event ), "event is not signaled\n" );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc was not called\n" );
CloseHandle( read );
if (!create_pipe_pair( &read, &write, FILE_FLAG_OVERLAPPED | pipe_flags, pipe_type, 4096 )) return;
ret = DuplicateHandle(GetCurrentProcess(), read, GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS);
ok(ret, "Failed to duplicate handle: %d\n", GetLastError());
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
status = NtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( event ), "event is signaled\n" );
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" );
/* Cancel by other handle */
status = pNtCancelIoFile( read, &iosb2 );
ok(status == STATUS_SUCCESS, "failed to cancel by different handle: %x\n", status);
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
ok( is_signaled( event ), "event is not signaled\n" );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc was not called\n" );
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( event ), "event is signaled\n" );
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" );
/* Close queued handle */
CloseHandle( read );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( U(iosb).Status == 0xdeadbabe, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 0xdeadbeef, "wrong info %lu\n", iosb.Information );
status = pNtCancelIoFile( read, &iosb2 );
ok(status == STATUS_INVALID_HANDLE, "cancelled by closed handle?\n");
status = pNtCancelIoFile( handle, &iosb2 );
ok(status == STATUS_SUCCESS, "failed to cancel: %x\n", status);
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
ok( is_signaled( event ), "event is not signaled\n" );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc was not called\n" );
CloseHandle( handle );
CloseHandle( write );
if (pNtCancelIoFileEx)
{
/* Basic Cancel Ex */
if (!create_pipe_pair( &read, &write, FILE_FLAG_OVERLAPPED | pipe_flags, pipe_type, 4096 )) return;
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( event ), "event is signaled\n" );
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" );
status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
ok( is_signaled( event ), "event is not signaled\n" );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 1, "apc was not called\n" );
/* Duplicate iosb */
apc_count = 0;
U(iosb).Status = 0xdeadbabe;
iosb.Information = 0xdeadbeef;
status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( event ), "event is signaled\n" );
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" );
status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 2, NULL, NULL );
ok( status == STATUS_PENDING, "wrong status %x\n", status );
ok( !is_signaled( event ), "event is signaled\n" );
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" );
status = pNtCancelIoFileEx( read, &iosb, &iosb2 );
ok(status == STATUS_SUCCESS, "Failed to cancel I/O\n");
Sleep(1); /* FIXME: needed for wine to run the i/o apc */
ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status );
ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
ok( is_signaled( event ), "event is not signaled\n" );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( apc_count == 2, "apc was not called\n" );
CloseHandle( read );
CloseHandle( write );
}
CloseHandle(event);
}
START_TEST(pipe)
{
if (!init_func_ptrs())
@@ -702,6 +1181,9 @@ START_TEST(pipe)
trace("starting overlapped tests\n");
test_overlapped();
trace("starting completion tests\n");
test_completion();
trace("starting FILE_PIPE_INFORMATION tests\n");
test_filepipeinfo();
@@ -716,4 +1198,17 @@ START_TEST(pipe)
trace("starting cancelio tests\n");
test_cancelio();
trace("starting byte read in byte mode client -> server\n");
read_pipe_test(PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE);
trace("starting byte read in message mode client -> server\n");
read_pipe_test(PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE);
trace("starting message read in message mode client -> server\n");
read_pipe_test(PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
trace("starting byte read in byte mode server -> client\n");
read_pipe_test(PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE);
trace("starting byte read in message mode server -> client\n");
read_pipe_test(PIPE_ACCESS_OUTBOUND, PIPE_TYPE_MESSAGE);
trace("starting message read in message mode server -> client\n");
read_pipe_test(PIPE_ACCESS_OUTBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
}
+207
View File
@@ -0,0 +1,207 @@
/*
* Unit test suite for process functions
*
* Copyright 2017 Michael Müller
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdio.h>
#include "ntdll_test.h"
#include "windef.h"
#include "winbase.h"
static NTSTATUS (WINAPI *pNtResumeProcess)(HANDLE);
static NTSTATUS (WINAPI *pNtSuspendProcess)(HANDLE);
static NTSTATUS (WINAPI *pNtSuspendThread)(HANDLE,PULONG);
static NTSTATUS (WINAPI *pNtResumeThread)(HANDLE);
static void test_NtSuspendProcess(char *process_name)
{
PROCESS_INFORMATION info;
DEBUG_EVENT ev;
STARTUPINFOA startup;
NTSTATUS status;
HANDLE event;
char buffer[MAX_PATH];
ULONG count;
DWORD ret;
status = pNtResumeProcess(GetCurrentProcess());
ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);
event = CreateEventA(NULL, TRUE, FALSE, "wine_suspend_event");
ok(!!event, "Failed to create event: %u\n", GetLastError());
memset(&startup, 0, sizeof(startup));
startup.cb = sizeof(startup);
sprintf(buffer, "%s tests/process.c dummy_process wine_suspend_event", process_name);
ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info);
ok(ret, "CreateProcess failed with error %u\n", GetLastError());
ret = WaitForSingleObject(event, 500);
ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret);
status = pNtSuspendProcess(info.hProcess);
ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);
ResetEvent(event);
ret = WaitForSingleObject(event, 200);
ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);
status = NtResumeThread(info.hThread, &count);
ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);
ok(count == 1, "Expected count 1, got %d\n", count);
ret = WaitForSingleObject(event, 200);
ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret);
status = pNtResumeProcess(info.hProcess);
ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);
status = pNtSuspendThread(info.hThread, &count);
ok(status == STATUS_SUCCESS, "NtSuspendThread failed: %x\n", status);
ok(count == 0, "Expected count 0, got %d\n", count);
ResetEvent(event);
ret = WaitForSingleObject(event, 200);
ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);
status = pNtResumeProcess(info.hProcess);
ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);
ret = WaitForSingleObject(event, 200);
ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret);
status = pNtSuspendThread(info.hThread, &count);
ok(status == STATUS_SUCCESS, "NtSuspendThread failed: %x\n", status);
ok(count == 0, "Expected count 0, got %d\n", count);
status = pNtSuspendThread(info.hThread, &count);
ok(status == STATUS_SUCCESS, "NtSuspendThread failed: %x\n", status);
ok(count == 1, "Expected count 1, got %d\n", count);
ResetEvent(event);
ret = WaitForSingleObject(event, 200);
ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);
status = pNtResumeProcess(info.hProcess);
ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);
ret = WaitForSingleObject(event, 200);
ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);
status = pNtResumeProcess(info.hProcess);
ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);
ret = WaitForSingleObject(event, 200);
ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret);
ret = DebugActiveProcess(info.dwProcessId);
ok(ret, "Failed to debug process: %d\n", GetLastError());
ResetEvent(event);
ret = WaitForSingleObject(event, 200);
ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);
for (;;)
{
ret = WaitForDebugEvent(&ev, INFINITE);
ok(ret, "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
if (!ret) break;
if (ev.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT) break;
ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
if (!ret) break;
}
ResetEvent(event);
ret = WaitForSingleObject(event, 200);
ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);
status = pNtResumeProcess(info.hProcess);
ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);
ret = WaitForSingleObject(event, 200);
ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);
status = NtResumeThread(info.hThread, &count);
ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);
ok(count == 0, "Expected count 0, got %d\n", count);
ret = WaitForSingleObject(event, 200);
ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);
ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
ret = WaitForSingleObject(event, 200);
ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret);
TerminateProcess(info.hProcess, 0);
CloseHandle(info.hProcess);
CloseHandle(info.hThread);
}
static void dummy_process(char *event_name)
{
HANDLE event = OpenEventA(EVENT_ALL_ACCESS, FALSE, event_name);
while (TRUE)
{
SetEvent(event);
OutputDebugStringA("test");
Sleep(5);
}
}
START_TEST(process)
{
HMODULE mod;
char **argv;
int argc;
argc = winetest_get_mainargs(&argv);
if (argc >= 4 && strcmp(argv[2], "dummy_process") == 0)
{
dummy_process(argv[3]);
return;
}
mod = GetModuleHandleA("ntdll.dll");
if (!mod)
{
win_skip("Not running on NT, skipping tests\n");
return;
}
pNtResumeProcess = (void*)GetProcAddress(mod, "NtResumeProcess");
pNtSuspendProcess = (void*)GetProcAddress(mod, "NtSuspendProcess");
pNtResumeThread = (void*)GetProcAddress(mod, "NtResumeThread");
pNtSuspendThread = (void*)GetProcAddress(mod, "NtSuspendThread");
test_NtSuspendProcess(argv[0]);
}
+75 -1
View File
@@ -364,16 +364,22 @@ static void test_NtOpenKey(void)
/* Zero accessmask */
attr.Length = sizeof(attr);
key = (HANDLE)0xdeadbeef;
status = pNtOpenKey(&key, 0, &attr);
todo_wine
ok(status == STATUS_ACCESS_DENIED, "Expected STATUS_ACCESS_DENIED, got: 0x%08x\n", status);
todo_wine
ok(!key, "key = %p\n", key);
if (status == STATUS_SUCCESS) NtClose(key);
/* Calling without parent key requres full registry path. */
pRtlCreateUnicodeStringFromAsciiz( &str, "Machine" );
InitializeObjectAttributes(&attr, &str, 0, 0, 0);
key = (HANDLE)0xdeadbeef;
status = pNtOpenKey(&key, KEY_READ, &attr);
todo_wine ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD, "NtOpenKey Failed: 0x%08x\n", status);
todo_wine
ok(!key, "key = %p\n", key);
pRtlFreeUnicodeString( &str );
/* Open is case sensitive unless OBJ_CASE_INSENSITIVE is specified. */
@@ -1070,8 +1076,10 @@ static void test_symlinks(void)
/* try opening the target through the link */
attr.ObjectName = &link_str;
key = (HANDLE)0xdeadbeef;
status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey wrong status 0x%08x\n", status );
ok( !key, "key = %p\n", key );
attr.ObjectName = &target_str;
status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
@@ -1135,6 +1143,40 @@ static void test_symlinks(void)
"wrong len %u\n", len );
pNtClose( key );
if (pNtOpenKeyEx)
{
/* REG_OPTION_OPEN_LINK flag doesn't matter */
status = pNtOpenKeyEx( &key, KEY_ALL_ACCESS, &attr, REG_OPTION_OPEN_LINK );
ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status );
len = sizeof(buffer);
status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR),
"wrong len %u\n", len );
pNtClose( key );
status = pNtOpenKeyEx( &key, KEY_ALL_ACCESS, &attr, 0 );
ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status );
len = sizeof(buffer);
status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR),
"wrong len %u\n", len );
pNtClose( key );
attr.Attributes = 0;
status = pNtOpenKeyEx( &key, KEY_ALL_ACCESS, &attr, REG_OPTION_OPEN_LINK );
ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status );
len = sizeof(buffer);
status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status );
pNtClose( key );
}
attr.Attributes = OBJ_OPENLINK;
status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
len = sizeof(buffer);
@@ -1144,6 +1186,36 @@ static void test_symlinks(void)
"wrong len %u\n", len );
pNtClose( key );
/* delete target and create by NtCreateKey on link */
attr.ObjectName = &target_str;
status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status );
status = pNtDeleteKey( key );
ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status );
pNtClose( key );
attr.ObjectName = &link_str;
attr.Attributes = 0;
status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey wrong status 0x%08x\n", status );
status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
todo_wine ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
pNtClose( key );
if (status) /* can be removed once todo_wine above is fixed */
{
attr.ObjectName = &target_str;
attr.Attributes = OBJ_OPENLINK;
status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
pNtClose( key );
}
attr.ObjectName = &target_str;
attr.Attributes = OBJ_OPENLINK;
status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
ok( status == STATUS_SUCCESS, "NtOpenKey wrong status 0x%08x\n", status );
if (0) /* crashes the Windows kernel on some Vista systems */
{
/* reopen the link from itself */
@@ -1207,8 +1279,10 @@ static void test_symlinks(void)
ok( status == STATUS_SUCCESS || status == STATUS_OBJECT_NAME_NOT_FOUND,
"NtOpenKey wrong status 0x%08x\n", status );
status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, REG_OPTION_CREATE_LINK, 0 );
key = (HKEY)0xdeadbeef;
status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, REG_OPTION_CREATE_LINK, NULL );
ok( status == STATUS_OBJECT_NAME_COLLISION, "NtCreateKey failed: 0x%08x\n", status );
ok( !key, "key = %p\n", key );
status = pNtDeleteKey( link );
ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status );
+387 -18
View File
@@ -86,7 +86,6 @@ static RTL_HANDLE * (WINAPI * pRtlAllocateHandle)(RTL_HANDLE_TABLE *, ULONG *);
static BOOLEAN (WINAPI * pRtlFreeHandle)(RTL_HANDLE_TABLE *, RTL_HANDLE *);
static NTSTATUS (WINAPI *pRtlAllocateAndInitializeSid)(PSID_IDENTIFIER_AUTHORITY,BYTE,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,PSID*);
static NTSTATUS (WINAPI *pRtlFreeSid)(PSID);
static struct _TEB * (WINAPI *pNtCurrentTeb)(void);
static DWORD (WINAPI *pRtlGetThreadErrorMode)(void);
static NTSTATUS (WINAPI *pRtlSetThreadErrorMode)(DWORD, LPDWORD);
static IMAGE_BASE_RELOCATION *(WINAPI *pLdrProcessRelocationBlock)(void*,UINT,USHORT*,INT_PTR);
@@ -111,7 +110,10 @@ static NTSTATUS (WINAPI *pRtlCompressBuffer)(USHORT, const UCHAR*, ULONG, PUCHA
static BOOL (WINAPI *pRtlIsCriticalSectionLocked)(CRITICAL_SECTION *);
static BOOL (WINAPI *pRtlIsCriticalSectionLockedByThread)(CRITICAL_SECTION *);
static NTSTATUS (WINAPI *pRtlInitializeCriticalSectionEx)(CRITICAL_SECTION *, ULONG, ULONG);
static NTSTATUS (WINAPI *pLdrEnumerateLoadedModules)(void *, void *, void *);
static NTSTATUS (WINAPI *pRtlQueryPackageIdentity)(HANDLE, WCHAR*, SIZE_T*, WCHAR*, SIZE_T*, BOOLEAN*);
static NTSTATUS (WINAPI *pLdrRegisterDllNotification)(ULONG, PLDR_DLL_NOTIFICATION_FUNCTION, void *, void **);
static NTSTATUS (WINAPI *pLdrUnregisterDllNotification)(void *);
static HMODULE hkernel32 = 0;
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
@@ -119,6 +121,9 @@ static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
#define LEN 16
static const char* src_src = "This is a test!"; /* 16 bytes long, incl NUL */
static WCHAR ws2_32dllW[] = {'w','s','2','_','3','2','.','d','l','l',0};
static WCHAR wintrustdllW[] = {'w','i','n','t','r','u','s','t','.','d','l','l',0};
static WCHAR crypt32dllW[] = {'c','r','y','p','t','3','2','.','d','l','l',0};
static ULONG src_aligned_block[4];
static ULONG dest_aligned_block[32];
static const char *src = (const char*)src_aligned_block;
@@ -149,7 +154,6 @@ static void InitFunctionPtrs(void)
pRtlFreeHandle = (void *)GetProcAddress(hntdll, "RtlFreeHandle");
pRtlAllocateAndInitializeSid = (void *)GetProcAddress(hntdll, "RtlAllocateAndInitializeSid");
pRtlFreeSid = (void *)GetProcAddress(hntdll, "RtlFreeSid");
pNtCurrentTeb = (void *)GetProcAddress(hntdll, "NtCurrentTeb");
pRtlGetThreadErrorMode = (void *)GetProcAddress(hntdll, "RtlGetThreadErrorMode");
pRtlSetThreadErrorMode = (void *)GetProcAddress(hntdll, "RtlSetThreadErrorMode");
pLdrProcessRelocationBlock = (void *)GetProcAddress(hntdll, "LdrProcessRelocationBlock");
@@ -174,7 +178,10 @@ static void InitFunctionPtrs(void)
pRtlIsCriticalSectionLocked = (void *)GetProcAddress(hntdll, "RtlIsCriticalSectionLocked");
pRtlIsCriticalSectionLockedByThread = (void *)GetProcAddress(hntdll, "RtlIsCriticalSectionLockedByThread");
pRtlInitializeCriticalSectionEx = (void *)GetProcAddress(hntdll, "RtlInitializeCriticalSectionEx");
pLdrEnumerateLoadedModules = (void *)GetProcAddress(hntdll, "LdrEnumerateLoadedModules");
pRtlQueryPackageIdentity = (void *)GetProcAddress(hntdll, "RtlQueryPackageIdentity");
pLdrRegisterDllNotification = (void *)GetProcAddress(hntdll, "LdrRegisterDllNotification");
pLdrUnregisterDllNotification = (void *)GetProcAddress(hntdll, "LdrUnregisterDllNotification");
}
hkernel32 = LoadLibraryA("kernel32.dll");
ok(hkernel32 != 0, "LoadLibrary failed\n");
@@ -382,8 +389,8 @@ static void test_RtlUlonglongByteSwap(void)
result = pRtlUlonglongByteSwap( ((ULONGLONG)0x76543210 << 32) | 0x87654321 );
ok( (((ULONGLONG)0x21436587 << 32) | 0x10325476) == result,
"RtlUlonglongByteSwap(0x7654321087654321) returns 0x%x%08x, expected 0x2143658710325476\n",
(DWORD)(result >> 32), (DWORD)result);
"RtlUlonglongByteSwap(0x7654321087654321) returns 0x%s, expected 0x2143658710325476\n",
wine_dbgstr_longlong(result));
}
@@ -624,11 +631,11 @@ static void test_RtlUniform(void)
seed_bak = seed;
result = pRtlUniform(&seed);
ok(result == expected,
"test: 0x%x%08x RtlUniform(&seed (seed == %x)) returns %x, expected %x\n",
(DWORD)(num >> 32), (DWORD)num, seed_bak, result, expected);
"test: 0x%s RtlUniform(&seed (seed == %x)) returns %x, expected %x\n",
wine_dbgstr_longlong(num), seed_bak, result, expected);
ok(seed == expected,
"test: 0x%x%08x RtlUniform(&seed (seed == %x)) sets seed to %x, expected %x\n",
(DWORD)(num >> 32), (DWORD)num, seed_bak, result, expected);
"test: 0x%s RtlUniform(&seed (seed == %x)) sets seed to %x, expected %x\n",
wine_dbgstr_longlong(num), seed_bak, result, expected);
} /* for */
/*
* Further investigation shows: In the different regions the highest bit
@@ -671,11 +678,11 @@ static void test_RtlUniform(void)
seed_bak = seed;
result = pRtlUniform(&seed);
ok(result == expected,
"test: 0x%x%08x RtlUniform(&seed (seed == %x)) returns %x, expected %x\n",
(DWORD)(num >> 32), (DWORD)num, seed_bak, result, expected);
"test: 0x%s RtlUniform(&seed (seed == %x)) returns %x, expected %x\n",
wine_dbgstr_longlong(num), seed_bak, result, expected);
ok(seed == expected,
"test: 0x%x%08x RtlUniform(&seed (seed == %x)) sets seed to %x, expected %x\n",
(DWORD)(num >> 32), (DWORD)num, seed_bak, result, expected);
"test: 0x%s RtlUniform(&seed (seed == %x)) sets seed to %x, expected %x\n",
wine_dbgstr_longlong(num), seed_bak, result, expected);
} /* for */
/*
* More tests show that RtlUniform does not return 0x7ffffffd for seed values
@@ -919,10 +926,12 @@ static void test_RtlThreadErrorMode(void)
mode, oldmode);
ok(pRtlGetThreadErrorMode() == 0x70,
"RtlGetThreadErrorMode returned 0x%x, expected 0x%x\n", mode, 0x70);
if (!is_wow64 && pNtCurrentTeb)
ok(pNtCurrentTeb()->HardErrorDisabled == 0x70,
if (!is_wow64)
{
ok(NtCurrentTeb()->HardErrorDisabled == 0x70,
"The TEB contains 0x%x, expected 0x%x\n",
pNtCurrentTeb()->HardErrorDisabled, 0x70);
NtCurrentTeb()->HardErrorDisabled, 0x70);
}
status = pRtlSetThreadErrorMode(0, &mode);
ok(status == STATUS_SUCCESS ||
@@ -933,10 +942,12 @@ static void test_RtlThreadErrorMode(void)
mode, 0x70);
ok(pRtlGetThreadErrorMode() == 0,
"RtlGetThreadErrorMode returned 0x%x, expected 0x%x\n", mode, 0);
if (!is_wow64 && pNtCurrentTeb)
ok(pNtCurrentTeb()->HardErrorDisabled == 0,
if (!is_wow64)
{
ok(NtCurrentTeb()->HardErrorDisabled == 0,
"The TEB contains 0x%x, expected 0x%x\n",
pNtCurrentTeb()->HardErrorDisabled, 0);
NtCurrentTeb()->HardErrorDisabled, 0);
}
for (mode = 1; mode; mode <<= 1)
{
@@ -3158,6 +3169,119 @@ static void test_RtlInitializeCriticalSectionEx(void)
RtlDeleteCriticalSection((PRTL_CRITICAL_SECTION)&cs);
}
static void test_RtlLeaveCriticalSection(void)
{
RTL_CRITICAL_SECTION cs;
NTSTATUS status;
if (!pRtlInitializeCriticalSectionEx)
return; /* Skip winxp */
status = RtlInitializeCriticalSection(&cs);
ok(!status, "RtlInitializeCriticalSection failed: %x\n", status);
status = RtlEnterCriticalSection(&cs);
ok(!status, "RtlEnterCriticalSection failed: %x\n", status);
todo_wine
ok(cs.LockCount == -2, "expected LockCount == -2, got %d\n", cs.LockCount);
ok(cs.RecursionCount == 1, "expected RecursionCount == 1, got %d\n", cs.RecursionCount);
ok(cs.OwningThread == ULongToHandle(GetCurrentThreadId()), "unexpected OwningThread\n");
status = RtlLeaveCriticalSection(&cs);
ok(!status, "RtlLeaveCriticalSection failed: %x\n", status);
ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount);
ok(cs.RecursionCount == 0, "expected RecursionCount == 0, got %d\n", cs.RecursionCount);
ok(!cs.OwningThread, "unexpected OwningThread %p\n", cs.OwningThread);
/*
* Trying to leave a section that wasn't acquired modifies RecursionCount to an invalid value,
* but doesn't modify LockCount so that an attempt to enter the section later will work.
*/
status = RtlLeaveCriticalSection(&cs);
ok(!status, "RtlLeaveCriticalSection failed: %x\n", status);
ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount);
ok(cs.RecursionCount == -1, "expected RecursionCount == -1, got %d\n", cs.RecursionCount);
ok(!cs.OwningThread, "unexpected OwningThread %p\n", cs.OwningThread);
/* and again */
status = RtlLeaveCriticalSection(&cs);
ok(!status, "RtlLeaveCriticalSection failed: %x\n", status);
ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount);
ok(cs.RecursionCount == -2, "expected RecursionCount == -2, got %d\n", cs.RecursionCount);
ok(!cs.OwningThread, "unexpected OwningThread %p\n", cs.OwningThread);
/* entering section fixes RecursionCount */
status = RtlEnterCriticalSection(&cs);
ok(!status, "RtlEnterCriticalSection failed: %x\n", status);
todo_wine
ok(cs.LockCount == -2, "expected LockCount == -2, got %d\n", cs.LockCount);
ok(cs.RecursionCount == 1, "expected RecursionCount == 1, got %d\n", cs.RecursionCount);
ok(cs.OwningThread == ULongToHandle(GetCurrentThreadId()), "unexpected OwningThread\n");
status = RtlLeaveCriticalSection(&cs);
ok(!status, "RtlLeaveCriticalSection failed: %x\n", status);
ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount);
ok(cs.RecursionCount == 0, "expected RecursionCount == 0, got %d\n", cs.RecursionCount);
ok(!cs.OwningThread, "unexpected OwningThread %p\n", cs.OwningThread);
status = RtlDeleteCriticalSection(&cs);
ok(!status, "RtlDeleteCriticalSection failed: %x\n", status);
}
struct ldr_enum_context
{
BOOL abort;
BOOL found;
int count;
};
static void WINAPI ldr_enum_callback(LDR_MODULE *module, void *context, BOOLEAN *stop)
{
static const WCHAR ntdllW[] = {'n','t','d','l','l','.','d','l','l',0};
struct ldr_enum_context *ctx = context;
if (!lstrcmpiW(module->BaseDllName.Buffer, ntdllW))
ctx->found = TRUE;
ctx->count++;
*stop = ctx->abort;
}
static void test_LdrEnumerateLoadedModules(void)
{
struct ldr_enum_context ctx;
NTSTATUS status;
if (!pLdrEnumerateLoadedModules)
{
win_skip("LdrEnumerateLoadedModules not available\n");
return;
}
ctx.abort = FALSE;
ctx.found = FALSE;
ctx.count = 0;
status = pLdrEnumerateLoadedModules(NULL, ldr_enum_callback, &ctx);
ok(status == STATUS_SUCCESS, "LdrEnumerateLoadedModules failed with %08x\n", status);
ok(ctx.count > 1, "Expected more than one module, got %d\n", ctx.count);
ok(ctx.found, "Could not find ntdll in list of modules\n");
ctx.abort = TRUE;
ctx.count = 0;
status = pLdrEnumerateLoadedModules(NULL, ldr_enum_callback, &ctx);
ok(status == STATUS_SUCCESS, "LdrEnumerateLoadedModules failed with %08x\n", status);
ok(ctx.count == 1, "Expected exactly one module, got %d\n", ctx.count);
status = pLdrEnumerateLoadedModules((void *)0x1, ldr_enum_callback, (void *)0xdeadbeef);
ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got 0x%08x\n", status);
status = pLdrEnumerateLoadedModules((void *)0xdeadbeef, ldr_enum_callback, (void *)0xdeadbeef);
ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got 0x%08x\n", status);
status = pLdrEnumerateLoadedModules(NULL, NULL, (void *)0xdeadbeef);
ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got 0x%08x\n", status);
}
static void test_RtlQueryPackageIdentity(void)
{
const WCHAR programW[] = {'M','i','c','r','o','s','o','f','t','.','W','i','n','d','o','w','s','.',
@@ -3228,6 +3352,248 @@ done:
CoUninitialize();
}
static DWORD (CALLBACK *orig_entry)(HMODULE,DWORD,LPVOID);
static DWORD *dll_main_data;
static inline void *get_rva( HMODULE module, DWORD va )
{
return (void *)((char *)module + va);
}
static void CALLBACK ldr_notify_callback1(ULONG reason, LDR_DLL_NOTIFICATION_DATA *data, void *context)
{
const IMAGE_IMPORT_DESCRIPTOR *imports;
const IMAGE_THUNK_DATA *import_list;
IMAGE_THUNK_DATA *thunk_list;
DWORD *calls = context;
LIST_ENTRY *mark;
LDR_MODULE *mod;
ULONG size;
int i, j;
*calls <<= 4;
*calls |= reason;
ok(data->Loaded.Flags == 0, "Expected flags 0, got %x\n", data->Loaded.Flags);
ok(!lstrcmpiW(data->Loaded.BaseDllName->Buffer, ws2_32dllW), "Expected ws2_32.dll, got %s\n",
wine_dbgstr_w(data->Loaded.BaseDllName->Buffer));
ok(!!data->Loaded.DllBase, "Expected non zero base address\n");
ok(data->Loaded.SizeOfImage, "Expected non zero image size\n");
/* expect module to be last module listed in LdrData load order list */
mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
mod = CONTAINING_RECORD(mark->Blink, LDR_MODULE, InMemoryOrderModuleList);
ok(mod->BaseAddress == data->Loaded.DllBase, "Expected base address %p, got %p\n",
data->Loaded.DllBase, mod->BaseAddress);
ok(!lstrcmpiW(mod->BaseDllName.Buffer, ws2_32dllW), "Expected ws2_32.dll, got %s\n",
wine_dbgstr_w(mod->BaseDllName.Buffer));
/* show that imports have already been resolved */
imports = RtlImageDirectoryEntryToData(data->Loaded.DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size);
ok(!!imports, "Expected dll to have imports\n");
for (i = 0; imports[i].Name; i++)
{
thunk_list = get_rva(data->Loaded.DllBase, (DWORD)imports[i].FirstThunk);
if (imports[i].OriginalFirstThunk)
import_list = get_rva(data->Loaded.DllBase, (DWORD)imports[i].OriginalFirstThunk);
else
import_list = thunk_list;
for (j = 0; import_list[j].u1.Ordinal; j++)
{
ok(thunk_list[j].u1.AddressOfData > data->Loaded.SizeOfImage,
"Import has not been resolved: %p\n", (void*)thunk_list[j].u1.Function);
}
}
}
static void CALLBACK ldr_notify_callback2(ULONG reason, LDR_DLL_NOTIFICATION_DATA *data, void *context)
{
DWORD *calls = context;
*calls <<= 4;
*calls |= reason + 2;
}
static BOOL WINAPI fake_dll_main(HINSTANCE instance, DWORD reason, void* reserved)
{
if (reason == DLL_PROCESS_ATTACH)
{
*dll_main_data <<= 4;
*dll_main_data |= 3;
}
else if (reason == DLL_PROCESS_DETACH)
{
*dll_main_data <<= 4;
*dll_main_data |= 4;
}
return orig_entry(instance, reason, reserved);
}
static void CALLBACK ldr_notify_callback_dll_main(ULONG reason, LDR_DLL_NOTIFICATION_DATA *data, void *context)
{
DWORD *calls = context;
LIST_ENTRY *mark;
LDR_MODULE *mod;
*calls <<= 4;
*calls |= reason;
if (reason != LDR_DLL_NOTIFICATION_REASON_LOADED)
return;
mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
mod = CONTAINING_RECORD(mark->Blink, LDR_MODULE, InMemoryOrderModuleList);
ok(mod->BaseAddress == data->Loaded.DllBase, "Expected base address %p, got %p\n",
data->Loaded.DllBase, mod->BaseAddress);
if (mod->BaseAddress != data->Loaded.DllBase)
return;
orig_entry = mod->EntryPoint;
mod->EntryPoint = fake_dll_main;
dll_main_data = calls;
}
static BOOL WINAPI fake_dll_main_fail(HINSTANCE instance, DWORD reason, void* reserved)
{
if (reason == DLL_PROCESS_ATTACH)
{
*dll_main_data <<= 4;
*dll_main_data |= 3;
}
else if (reason == DLL_PROCESS_DETACH)
{
*dll_main_data <<= 4;
*dll_main_data |= 4;
}
return FALSE;
}
static void CALLBACK ldr_notify_callback_fail(ULONG reason, LDR_DLL_NOTIFICATION_DATA *data, void *context)
{
DWORD *calls = context;
LIST_ENTRY *mark;
LDR_MODULE *mod;
*calls <<= 4;
*calls |= reason;
if (reason != LDR_DLL_NOTIFICATION_REASON_LOADED)
return;
mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
mod = CONTAINING_RECORD(mark->Blink, LDR_MODULE, InMemoryOrderModuleList);
ok(mod->BaseAddress == data->Loaded.DllBase, "Expected base address %p, got %p\n",
data->Loaded.DllBase, mod->BaseAddress);
if (mod->BaseAddress != data->Loaded.DllBase)
return;
orig_entry = mod->EntryPoint;
mod->EntryPoint = fake_dll_main_fail;
dll_main_data = calls;
}
static void CALLBACK ldr_notify_callback_imports(ULONG reason, LDR_DLL_NOTIFICATION_DATA *data, void *context)
{
DWORD *calls = context;
if (reason != LDR_DLL_NOTIFICATION_REASON_LOADED)
return;
if (!lstrcmpiW(data->Loaded.BaseDllName->Buffer, crypt32dllW))
{
*calls <<= 4;
*calls |= 1;
}
if (!lstrcmpiW(data->Loaded.BaseDllName->Buffer, wintrustdllW))
{
*calls <<= 4;
*calls |= 2;
}
}
static void test_LdrRegisterDllNotification(void)
{
void *cookie, *cookie2;
NTSTATUS status;
HMODULE mod;
DWORD calls;
if (!pLdrRegisterDllNotification || !pLdrUnregisterDllNotification)
{
win_skip("Ldr(Un)RegisterDllNotification not available\n");
return;
}
/* generic test */
status = pLdrRegisterDllNotification(0, ldr_notify_callback1, &calls, &cookie);
ok(!status, "Expected STATUS_SUCCESS, got %08x\n", status);
calls = 0;
mod = LoadLibraryW(ws2_32dllW);
ok(!!mod, "Failed to load library: %d\n", GetLastError());
ok(calls == LDR_DLL_NOTIFICATION_REASON_LOADED, "Expected LDR_DLL_NOTIFICATION_REASON_LOADED, got %x\n", calls);
calls = 0;
FreeLibrary(mod);
ok(calls == LDR_DLL_NOTIFICATION_REASON_UNLOADED, "Expected LDR_DLL_NOTIFICATION_REASON_UNLOADED, got %x\n", calls);
/* test order of callbacks */
status = pLdrRegisterDllNotification(0, ldr_notify_callback2, &calls, &cookie2);
ok(!status, "Expected STATUS_SUCCESS, got %08x\n", status);
calls = 0;
mod = LoadLibraryW(ws2_32dllW);
ok(!!mod, "Failed to load library: %d\n", GetLastError());
ok(calls == 0x13, "Expected order 0x13, got %x\n", calls);
calls = 0;
FreeLibrary(mod);
ok(calls == 0x24, "Expected order 0x24, got %x\n", calls);
pLdrUnregisterDllNotification(cookie2);
pLdrUnregisterDllNotification(cookie);
/* test dll main order */
status = pLdrRegisterDllNotification(0, ldr_notify_callback_dll_main, &calls, &cookie);
ok(!status, "Expected STATUS_SUCCESS, got %08x\n", status);
calls = 0;
mod = LoadLibraryW(ws2_32dllW);
ok(!!mod, "Failed to load library: %d\n", GetLastError());
ok(calls == 0x13, "Expected order 0x13, got %x\n", calls);
calls = 0;
FreeLibrary(mod);
ok(calls == 0x42, "Expected order 0x42, got %x\n", calls);
pLdrUnregisterDllNotification(cookie);
/* test dll main order */
status = pLdrRegisterDllNotification(0, ldr_notify_callback_fail, &calls, &cookie);
ok(!status, "Expected STATUS_SUCCESS, got %08x\n", status);
calls = 0;
mod = LoadLibraryW(ws2_32dllW);
ok(!mod, "Expected library to fail loading\n");
ok(calls == 0x1342, "Expected order 0x1342, got %x\n", calls);
pLdrUnregisterDllNotification(cookie);
/* test dll with dependencies */
status = pLdrRegisterDllNotification(0, ldr_notify_callback_imports, &calls, &cookie);
ok(!status, "Expected STATUS_SUCCESS, got %08x\n", status);
calls = 0;
mod = LoadLibraryW(wintrustdllW);
ok(!!mod, "Failed to load library: %d\n", GetLastError());
ok(calls == 0x12, "Expected order 0x12, got %x\n", calls);
FreeLibrary(mod);
pLdrUnregisterDllNotification(cookie);
}
START_TEST(rtl)
{
InitFunctionPtrs();
@@ -3264,5 +3630,8 @@ START_TEST(rtl)
test_RtlDecompressBuffer();
test_RtlIsCriticalSectionLocked();
test_RtlInitializeCriticalSectionEx();
test_RtlLeaveCriticalSection();
test_LdrEnumerateLoadedModules();
test_RtlQueryPackageIdentity();
test_LdrRegisterDllNotification();
}
+8 -8
View File
@@ -425,15 +425,15 @@ static void test_RtlFindMostSignificantBit(void)
ulLong <<= i;
cPos = pRtlFindMostSignificantBit(ulLong);
ok (cPos == i, "didn't find MSB 0x%x%08x %d %d\n",
(DWORD)(ulLong >> 32), (DWORD)ulLong, i, cPos);
ok (cPos == i, "didn't find MSB 0x%s %d %d\n",
wine_dbgstr_longlong(ulLong ), i, cPos);
/* Set all bits lower than bit i */
ulLong = ((ulLong - 1) << 1) | 1;
cPos = pRtlFindMostSignificantBit(ulLong);
ok (cPos == i, "didn't find MSB 0x%x%08x %d %d\n",
(DWORD)(ulLong >> 32), (DWORD)ulLong, i, cPos);
ok (cPos == i, "didn't find MSB 0x%s %d %d\n",
wine_dbgstr_longlong(ulLong ), i, cPos);
}
cPos = pRtlFindMostSignificantBit(0);
ok (cPos == -1, "found bit when not set\n");
@@ -453,14 +453,14 @@ static void test_RtlFindLeastSignificantBit(void)
ulLong = (ULONGLONG)1 << i;
cPos = pRtlFindLeastSignificantBit(ulLong);
ok (cPos == i, "didn't find LSB 0x%x%08x %d %d\n",
(DWORD)(ulLong >> 32), (DWORD)ulLong, i, cPos);
ok (cPos == i, "didn't find LSB 0x%s %d %d\n",
wine_dbgstr_longlong(ulLong ), i, cPos);
ulLong = ~((ULONGLONG)0) << i;
cPos = pRtlFindLeastSignificantBit(ulLong);
ok (cPos == i, "didn't find LSB 0x%x%08x %d %d\n",
(DWORD)(ulLong >> 32), (DWORD)ulLong, i, cPos);
ok (cPos == i, "didn't find LSB 0x%s %d %d\n",
wine_dbgstr_longlong(ulLong ), i, cPos);
}
cPos = pRtlFindLeastSignificantBit(0);
ok (cPos == -1, "found bit when not set\n");
+36 -39
View File
@@ -600,22 +600,21 @@ static void one_i64toa_test(int test_num, const ulonglong2str_t *ulonglong2str)
dest_str[LARGE_STRI_BUFFER_LENGTH] = '\0';
result = p_i64toa(ulonglong2str->value, dest_str, ulonglong2str->base);
ok(result == dest_str,
"(test %d): _i64toa(%08x%08x, [out], %d) has result %p, expected: %p\n",
test_num, (DWORD)(ulonglong2str->value >> 32), (DWORD)ulonglong2str->value,
ulonglong2str->base, result, dest_str);
"(test %d): _i64toa(%s, [out], %d) has result %p, expected: %p\n",
test_num, wine_dbgstr_longlong(ulonglong2str->value), ulonglong2str->base, result, dest_str);
if (ulonglong2str->mask & 0x04) {
if (memcmp(dest_str, ulonglong2str->Buffer, LARGE_STRI_BUFFER_LENGTH) != 0) {
if (memcmp(dest_str, ulonglong2str[1].Buffer, LARGE_STRI_BUFFER_LENGTH) != 0) {
ok(memcmp(dest_str, ulonglong2str->Buffer, LARGE_STRI_BUFFER_LENGTH) == 0,
"(test %d): _i64toa(%08x%08x, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
test_num, (DWORD)(ulonglong2str->value >> 32), (DWORD)ulonglong2str->value,
"(test %d): _i64toa(%s, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
test_num, wine_dbgstr_longlong(ulonglong2str->value),
ulonglong2str->base, dest_str, ulonglong2str->Buffer);
} /* if */
} /* if */
} else {
ok(memcmp(dest_str, ulonglong2str->Buffer, LARGE_STRI_BUFFER_LENGTH) == 0,
"(test %d): _i64toa(%08x%08x, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
test_num, (DWORD)(ulonglong2str->value >> 32), (DWORD)ulonglong2str->value,
"(test %d): _i64toa(%s, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
test_num, wine_dbgstr_longlong(ulonglong2str->value),
ulonglong2str->base, dest_str, ulonglong2str->Buffer);
} /* if */
}
@@ -630,12 +629,11 @@ static void one_ui64toa_test(int test_num, const ulonglong2str_t *ulonglong2str)
dest_str[LARGE_STRI_BUFFER_LENGTH] = '\0';
result = p_ui64toa(ulonglong2str->value, dest_str, ulonglong2str->base);
ok(result == dest_str,
"(test %d): _ui64toa(%08x%08x, [out], %d) has result %p, expected: %p\n",
test_num, (DWORD)(ulonglong2str->value >> 32), (DWORD)ulonglong2str->value,
ulonglong2str->base, result, dest_str);
"(test %d): _ui64toa(%s, [out], %d) has result %p, expected: %p\n",
test_num, wine_dbgstr_longlong(ulonglong2str->value), ulonglong2str->base, result, dest_str);
ok(memcmp(dest_str, ulonglong2str->Buffer, LARGE_STRI_BUFFER_LENGTH) == 0,
"(test %d): _ui64toa(%08x%08x, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
test_num, (DWORD)(ulonglong2str->value >> 32), (DWORD)ulonglong2str->value,
"(test %d): _ui64toa(%s, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
test_num, wine_dbgstr_longlong(ulonglong2str->value),
ulonglong2str->base, dest_str, ulonglong2str->Buffer);
}
@@ -682,9 +680,8 @@ static void one_i64tow_test(int test_num, const ulonglong2str_t *ulonglong2str)
result = p_i64tow(ulonglong2str->value, dest_wstr, ulonglong2str->base);
pRtlUnicodeStringToAnsiString(&ansi_str, &unicode_string, 1);
ok(result == dest_wstr,
"(test %d): _i64tow(0x%x%08x, [out], %d) has result %p, expected: %p\n",
test_num, (DWORD)(ulonglong2str->value >> 32), (DWORD)ulonglong2str->value,
ulonglong2str->base, result, dest_wstr);
"(test %d): _i64tow(0x%s, [out], %d) has result %p, expected: %p\n",
test_num, wine_dbgstr_longlong(ulonglong2str->value), ulonglong2str->base, result, dest_wstr);
if (ulonglong2str->mask & 0x04) {
if (memcmp(dest_wstr, expected_wstr, LARGE_STRI_BUFFER_LENGTH * sizeof(WCHAR)) != 0) {
for (pos = 0; pos < LARGE_STRI_BUFFER_LENGTH; pos++) {
@@ -693,15 +690,15 @@ static void one_i64tow_test(int test_num, const ulonglong2str_t *ulonglong2str)
expected_wstr[LARGE_STRI_BUFFER_LENGTH] = '\0';
if (memcmp(dest_wstr, expected_wstr, LARGE_STRI_BUFFER_LENGTH * sizeof(WCHAR)) != 0) {
ok(memcmp(dest_wstr, expected_wstr, LARGE_STRI_BUFFER_LENGTH * sizeof(WCHAR)) == 0,
"(test %d): _i64tow(0x%x%08x, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
test_num, (DWORD)(ulonglong2str->value >> 32), (DWORD)ulonglong2str->value,
"(test %d): _i64tow(0x%s, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
test_num, wine_dbgstr_longlong(ulonglong2str->value),
ulonglong2str->base, ansi_str.Buffer, ulonglong2str->Buffer);
} /* if */
} /* if */
} else {
ok(memcmp(dest_wstr, expected_wstr, LARGE_STRI_BUFFER_LENGTH * sizeof(WCHAR)) == 0,
"(test %d): _i64tow(0x%x%08x, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
test_num, (DWORD)(ulonglong2str->value >> 32), (DWORD)ulonglong2str->value,
"(test %d): _i64tow(0x%s, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
test_num, wine_dbgstr_longlong(ulonglong2str->value),
ulonglong2str->base, ansi_str.Buffer, ulonglong2str->Buffer);
} /* if */
pRtlFreeAnsiString(&ansi_str);
@@ -733,12 +730,12 @@ static void one_ui64tow_test(int test_num, const ulonglong2str_t *ulonglong2str)
result = p_ui64tow(ulonglong2str->value, dest_wstr, ulonglong2str->base);
pRtlUnicodeStringToAnsiString(&ansi_str, &unicode_string, 1);
ok(result == dest_wstr,
"(test %d): _ui64tow(0x%x%08x, [out], %d) has result %p, expected: %p\n",
test_num, (DWORD)(ulonglong2str->value >> 32), (DWORD)ulonglong2str->value,
"(test %d): _ui64tow(0x%s, [out], %d) has result %p, expected: %p\n",
test_num, wine_dbgstr_longlong(ulonglong2str->value),
ulonglong2str->base, result, dest_wstr);
ok(memcmp(dest_wstr, expected_wstr, LARGE_STRI_BUFFER_LENGTH * sizeof(WCHAR)) == 0,
"(test %d): _ui64tow(0x%x%08x, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
test_num, (DWORD)(ulonglong2str->value >> 32), (DWORD)ulonglong2str->value,
"(test %d): _ui64tow(0x%s, [out], %d) assigns string \"%s\", expected: \"%s\"\n",
test_num, wine_dbgstr_longlong(ulonglong2str->value),
ulonglong2str->base, ansi_str.Buffer, ulonglong2str->Buffer);
pRtlFreeAnsiString(&ansi_str);
}
@@ -764,8 +761,8 @@ static void test_ulonglongtow(void)
/* Crashes on XP and W2K3 */
result = p_i64tow(ulonglong2str[0].value, NULL, 10);
ok(result == NULL,
"(test d): _i64tow(0x%x%08x, NULL, 10) has result %p, expected: NULL\n",
(DWORD)(ulonglong2str[0].value >> 32), (DWORD)ulonglong2str[0].value, result);
"(test d): _i64tow(0x%s, NULL, 10) has result %p, expected: NULL\n",
wine_dbgstr_longlong(ulonglong2str[0].value), result);
}
if (p_ui64tow) {
@@ -773,8 +770,8 @@ static void test_ulonglongtow(void)
/* Crashes on XP and W2K3 */
result = p_ui64tow(ulonglong2str[0].value, NULL, 10);
ok(result == NULL,
"(test e): _ui64tow(0x%x%08x, NULL, 10) has result %p, expected: NULL\n",
(DWORD)(ulonglong2str[0].value >> 32), (DWORD)ulonglong2str[0].value, result);
"(test e): _ui64tow(0x%s, NULL, 10) has result %p, expected: NULL\n",
wine_dbgstr_longlong(ulonglong2str[0].value), result);
}
} /* if */
}
@@ -1085,14 +1082,14 @@ static void test_atoi64(void)
ok(result == str2longlong[test_num].value ||
(result == ((str2longlong[test_num].overflow == -1) ?
ULL(0x80000000,0x00000000) : ULL(0x7fffffff,0xffffffff))),
"(test %d): call failed: _atoi64(\"%s\") has result 0x%x%08x, expected: 0x%x%08x\n",
test_num, str2longlong[test_num].str, (DWORD)(result >> 32), (DWORD)result,
(DWORD)(str2longlong[test_num].value >> 32), (DWORD)str2longlong[test_num].value);
"(test %d): call failed: _atoi64(\"%s\") has result 0x%s, expected: 0x%s\n",
test_num, str2longlong[test_num].str, wine_dbgstr_longlong(result),
wine_dbgstr_longlong(str2longlong[test_num].value));
else
ok(result == str2longlong[test_num].value,
"(test %d): call failed: _atoi64(\"%s\") has result 0x%x%08x, expected: 0x%x%08x\n",
test_num, str2longlong[test_num].str, (DWORD)(result >> 32), (DWORD)result,
(DWORD)(str2longlong[test_num].value >> 32), (DWORD)str2longlong[test_num].value);
"(test %d): call failed: _atoi64(\"%s\") has result 0x%s, expected: 0x%s\n",
test_num, str2longlong[test_num].str, wine_dbgstr_longlong(result),
wine_dbgstr_longlong(str2longlong[test_num].value));
}
}
@@ -1110,14 +1107,14 @@ static void test_wtoi64(void)
ok(result == str2longlong[test_num].value ||
(result == ((str2longlong[test_num].overflow == -1) ?
ULL(0x80000000,0x00000000) : ULL(0x7fffffff,0xffffffff))),
"(test %d): call failed: _atoi64(\"%s\") has result 0x%x%08x, expected: 0x%x%08x\n",
test_num, str2longlong[test_num].str, (DWORD)(result >> 32), (DWORD)result,
(DWORD)(str2longlong[test_num].value >> 32), (DWORD)str2longlong[test_num].value);
"(test %d): call failed: _atoi64(\"%s\") has result 0x%s, expected: 0x%s\n",
test_num, str2longlong[test_num].str, wine_dbgstr_longlong(result),
wine_dbgstr_longlong(str2longlong[test_num].value));
else
ok(result == str2longlong[test_num].value,
"(test %d): call failed: _atoi64(\"%s\") has result 0x%x%08x, expected: 0x%x%08x\n",
test_num, str2longlong[test_num].str, (DWORD)(result >> 32), (DWORD)result,
(DWORD)(str2longlong[test_num].value >> 32), (DWORD)str2longlong[test_num].value);
"(test %d): call failed: _atoi64(\"%s\") has result 0x%s, expected: 0x%s\n",
test_num, str2longlong[test_num].str, wine_dbgstr_longlong(result),
wine_dbgstr_longlong(str2longlong[test_num].value));
pRtlFreeUnicodeString(&uni);
}
}
@@ -17,6 +17,7 @@ extern void func_om(void);
extern void func_path(void);
extern void func_pipe(void);
extern void func_port(void);
extern void func_process(void);
extern void func_reg(void);
extern void func_rtl(void);
extern void func_rtlbitmap(void);
@@ -42,6 +43,7 @@ const struct test winetest_testlist[] =
{ "path", func_path },
{ "pipe", func_pipe },
{ "port", func_port },
{ "process", func_process },
{ "reg", func_reg },
{ "rtl", func_rtl },
{ "rtlbitmap", func_rtlbitmap },
File diff suppressed because it is too large Load Diff
+121
View File
@@ -18,14 +18,88 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define NONAMELESSUNION
#include "ntdll_test.h"
/* FIXME: Inspect */
typedef struct _KSYSTEM_TIME {
ULONG LowPart;
LONG High1Time;
LONG High2Time;
} KSYSTEM_TIME, *PKSYSTEM_TIME;
typedef enum _NT_PRODUCT_TYPE {
NtProductWinNt = 1,
NtProductLanManNt,
NtProductServer
} NT_PRODUCT_TYPE, *PNT_PRODUCT_TYPE;
#define PROCESSOR_FEATURE_MAX 64
typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE
{
StandardDesign,
NEC98x86,
EndAlternatives
} ALTERNATIVE_ARCHITECTURE_TYPE;
#define MAX_WOW64_SHARED_ENTRIES 16
typedef struct _KUSER_SHARED_DATA {
ULONG TickCountLowDeprecated;
ULONG TickCountMultiplier;
volatile KSYSTEM_TIME InterruptTime;
volatile KSYSTEM_TIME SystemTime;
volatile KSYSTEM_TIME TimeZoneBias;
USHORT ImageNumberLow;
USHORT ImageNumberHigh;
WCHAR NtSystemRoot[260];
ULONG MaxStackTraceDepth;
ULONG CryptoExponent;
ULONG TimeZoneId;
ULONG LargePageMinimum;
ULONG Reserved2[7];
NT_PRODUCT_TYPE NtProductType;
BOOLEAN ProductTypeIsValid;
ULONG NtMajorVersion;
ULONG NtMinorVersion;
BOOLEAN ProcessorFeatures[PROCESSOR_FEATURE_MAX];
ULONG Reserved1;
ULONG Reserved3;
volatile ULONG TimeSlip;
ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture;
LARGE_INTEGER SystemExpirationDate;
ULONG SuiteMask;
BOOLEAN KdDebuggerEnabled;
UCHAR NXSupportPolicy;
volatile ULONG ActiveConsoleId;
volatile ULONG DismountCount;
ULONG ComPlusPackage;
ULONG LastSystemRITEventTickCount;
ULONG NumberOfPhysicalPages;
BOOLEAN SafeBootMode;
ULONG TraceLogging;
ULONGLONG TestRetInstruction;
ULONG SystemCall;
ULONG SystemCallReturn;
ULONGLONG SystemCallPad[3];
union {
volatile KSYSTEM_TIME TickCount;
volatile ULONG64 TickCountQuad;
} DUMMYUNIONNAME;
ULONG Cookie;
ULONG Wow64SharedInformation[MAX_WOW64_SHARED_ENTRIES];
} KSHARED_USER_DATA, *PKSHARED_USER_DATA;
#define TICKSPERSEC 10000000
#define TICKSPERMSEC 10000
#define SECSPERDAY 86400
static VOID (WINAPI *pRtlTimeToTimeFields)( const LARGE_INTEGER *liTime, PTIME_FIELDS TimeFields) ;
static VOID (WINAPI *pRtlTimeFieldsToTime)( PTIME_FIELDS TimeFields, PLARGE_INTEGER Time) ;
static NTSTATUS (WINAPI *pNtQueryPerformanceCounter)( LARGE_INTEGER *counter, LARGE_INTEGER *frequency );
static ULONG (WINAPI *pNtGetTickCount)(void);
static const int MonthLengths[2][12] =
{
@@ -94,13 +168,60 @@ static void test_pRtlTimeToTimeFields(void)
}
}
static void test_NtQueryPerformanceCounter(void)
{
LARGE_INTEGER counter, frequency;
NTSTATUS status;
status = pNtQueryPerformanceCounter(NULL, NULL);
ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
status = pNtQueryPerformanceCounter(NULL, &frequency);
ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
status = pNtQueryPerformanceCounter(&counter, (void *)0xdeadbee0);
ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
status = pNtQueryPerformanceCounter((void *)0xdeadbee0, &frequency);
ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
status = pNtQueryPerformanceCounter(&counter, NULL);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
status = pNtQueryPerformanceCounter(&counter, &frequency);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
}
static void test_NtGetTickCount(void)
{
#ifndef _WIN64
KSHARED_USER_DATA *user_shared_data = (void *)0x7ffe0000;
LONG diff;
int i;
if (!pNtGetTickCount)
{
win_skip("NtGetTickCount is not available\n");
return;
}
for (i = 0; i < 5; ++i)
{
diff = (user_shared_data->u.TickCountQuad * user_shared_data->TickCountMultiplier) >> 24;
diff = pNtGetTickCount() - diff;
ok(diff < 32, "NtGetTickCount - TickCountQuad too high, expected < 32 got %d\n", diff);
Sleep(50);
}
#endif
}
START_TEST(time)
{
HMODULE mod = GetModuleHandleA("ntdll.dll");
pRtlTimeToTimeFields = (void *)GetProcAddress(mod,"RtlTimeToTimeFields");
pRtlTimeFieldsToTime = (void *)GetProcAddress(mod,"RtlTimeFieldsToTime");
pNtQueryPerformanceCounter = (void *)GetProcAddress(mod, "NtQueryPerformanceCounter");
pNtGetTickCount = (void *)GetProcAddress(mod,"NtGetTickCount");
if (pRtlTimeToTimeFields && pRtlTimeFieldsToTime)
test_pRtlTimeToTimeFields();
else
win_skip("Required time conversion functions are not available\n");
test_NtQueryPerformanceCounter();
test_NtGetTickCount();
}