Author: akhaldi
Date: Tue Mar 10 10:10:04 2015
New Revision: 66658
URL:
http://svn.reactos.org/svn/reactos?rev=66658&view=rev
Log:
[NTDLL_WINETEST] Sync with Wine Staging 1.7.37. CORE-9246
Modified:
trunk/rostests/winetests/ntdll/directory.c
trunk/rostests/winetests/ntdll/exception.c
trunk/rostests/winetests/ntdll/file.c
trunk/rostests/winetests/ntdll/info.c
trunk/rostests/winetests/ntdll/om.c
trunk/rostests/winetests/ntdll/reg.c
trunk/rostests/winetests/ntdll/rtl.c
trunk/rostests/winetests/ntdll/string.c
Modified: trunk/rostests/winetests/ntdll/directory.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ntdll/directory…
==============================================================================
--- trunk/rostests/winetests/ntdll/directory.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/ntdll/directory.c [iso-8859-1] Tue Mar 10 10:10:04 2015
@@ -51,7 +51,6 @@
/* The attribute sets to test */
static struct testfile_s {
- BOOL todo; /* set if it doesn't work on wine yet */
BOOL attr_done; /* set if attributes were tested for this file already */
const DWORD attr; /* desired attribute */
const char *name; /* filename to use */
@@ -60,13 +59,13 @@
int nfound; /* How many were found (expect 1) */
WCHAR nameW[20]; /* unicode version of name (filled in later) */
} testfiles[] = {
- { 0, 0, FILE_ATTRIBUTE_NORMAL, "n.tmp", NULL, "normal" },
- { 1, 0, FILE_ATTRIBUTE_HIDDEN, "h.tmp", NULL, "hidden" },
- { 1, 0, FILE_ATTRIBUTE_SYSTEM, "s.tmp", NULL, "system" },
- { 0, 0, FILE_ATTRIBUTE_DIRECTORY, "d.tmp", NULL, "directory" },
- { 0, 0, FILE_ATTRIBUTE_DIRECTORY, ".", NULL, ". directory"
},
- { 0, 0, FILE_ATTRIBUTE_DIRECTORY, "..", NULL, ".. directory"
},
- { 0, 0, 0, NULL }
+ { 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 }
};
static const int max_test_dir_size = 20; /* size of above plus some for .. etc */
@@ -147,12 +146,7 @@
if (namelen != len || memcmp(nameW, testfiles[i].nameW, len*sizeof(WCHAR)))
continue;
if (!testfiles[i].attr_done) {
- if (testfiles[i].todo) {
- todo_wine
- 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);
- } else {
- 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", testfiles[i].name,
testfiles[i].description, testfiles[i].attr, attrib);
testfiles[i].attr_done = TRUE;
}
testfiles[i].nfound++;
Modified: trunk/rostests/winetests/ntdll/exception.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ntdll/exception…
==============================================================================
--- trunk/rostests/winetests/ntdll/exception.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/ntdll/exception.c [iso-8859-1] Tue Mar 10 10:10:04 2015
@@ -46,11 +46,14 @@
static PVOID (WINAPI *pRtlUnwind)(PVOID, PVOID, PEXCEPTION_RECORD, PVOID);
static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG first,
PVECTORED_EXCEPTION_HANDLER func);
static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID handler);
+static PVOID (WINAPI *pRtlAddVectoredContinueHandler)(ULONG first,
PVECTORED_EXCEPTION_HANDLER func);
+static ULONG (WINAPI *pRtlRemoveVectoredContinueHandler)(PVOID handler);
static NTSTATUS (WINAPI *pNtReadVirtualMemory)(HANDLE, const void*, void*, SIZE_T,
SIZE_T*);
static NTSTATUS (WINAPI *pNtTerminateProcess)(HANDLE handle, LONG exit_code);
static NTSTATUS (WINAPI *pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID,
ULONG, PULONG);
static NTSTATUS (WINAPI *pNtSetInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID,
ULONG);
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
+static NTSTATUS (WINAPI *pNtClose)(HANDLE);
#if defined(__x86_64__)
static BOOLEAN (CDECL *pRtlAddFunctionTable)(RUNTIME_FUNCTION*, DWORD, DWORD64);
@@ -936,6 +939,16 @@
/* here we handle exception */
}
}
+ else if (stage == 7 || stage == 8)
+ {
+ ok(de.u.Exception.ExceptionRecord.ExceptionCode ==
EXCEPTION_INVALID_HANDLE,
+ "unexpected exception code %08x, expected %08x\n",
de.u.Exception.ExceptionRecord.ExceptionCode,
+ EXCEPTION_INVALID_HANDLE);
+ ok(de.u.Exception.ExceptionRecord.NumberParameters == 0,
+ "unexpected number of parameters %d, expected 0\n",
de.u.Exception.ExceptionRecord.NumberParameters);
+
+ if (stage == 8) continuestatus = DBG_EXCEPTION_NOT_HANDLED;
+ }
else
ok(FALSE, "unexpected stage %x\n", stage);
@@ -1695,6 +1708,7 @@
#endif /* __x86_64__ */
+#if defined(__i386__) || defined(__x86_64__)
static DWORD outputdebugstring_exceptions;
static LONG CALLBACK outputdebugstring_vectored_handler(EXCEPTION_POINTERS
*ExceptionInfo)
@@ -1713,7 +1727,7 @@
return EXCEPTION_CONTINUE_SEARCH;
}
-static void test_outputdebugstring(DWORD numexc, BOOL todo)
+static void test_outputdebugstring(DWORD numexc)
{
PVOID vectored_handler;
@@ -1728,13 +1742,8 @@
outputdebugstring_exceptions = 0;
OutputDebugStringA("Hello World");
- if (todo)
- todo_wine
- ok(outputdebugstring_exceptions == numexc, "OutputDebugStringA generated %d
exceptions, expected %d\n",
- outputdebugstring_exceptions, numexc);
- else
- ok(outputdebugstring_exceptions == numexc, "OutputDebugStringA generated %d
exceptions, expected %d\n",
- outputdebugstring_exceptions, numexc);
+ ok(outputdebugstring_exceptions == numexc, "OutputDebugStringA generated %d
exceptions, expected %d\n",
+ outputdebugstring_exceptions, numexc);
pRtlRemoveVectoredExceptionHandler(vectored_handler);
}
@@ -1788,6 +1797,91 @@
pRtlRemoveVectoredExceptionHandler(vectored_handler);
}
+static DWORD invalid_handle_exceptions;
+
+static LONG CALLBACK invalid_handle_vectored_handler(EXCEPTION_POINTERS *ExceptionInfo)
+{
+ PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord;
+ trace("vect. handler %08x addr:%p\n", rec->ExceptionCode,
rec->ExceptionAddress);
+
+ ok(rec->ExceptionCode == EXCEPTION_INVALID_HANDLE, "ExceptionCode is %08x
instead of %08x\n",
+ rec->ExceptionCode, EXCEPTION_INVALID_HANDLE);
+ ok(rec->NumberParameters == 0, "ExceptionParameters is %d instead of
0\n", rec->NumberParameters);
+
+ invalid_handle_exceptions++;
+ return (rec->ExceptionCode == EXCEPTION_INVALID_HANDLE) ?
EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH;
+}
+
+static void test_closehandle(DWORD numexc)
+{
+ PVOID vectored_handler;
+ NTSTATUS status;
+ DWORD res;
+
+ if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler ||
!pRtlRaiseException)
+ {
+ skip("RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler or
RtlRaiseException not found\n");
+ return;
+ }
+
+ vectored_handler = pRtlAddVectoredExceptionHandler(TRUE,
&invalid_handle_vectored_handler);
+ ok(vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n");
+
+ invalid_handle_exceptions = 0;
+ res = CloseHandle((HANDLE)0xdeadbeef);
+ ok(!res, "CloseHandle(0xdeadbeef) unexpectedly succeeded\n");
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error code %d instead of
%d",
+ GetLastError(), ERROR_INVALID_HANDLE);
+ ok(invalid_handle_exceptions == numexc, "CloseHandle generated %d exceptions,
expected %d\n",
+ invalid_handle_exceptions, numexc);
+
+ invalid_handle_exceptions = 0;
+ status = pNtClose((HANDLE)0xdeadbeef);
+ ok(status == STATUS_INVALID_HANDLE, "NtClose(0xdeadbeef) returned status
%08x\n", status);
+ ok(invalid_handle_exceptions == numexc, "NtClose generated %d exceptions,
expected %d\n",
+ invalid_handle_exceptions, numexc);
+
+ pRtlRemoveVectoredExceptionHandler(vectored_handler);
+}
+
+static void test_vectored_continue_handler(void)
+{
+ PVOID handler1, handler2;
+ ULONG ret;
+
+ if (!pRtlAddVectoredContinueHandler || !pRtlRemoveVectoredContinueHandler)
+ {
+ skip("RtlAddVectoredContinueHandler or RtlRemoveVectoredContinueHandler not
found\n");
+ return;
+ }
+
+ handler1 = pRtlAddVectoredContinueHandler(TRUE, (void *)0xdeadbeef);
+ ok(handler1 != 0, "RtlAddVectoredContinueHandler failed\n");
+
+ handler2 = pRtlAddVectoredContinueHandler(TRUE, (void *)0xdeadbeef);
+ ok(handler2 != 0, "RtlAddVectoredContinueHandler failed\n");
+ ok(handler1 != handler2, "RtlAddVectoredContinueHandler returned same
handler\n");
+
+ if (pRtlRemoveVectoredExceptionHandler)
+ {
+ ret = pRtlRemoveVectoredExceptionHandler(handler1);
+ ok(!ret, "RtlRemoveVectoredExceptionHandler succeeded\n");
+ }
+
+ ret = pRtlRemoveVectoredContinueHandler(handler1);
+ ok(ret, "RtlRemoveVectoredContinueHandler failed\n");
+
+ ret = pRtlRemoveVectoredContinueHandler(handler2);
+ ok(ret, "RtlRemoveVectoredContinueHandler failed\n");
+
+ ret = pRtlRemoveVectoredContinueHandler(handler1);
+ ok(!ret, "RtlRemoveVectoredContinueHandler succeeded\n");
+
+ ret = pRtlRemoveVectoredContinueHandler((void *)0x11223344);
+ ok(!ret, "RtlRemoveVectoredContinueHandler succeeded\n");
+}
+#endif /* defined(__i386__) || defined(__x86_64__) */
+
START_TEST(exception)
{
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
@@ -1802,6 +1896,7 @@
pNtGetContextThread = (void *)GetProcAddress( hntdll, "NtGetContextThread"
);
pNtSetContextThread = (void *)GetProcAddress( hntdll, "NtSetContextThread"
);
pNtReadVirtualMemory = (void *)GetProcAddress( hntdll,
"NtReadVirtualMemory" );
+ pNtClose = (void *)GetProcAddress( hntdll, "NtClose" );
pRtlUnwind = (void *)GetProcAddress( hntdll, "RtlUnwind" );
pRtlRaiseException = (void *)GetProcAddress( hntdll, "RtlRaiseException"
);
pNtTerminateProcess = (void *)GetProcAddress( hntdll, "NtTerminateProcess"
);
@@ -1809,6 +1904,10 @@
"RtlAddVectoredExceptionHandler" );
pRtlRemoveVectoredExceptionHandler = (void *)GetProcAddress( hntdll,
"RtlRemoveVectoredExceptionHandler" );
+ pRtlAddVectoredContinueHandler = (void *)GetProcAddress( hntdll,
+
"RtlAddVectoredContinueHandler" );
+ pRtlRemoveVectoredContinueHandler = (void *)GetProcAddress( hntdll,
+
"RtlRemoveVectoredContinueHandler" );
pNtQueryInformationProcess = (void*)GetProcAddress( hntdll,
"NtQueryInformationProcess" );
pNtSetInformationProcess = (void*)GetProcAddress( hntdll,
@@ -1858,13 +1957,17 @@
run_rtlraiseexception_test(EXCEPTION_BREAKPOINT);
run_rtlraiseexception_test(EXCEPTION_INVALID_HANDLE);
test_stage = 3;
- test_outputdebugstring(0, FALSE);
+ test_outputdebugstring(0);
test_stage = 4;
- test_outputdebugstring(2, TRUE); /* is this a Windows bug? */
+ test_outputdebugstring(2);
test_stage = 5;
test_ripevent(0);
test_stage = 6;
test_ripevent(1);
+ test_stage = 7;
+ test_closehandle(0);
+ test_stage = 8;
+ test_closehandle(1);
}
else
skip( "RtlRaiseException not found\n" );
@@ -1876,8 +1979,10 @@
test_unwind();
test_exceptions();
test_rtlraiseexception();
- test_outputdebugstring(1, FALSE);
+ test_outputdebugstring(1);
test_ripevent(1);
+ test_closehandle(0);
+ test_vectored_continue_handler();
test_debugger();
test_simd_exceptions();
test_fpu_exceptions();
@@ -1894,8 +1999,10 @@
pRtlLookupFunctionEntry = (void *)GetProcAddress( hntdll,
"RtlLookupFunctionEntry" );
- test_outputdebugstring(1, FALSE);
+ test_outputdebugstring(1);
test_ripevent(1);
+ test_closehandle(0);
+ test_vectored_continue_handler();
test_virtual_unwind();
if (pRtlAddFunctionTable && pRtlDeleteFunctionTable &&
pRtlInstallFunctionTableCallback && pRtlLookupFunctionEntry)
Modified: trunk/rostests/winetests/ntdll/file.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ntdll/file.c?re…
==============================================================================
--- trunk/rostests/winetests/ntdll/file.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/ntdll/file.c [iso-8859-1] Tue Mar 10 10:10:04 2015
@@ -37,6 +37,33 @@
#include "winternl.h"
#include "winuser.h"
#include "wine/winioctl.h"
+
+/* FIXME */
+typedef struct _REPARSE_DATA_BUFFER {
+ ULONG ReparseTag;
+ USHORT ReparseDataLength;
+ USHORT Reserved;
+ _ANONYMOUS_UNION union {
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ ULONG Flags;
+ WCHAR PathBuffer[1];
+ } SymbolicLinkReparseBuffer;
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ WCHAR PathBuffer[1];
+ } MountPointReparseBuffer;
+ struct {
+ UCHAR DataBuffer[1];
+ } GenericReparseBuffer;
+ } DUMMYUNIONNAME;
+} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
#ifndef IO_COMPLETION_ALL_ACCESS
#define IO_COMPLETION_ALL_ACCESS 0x001F0003
@@ -1234,7 +1261,7 @@
memset(&fbi, 0, sizeof(fbi));
res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi,
FileBasicInformation);
ok ( res == STATUS_SUCCESS, "can't get attributes\n");
- todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM,
"attribute %x not FILE_ATTRIBUTE_SYSTEM\n", fbi.FileAttributes );
+ ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute
%x not FILE_ATTRIBUTE_SYSTEM (ok in old linux without xattr)\n", fbi.FileAttributes
);
/* Then HIDDEN */
memset(&fbi, 0, sizeof(fbi));
@@ -1247,7 +1274,7 @@
memset(&fbi, 0, sizeof(fbi));
res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi,
FileBasicInformation);
ok ( res == STATUS_SUCCESS, "can't get attributes\n");
- todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN,
"attribute %x not FILE_ATTRIBUTE_HIDDEN\n", fbi.FileAttributes );
+ ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute
%x not FILE_ATTRIBUTE_HIDDEN (ok in old linux without xattr)\n", fbi.FileAttributes
);
/* Check NORMAL last of all (to make sure we can clear attributes) */
memset(&fbi, 0, sizeof(fbi));
@@ -1304,7 +1331,7 @@
memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf,
FileAllInformation);
ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
- todo_wine ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) ==
FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM\n",
fai_buf.fai.BasicInformation.FileAttributes );
+ ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) ==
FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM (ok in old linux
without xattr)\n", fai_buf.fai.BasicInformation.FileAttributes );
/* Then HIDDEN */
memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
@@ -1317,7 +1344,7 @@
memset(&fai_buf.fai, 0, sizeof(fai_buf.fai));
res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf,
FileAllInformation);
ok ( res == STATUS_SUCCESS, "can't get attributes\n");
- todo_wine ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) ==
FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN\n",
fai_buf.fai.BasicInformation.FileAttributes );
+ ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) ==
FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN (ok in old linux
without xattr)\n", fai_buf.fai.BasicInformation.FileAttributes );
/* Check NORMAL last of all (to make sure we can clear attributes) */
memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation));
@@ -1371,7 +1398,6 @@
ok( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED,
"Unexpected NtQueryInformationFile result (expected STATUS_INVALID_INFO_CLASS, got
%x)\n", res );
fdi.DoDeleteFile = TRUE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi,
FileDispositionInformation );
- todo_wine
ok( res == STATUS_ACCESS_DENIED, "unexpected FileDispositionInformation result
(expected STATUS_ACCESS_DENIED, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1384,12 +1410,24 @@
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
fdi.DoDeleteFile = TRUE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi,
FileDispositionInformation );
- todo_wine
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result
(expected STATUS_SUCCESS, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
- todo_wine
ok( fileDeleted, "File should have been deleted\n" );
+ DeleteFileA( buffer );
+
+ /* cannot set disposition on readonly file */
+ GetTempFileNameA( tmp_path, "dis", 0, buffer );
+ DeleteFileA( buffer );
+ handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_READONLY, 0);
+ ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
+ fdi.DoDeleteFile = TRUE;
+ res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi,
FileDispositionInformation );
+ ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result
(expected STATUS_CANNOT_DELETE, got %x)\n", res );
+ CloseHandle( handle );
+ fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "File shouldn't have been deleted\n" );
+ SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
DeleteFileA( buffer );
/* cannot set disposition on readonly file */
@@ -1402,6 +1440,21 @@
ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result
(expected STATUS_CANNOT_DELETE, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
+ todo_wine
+ ok( !fileDeleted, "File shouldn't have been deleted\n" );
+ SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
+ DeleteFileA( buffer );
+
+ /* cannot set disposition on readonly file */
+ GetTempFileNameA( tmp_path, "dis", 0, buffer );
+ DeleteFileA( buffer );
+ handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_READONLY, 0);
+ ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
+ fdi.DoDeleteFile = TRUE;
+ res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi,
FileDispositionInformation );
+ ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result
(expected STATUS_CANNOT_DELETE, got %x)\n", res );
+ CloseHandle( handle );
+ fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "File shouldn't have been deleted\n" );
SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
DeleteFileA( buffer );
@@ -1412,11 +1465,9 @@
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
fdi.DoDeleteFile = TRUE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi,
FileDispositionInformation );
- todo_wine
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result
(expected STATUS_SUCCESS, got %x)\n", res );
fdi.DoDeleteFile = FALSE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi,
FileDispositionInformation );
- todo_wine
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result
(expected STATUS_SUCCESS, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1429,7 +1480,6 @@
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
fdi.DoDeleteFile = FALSE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi,
FileDispositionInformation );
- todo_wine
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result
(expected STATUS_SUCCESS, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1444,7 +1494,6 @@
CloseHandle( handle );
fdi.DoDeleteFile = FALSE;
res = pNtSetInformationFile( handle2, &io, &fdi, sizeof fdi,
FileDispositionInformation );
- todo_wine
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result
(expected STATUS_SUCCESS, got %x)\n", res );
CloseHandle( handle2 );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1459,11 +1508,9 @@
ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
fdi.DoDeleteFile = TRUE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi,
FileDispositionInformation );
- todo_wine
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result
(expected STATUS_SUCCESS, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
- todo_wine
ok( fileDeleted, "Directory should have been deleted\n" );
RemoveDirectoryA( buffer );
@@ -1476,7 +1523,6 @@
RemoveDirectoryA( buffer );
fdi.DoDeleteFile = FALSE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi,
FileDispositionInformation );
- todo_wine
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result
(expected STATUS_SUCCESS, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1501,6 +1547,7 @@
buffer[dirpos] = '\0';
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
+ todo_wine
ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
RemoveDirectoryA( buffer );
}
@@ -2683,6 +2730,178 @@
CloseHandle(hfile);
}
+static INT build_reparse_buffer(WCHAR *filename, REPARSE_DATA_BUFFER **pbuffer)
+{
+ REPARSE_DATA_BUFFER *buffer;
+ INT buffer_len, string_len;
+ WCHAR *dest;
+
+ string_len = (lstrlenW(filename)+1)*sizeof(WCHAR);
+ buffer_len = FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer[1])
+ string_len;
+ buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_len);
+ buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
+ buffer->ReparseDataLength = sizeof(buffer->MountPointReparseBuffer) +
string_len;
+ buffer->MountPointReparseBuffer.SubstituteNameLength = string_len -
sizeof(WCHAR);
+ buffer->MountPointReparseBuffer.PrintNameOffset = string_len;
+ dest = &buffer->MountPointReparseBuffer.PathBuffer[0];
+ memcpy(dest, filename, string_len);
+ *pbuffer = buffer;
+ return buffer_len;
+}
+
+static void test_junction_points(void)
+{
+ static const WCHAR junctionW[] =
{'\\','j','u','n','c','t','i','o','n',0};
+ WCHAR path[MAX_PATH], junction_path[MAX_PATH], target_path[MAX_PATH];
+ static const WCHAR targetW[] =
{'\\','t','a','r','g','e','t',0};
+ FILE_BASIC_INFORMATION old_attrib, new_attrib;
+ static const WCHAR fooW[] = {'f','o','o',0};
+ static WCHAR volW[] = {'c',':','\\',0};
+ REPARSE_GUID_DATA_BUFFER guid_buffer;
+ static const WCHAR dotW[] = {'.',0};
+ REPARSE_DATA_BUFFER *buffer = NULL;
+ DWORD dwret, dwLen, dwFlags, err;
+ INT buffer_len, string_len;
+ IO_STATUS_BLOCK iosb;
+ UNICODE_STRING nameW;
+ HANDLE hJunction;
+ WCHAR *dest;
+ BOOL bret;
+
+ /* Create a temporary folder for the junction point tests */
+ GetTempFileNameW(dotW, fooW, 0, path);
+ DeleteFileW(path);
+ if (!CreateDirectoryW(path, NULL))
+ {
+ win_skip("Unable to create a temporary junction point directory.\n");
+ return;
+ }
+
+ /* Check that the volume this folder is located on supports junction points */
+ pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
+ volW[0] = nameW.Buffer[4];
+ pRtlFreeUnicodeString( &nameW );
+ GetVolumeInformationW(volW, 0, 0, 0, &dwLen, &dwFlags, 0, 0);
+ if (!(dwFlags & FILE_SUPPORTS_REPARSE_POINTS))
+ {
+ skip("File system does not support junction points.\n");
+ RemoveDirectoryW(path);
+ return;
+ }
+
+ /* Create the folder to be replaced by a junction point */
+ lstrcpyW(junction_path, path);
+ lstrcatW(junction_path, junctionW);
+ bret = CreateDirectoryW(junction_path, NULL);
+ ok(bret, "Failed to create junction point directory.\n");
+
+ /* Create a destination folder for the junction point to target */
+ lstrcpyW(target_path, path);
+ lstrcatW(target_path, targetW);
+ bret = CreateDirectoryW(target_path, NULL);
+ ok(bret, "Failed to create junction point target directory.\n");
+ pRtlDosPathNameToNtPathName_U(target_path, &nameW, NULL, NULL);
+
+ /* Create the junction point */
+ hJunction = CreateFileW(junction_path, GENERIC_READ | GENERIC_WRITE, 0, 0,
OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
0);
+ if (hJunction == INVALID_HANDLE_VALUE)
+ {
+ win_skip("Failed to open junction point directory handle (0x%x).\n",
GetLastError());
+ goto cleanup;
+ }
+ dwret = NtQueryInformationFile(hJunction, &iosb, &old_attrib,
sizeof(old_attrib), FileBasicInformation);
+ ok(dwret == STATUS_SUCCESS, "Failed to get junction point folder's
attributes (0x%x).\n", dwret);
+ buffer_len = build_reparse_buffer(nameW.Buffer, &buffer);
+ bret = DeviceIoControl(hJunction, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer,
buffer_len, NULL, 0, &dwret, 0);
+ ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
+
+ /* Check the file attributes of the junction point */
+ dwret = GetFileAttributesW(junction_path);
+ ok(dwret != (DWORD)~0, "Junction point doesn't exist (attributes:
0x%x)!\n", dwret);
+ ok(dwret & FILE_ATTRIBUTE_REPARSE_POINT, "File is not a junction point!
(attributes: %d)\n", dwret);
+
+ /* Read back the junction point */
+ HeapFree(GetProcessHeap(), 0, buffer);
+ buffer_len = sizeof(*buffer) + MAX_PATH*sizeof(WCHAR);
+ buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_len);
+ bret = DeviceIoControl(hJunction, FSCTL_GET_REPARSE_POINT, NULL, 0, (LPVOID)buffer,
buffer_len, &dwret, 0);
+ string_len = buffer->MountPointReparseBuffer.SubstituteNameLength;
+ dest =
&buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)];
+ ok(bret, "Failed to read junction point!\n");
+ ok((memcmp(dest, nameW.Buffer, string_len) == 0), "Junction point destination
does not match ('%s' != '%s')!\n",
+ wine_dbgstr_w(dest),
wine_dbgstr_w(nameW.Buffer));
+
+ /* Delete the junction point */
+ memset(&old_attrib, 0x00, sizeof(old_attrib));
+ old_attrib.LastAccessTime.QuadPart = 0x200deadcafebeef;
+ dwret = NtSetInformationFile(hJunction, &iosb, &old_attrib,
sizeof(old_attrib), FileBasicInformation);
+ ok(dwret == STATUS_SUCCESS, "Failed to set junction point folder's
attributes (0x%x).\n", dwret);
+ memset(&guid_buffer, 0x00, sizeof(guid_buffer));
+ guid_buffer.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
+ bret = DeviceIoControl(hJunction, FSCTL_DELETE_REPARSE_POINT,
(LPVOID)&guid_buffer,
+ REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, NULL, 0, &dwret,
0);
+ ok(bret, "Failed to delete junction point! (0x%x)\n", GetLastError());
+ memset(&new_attrib, 0x00, sizeof(new_attrib));
+ dwret = NtQueryInformationFile(hJunction, &iosb, &new_attrib,
sizeof(new_attrib), FileBasicInformation);
+ ok(dwret == STATUS_SUCCESS, "Failed to get junction point folder's
attributes (0x%x).\n", dwret);
+ ok(old_attrib.LastAccessTime.QuadPart == new_attrib.LastAccessTime.QuadPart,
+ "Junction point folder's access time does not match (0x%llx !=
0x%llx).\n",
+ new_attrib.LastAccessTime.QuadPart, old_attrib.LastAccessTime.QuadPart);
+ CloseHandle(hJunction);
+
+ /* Check deleting a junction point as if it were a directory */
+ HeapFree(GetProcessHeap(), 0, buffer);
+ hJunction = CreateFileW(junction_path, GENERIC_READ | GENERIC_WRITE, 0, 0,
OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
0);
+ buffer_len = build_reparse_buffer(nameW.Buffer, &buffer);
+ bret = DeviceIoControl(hJunction, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer,
buffer_len, NULL, 0, &dwret, 0);
+ ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
+ CloseHandle(hJunction);
+ bret = RemoveDirectoryW(junction_path);
+ ok(bret, "Failed to delete junction point as directory!\n");
+ dwret = GetFileAttributesW(junction_path);
+ ok(dwret == (DWORD)~0, "Junction point still exists (attributes: 0x%x)!\n",
dwret);
+
+ /* Check deleting a junction point as if it were a file */
+ HeapFree(GetProcessHeap(), 0, buffer);
+ bret = CreateDirectoryW(junction_path, NULL);
+ ok(bret, "Failed to create junction point target directory.\n");
+ hJunction = CreateFileW(junction_path, GENERIC_READ | GENERIC_WRITE, 0, 0,
OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
0);
+ buffer_len = build_reparse_buffer(nameW.Buffer, &buffer);
+ bret = DeviceIoControl(hJunction, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer,
buffer_len, NULL, 0, &dwret, 0);
+ ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError());
+ CloseHandle(hJunction);
+ bret = DeleteFileW(junction_path);
+ ok(!bret, "Succeeded in deleting junction point as file!\n");
+ err = GetLastError();
+ ok(err == ERROR_ACCESS_DENIED, "Expected last error 0x%x for DeleteFile on
junction point (actually 0x%x)!\n",
+ ERROR_ACCESS_DENIED, err);
+ dwret = GetFileAttributesW(junction_path);
+ ok(dwret != (DWORD)~0, "Junction point doesn't exist (attributes:
0x%x)!\n", dwret);
+ ok(dwret & FILE_ATTRIBUTE_REPARSE_POINT, "File is not a junction point!
(attributes: 0x%x)\n", dwret);
+
+ /* Test deleting a junction point's target */
+ dwret = GetFileAttributesW(junction_path);
+ ok(dwret == 0x410 || broken(dwret == 0x430) /* win2k */,
+ "Unexpected junction point attributes (0x%x != 0x410)!\n", dwret);
+ bret = RemoveDirectoryW(target_path);
+ ok(bret, "Failed to delete junction point target!\n");
+ bret = CreateDirectoryW(target_path, NULL);
+ ok(bret, "Failed to create junction point target directory.\n");
+
+cleanup:
+ /* Cleanup */
+ pRtlFreeUnicodeString( &nameW );
+ HeapFree(GetProcessHeap(), 0, buffer);
+ bret = RemoveDirectoryW(junction_path);
+ ok(bret, "Failed to remove temporary junction point directory!\n");
+ bret = RemoveDirectoryW(target_path);
+ ok(bret, "Failed to remove temporary target directory!\n");
+ RemoveDirectoryW(path);
+}
+
START_TEST(file)
{
HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
@@ -2736,4 +2955,5 @@
test_file_disposition_information();
test_query_volume_information_file();
test_query_attribute_information_file();
+ test_junction_points();
}
Modified: trunk/rostests/winetests/ntdll/info.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ntdll/info.c?re…
==============================================================================
--- trunk/rostests/winetests/ntdll/info.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/ntdll/info.c [iso-8859-1] Tue Mar 10 10:10:04 2015
@@ -737,6 +737,84 @@
HeapFree(GetProcessHeap(), 0, ppi);
}
+static void test_query_process_wow64(void)
+{
+ NTSTATUS status;
+ ULONG ReturnLength;
+ ULONG_PTR pbi[2], dummy;
+
+ memset(&dummy, 0xcc, sizeof(dummy));
+
+ /* Do not give a handle and buffer */
+ status = pNtQueryInformationProcess(NULL, ProcessWow64Information, NULL, 0, NULL);
+ ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected
STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
+
+ /* Use a correct info class and buffer size, but still no handle and buffer */
+ status = pNtQueryInformationProcess(NULL, ProcessWow64Information, NULL,
sizeof(ULONG_PTR), NULL);
+ ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
+ "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE, got
%08x\n", status);
+
+ /* Use a correct info class, buffer size and handle, but no buffer */
+ status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information,
NULL, sizeof(ULONG_PTR), NULL);
+ ok( status == STATUS_ACCESS_VIOLATION , "Expected STATUS_ACCESS_VIOLATION, got
%08x\n", status);
+
+ /* Use a correct info class, buffer and buffer size, but no handle */
+ pbi[0] = pbi[1] = dummy;
+ status = pNtQueryInformationProcess(NULL, ProcessWow64Information, pbi,
sizeof(ULONG_PTR), NULL);
+ ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got
%08x\n", status);
+ ok( pbi[0] == dummy, "pbi[0] changed to %lx\n", pbi[0]);
+ ok( pbi[1] == dummy, "pbi[1] changed to %lx\n", pbi[1]);
+
+ /* Use a greater buffer size */
+ pbi[0] = pbi[1] = dummy;
+ status = pNtQueryInformationProcess(NULL, ProcessWow64Information, pbi,
sizeof(ULONG_PTR) + 1, NULL);
+ ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected
STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
+ ok( pbi[0] == dummy, "pbi[0] changed to %lx\n", pbi[0]);
+ ok( pbi[1] == dummy, "pbi[1] changed to %lx\n", pbi[1]);
+
+ /* Use no ReturnLength */
+ pbi[0] = pbi[1] = dummy;
+ status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information,
pbi, sizeof(ULONG_PTR), NULL);
+ ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n",
status);
+ trace( "Platform is_wow64 %d, ProcessInformation of ProcessWow64Information
%lx\n", is_wow64, pbi[0]);
+ ok( is_wow64 == (pbi[0] != 0), "is_wow64 %x, pbi[0] %lx\n", is_wow64,
pbi[0]);
+ ok( pbi[0] != dummy, "pbi[0] %lx\n", pbi[0]);
+ ok( pbi[1] == dummy, "pbi[1] changed to %lx\n", pbi[1]);
+ /* Test written size on 64 bit by checking high 32 bit buffer */
+ if (sizeof(ULONG_PTR) > sizeof(DWORD))
+ {
+ DWORD *ptr = (DWORD *)pbi;
+ ok( ptr[1] != (DWORD)dummy, "ptr[1] unchanged!\n");
+ }
+
+ /* Finally some correct calls */
+ pbi[0] = pbi[1] = dummy;
+ ReturnLength = 0xdeadbeef;
+ status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information,
pbi, sizeof(ULONG_PTR), &ReturnLength);
+ ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n",
status);
+ ok( is_wow64 == (pbi[0] != 0), "is_wow64 %x, pbi[0] %lx\n", is_wow64,
pbi[0]);
+ ok( pbi[1] == dummy, "pbi[1] changed to %lx\n", pbi[1]);
+ ok( ReturnLength == sizeof(ULONG_PTR), "Inconsistent length %d\n",
ReturnLength);
+
+ /* Everything is correct except a too small buffer size */
+ pbi[0] = pbi[1] = dummy;
+ ReturnLength = 0xdeadbeef;
+ status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information,
pbi, sizeof(ULONG_PTR) - 1, &ReturnLength);
+ ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected
STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
+ ok( pbi[0] == dummy, "pbi[0] changed to %lx\n", pbi[0]);
+ ok( pbi[1] == dummy, "pbi[1] changed to %lx\n", pbi[1]);
+ todo_wine ok( ReturnLength == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n",
ReturnLength);
+
+ /* Everything is correct except a too large buffer size */
+ pbi[0] = pbi[1] = dummy;
+ ReturnLength = 0xdeadbeef;
+ status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information,
pbi, sizeof(ULONG_PTR) + 1, &ReturnLength);
+ ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected
STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
+ ok( pbi[0] == dummy, "pbi[0] changed to %lx\n", pbi[0]);
+ ok( pbi[1] == dummy, "pbi[1] changed to %lx\n", pbi[1]);
+ todo_wine ok( ReturnLength == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n",
ReturnLength);
+}
+
static void test_query_process_basic(void)
{
NTSTATUS status;
@@ -1714,6 +1792,10 @@
trace("Starting test_query_process_handlecount()\n");
test_query_process_handlecount();
+ /* 0x1A ProcessWow64Information */
+ trace("Starting test_query_process_wow64()\n");
+ test_query_process_wow64();
+
/* 0x1B ProcessImageFileName */
trace("Starting test_query_process_image_file_name()\n");
test_query_process_image_file_name();
Modified: trunk/rostests/winetests/ntdll/om.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ntdll/om.c?rev=…
==============================================================================
--- trunk/rostests/winetests/ntdll/om.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/ntdll/om.c [iso-8859-1] Tue Mar 10 10:10:04 2015
@@ -835,14 +835,14 @@
status = pNtOpenEvent(&Event2, GENERIC_ALL, &attr);
ok( status == STATUS_SUCCESS, "NtOpenEvent failed %08x\n", status );
- status = pNtClose(Event);
+ pNtClose(Event);
status = pNtQueryEvent(Event2, EventBasicInformation, &info, sizeof(info),
NULL);
ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
ok( info.EventType == 1 && info.EventState == 0,
"NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType,
info.EventState );
- status = pNtClose(Event2);
+ pNtClose(Event2);
}
static const WCHAR keyed_nameW[] =
{'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s',
Modified: trunk/rostests/winetests/ntdll/reg.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ntdll/reg.c?rev…
==============================================================================
--- trunk/rostests/winetests/ntdll/reg.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/ntdll/reg.c [iso-8859-1] Tue Mar 10 10:10:04 2015
@@ -129,11 +129,14 @@
static NTSTATUS (WINAPI * pNtCreateKey)( PHANDLE retkey, ACCESS_MASK access, const
OBJECT_ATTRIBUTES *attr,
ULONG TitleIndex, const UNICODE_STRING *class, ULONG
options,
PULONG dispos );
+static NTSTATUS (WINAPI * pNtQueryKey)(HANDLE,KEY_INFORMATION_CLASS,PVOID,ULONG,PULONG);
+static NTSTATUS (WINAPI * pNtQueryLicenseValue)(const UNICODE_STRING *,ULONG
*,PVOID,ULONG,ULONG *);
static NTSTATUS (WINAPI * pNtQueryValueKey)(HANDLE,const UNICODE_STRING
*,KEY_VALUE_INFORMATION_CLASS,void *,DWORD,DWORD *);
static NTSTATUS (WINAPI * pNtSetValueKey)(HANDLE, const PUNICODE_STRING, ULONG,
ULONG, const void*, ULONG );
static NTSTATUS (WINAPI *
pNtQueryInformationProcess)(HANDLE,PROCESSINFOCLASS,PVOID,ULONG,PULONG);
static NTSTATUS (WINAPI * pRtlFormatCurrentUserKeyPath)(PUNICODE_STRING);
+static LONG (WINAPI * pRtlCompareUnicodeString)(const PUNICODE_STRING,const
PUNICODE_STRING,BOOLEAN);
static BOOLEAN (WINAPI * pRtlCreateUnicodeString)(PUNICODE_STRING, LPCWSTR);
static LPVOID (WINAPI * pRtlReAllocateHeap)(IN PVOID, IN ULONG, IN PVOID, IN ULONG);
static NTSTATUS (WINAPI * pRtlAppendUnicodeToString)(PUNICODE_STRING, PCWSTR);
@@ -166,7 +169,6 @@
NTDLL_GET_PROC(RtlCreateUnicodeStringFromAsciiz)
NTDLL_GET_PROC(RtlCreateUnicodeString)
NTDLL_GET_PROC(RtlFreeUnicodeString)
- NTDLL_GET_PROC(NtDeleteValueKey)
NTDLL_GET_PROC(RtlQueryRegistryValues)
NTDLL_GET_PROC(RtlCheckRegistryKey)
NTDLL_GET_PROC(RtlOpenCurrentUser)
@@ -175,11 +177,13 @@
NTDLL_GET_PROC(NtCreateKey)
NTDLL_GET_PROC(NtFlushKey)
NTDLL_GET_PROC(NtDeleteKey)
+ NTDLL_GET_PROC(NtQueryKey)
NTDLL_GET_PROC(NtQueryValueKey)
NTDLL_GET_PROC(NtQueryInformationProcess)
NTDLL_GET_PROC(NtSetValueKey)
NTDLL_GET_PROC(NtOpenKey)
NTDLL_GET_PROC(RtlFormatCurrentUserKeyPath)
+ NTDLL_GET_PROC(RtlCompareUnicodeString)
NTDLL_GET_PROC(RtlReAllocateHeap)
NTDLL_GET_PROC(RtlAppendUnicodeToString)
NTDLL_GET_PROC(RtlUnicodeStringToAnsiString)
@@ -188,6 +192,10 @@
NTDLL_GET_PROC(RtlZeroMemory)
NTDLL_GET_PROC(RtlpNtQueryValueKey)
NTDLL_GET_PROC(RtlOpenCurrentUser)
+
+ /* optional functions */
+ pNtQueryLicenseValue = (void *)GetProcAddress(hntdll,
"NtQueryLicenseValue");
+
return TRUE;
}
#undef NTDLL_GET_PROC
@@ -640,6 +648,180 @@
status = pNtDeleteKey(hkey);
ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
+}
+
+static void test_NtQueryLicenseKey(void)
+{
+ static const WCHAR emptyW[] =
{'E','M','P','T','Y',0};
+ UNICODE_STRING name;
+ WORD buffer[32];
+ NTSTATUS status;
+ ULONG type, len;
+ DWORD value;
+
+ if (!pNtQueryLicenseValue)
+ {
+ win_skip("NtQueryLicenseValue not found, skipping tests\n");
+ return;
+ }
+
+ type = 0xdead;
+ len = 0xbeef;
+ memset(&name, 0, sizeof(name));
+ status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer),
&len);
+ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x,
expected STATUS_INVALID_PARAMETER\n", status);
+ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
+ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
+
+ /* test with empty key */
+ pRtlCreateUnicodeStringFromAsciiz(&name, "");
+
+ type = 0xdead;
+ len = 0xbeef;
+ status = pNtQueryLicenseValue(NULL, &type, buffer, sizeof(buffer), &len);
+ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x,
expected STATUS_INVALID_PARAMETER\n", status);
+ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
+ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
+
+ type = 0xdead;
+ status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), NULL);
+ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x,
expected STATUS_INVALID_PARAMETER\n", status);
+ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
+
+ len = 0xbeef;
+ status = pNtQueryLicenseValue(&name, NULL, buffer, sizeof(buffer), &len);
+ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x,
expected STATUS_INVALID_PARAMETER\n", status);
+ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
+
+ type = 0xdead;
+ len = 0xbeef;
+ status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer),
&len);
+ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x,
expected STATUS_INVALID_PARAMETER\n", status);
+ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
+ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
+
+ pRtlFreeUnicodeString(&name);
+
+ /* test with nonexistent licence key */
+ pRtlCreateUnicodeStringFromAsciiz(&name, "Nonexistent-License-Value");
+
+ type = 0xdead;
+ len = 0xbeef;
+ status = pNtQueryLicenseValue(NULL, &type, buffer, sizeof(buffer), &len);
+ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x,
expected STATUS_INVALID_PARAMETER\n", status);
+ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
+ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
+
+ type = 0xdead;
+ status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), NULL);
+ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x,
expected STATUS_INVALID_PARAMETER\n", status);
+ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
+
+ len = 0xbeef;
+ status = pNtQueryLicenseValue(&name, NULL, buffer, sizeof(buffer), &len);
+ ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryLicenseValue returned %08x,
expected STATUS_OBJECT_NAME_NOT_FOUND\n", status);
+ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
+
+ type = 0xdead;
+ len = 0xbeef;
+ status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer),
&len);
+ ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryLicenseValue unexpected
suceeded\n");
+ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
+ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
+
+ pRtlFreeUnicodeString(&name);
+
+ /* test with REG_SZ license key */
+ pRtlCreateUnicodeStringFromAsciiz(&name,
"Kernel-MUI-Language-Allowed");
+
+ type = 0xdead;
+ len = 0xbeef;
+ status = pNtQueryLicenseValue(NULL, &type, buffer, sizeof(buffer), &len);
+ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x,
expected STATUS_INVALID_PARAMETER\n", status);
+ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
+ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
+
+ type = 0xdead;
+ status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), NULL);
+ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x,
expected STATUS_INVALID_PARAMETER\n", status);
+ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
+
+ type = 0xdead;
+ len = 0;
+ status = pNtQueryLicenseValue(&name, &type, buffer, 0, &len);
+ ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x,
expected STATUS_BUFFER_TOO_SMALL\n", status);
+ ok(type == REG_SZ, "expected type = REG_SZ, got %u\n", type);
+ ok(len == sizeof(emptyW), "expected len = %u, got %u\n",
(DWORD)sizeof(emptyW), len);
+
+ len = 0;
+ status = pNtQueryLicenseValue(&name, NULL, buffer, 0, &len);
+ ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x,
expected STATUS_BUFFER_TOO_SMALL\n", status);
+ ok(len == sizeof(emptyW), "expected len = %u, got %u\n",
(DWORD)sizeof(emptyW), len);
+
+ type = 0xdead;
+ len = 0;
+ memset(buffer, 0x11, sizeof(buffer));
+ status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer),
&len);
+ ok(status == STATUS_SUCCESS, "NtQueryLicenseValue returned %08x, expected
STATUS_SUCCESS\n", status);
+ ok(type == REG_SZ, "expected type = REG_SZ, got %u\n", type);
+ ok(len == sizeof(emptyW), "expected len = %u, got %u\n",
(DWORD)sizeof(emptyW), len);
+ ok(!memcmp(buffer, emptyW, sizeof(emptyW)), "unexpected buffer
content\n");
+
+ type = 0xdead;
+ len = 0;
+ memset(buffer, 0x11, sizeof(buffer));
+ status = pNtQueryLicenseValue(&name, &type, buffer, 2, &len);
+ ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x,
expected STATUS_BUFFER_TOO_SMALL\n", status);
+ ok(type == REG_SZ, "expected type REG_SZ, got %u\n", type);
+ ok(len == sizeof(emptyW), "expected len = %u, got %u\n",
(DWORD)sizeof(emptyW), len);
+ ok(buffer[0] == 0x1111, "expected buffer[0] = 0x1111, got %u\n",
buffer[0]);
+
+ pRtlFreeUnicodeString(&name);
+
+ /* test with REG_DWORD license key */
+ pRtlCreateUnicodeStringFromAsciiz(&name, "Kernel-MUI-Number-Allowed");
+
+ type = 0xdead;
+ len = 0xbeef;
+ status = pNtQueryLicenseValue(NULL, &type, &value, sizeof(value), &len);
+ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x,
expected STATUS_INVALID_PARAMETER\n", status);
+ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
+ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
+
+ type = 0xdead;
+ status = pNtQueryLicenseValue(&name, &type, &value, sizeof(value),
NULL);
+ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x,
expected STATUS_INVALID_PARAMETER\n", status);
+ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
+
+ type = 0xdead;
+ len = 0;
+ status = pNtQueryLicenseValue(&name, &type, &value, 0, &len);
+ ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x,
expected STATUS_BUFFER_TOO_SMALL\n", status);
+ ok(type == REG_DWORD, "expected type = REG_DWORD, got %u\n", type);
+ ok(len == sizeof(value), "expected len = %u, got %u\n",
(DWORD)sizeof(value), len);
+
+ len = 0;
+ status = pNtQueryLicenseValue(&name, NULL, &value, 0, &len);
+ ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x,
expected STATUS_BUFFER_TOO_SMALL\n", status);
+ ok(len == sizeof(value), "expected len = %u, got %u\n",
(DWORD)sizeof(value), len);
+
+ type = 0xdead;
+ len = 0;
+ value = 0xdeadbeef;
+ status = pNtQueryLicenseValue(&name, &type, &value, sizeof(value),
&len);
+ ok(status == STATUS_SUCCESS, "NtQueryLicenseValue returned %08x, expected
STATUS_SUCCESS\n", status);
+ ok(type == REG_DWORD, "expected type = REG_DWORD, got %u\n", type);
+ ok(len == sizeof(value), "expected len = %u, got %u\n",
(DWORD)sizeof(value), len);
+ ok(value != 0xdeadbeef, "expected value != 0xdeadbeef\n");
+
+ type = 0xdead;
+ len = 0;
+ status = pNtQueryLicenseValue(&name, &type, &value, 2, &len);
+ ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x,
expected STATUS_BUFFER_TOO_SMALL\n", status);
+ ok(type == REG_DWORD, "expected type REG_DWORD, got %u\n", type);
+ ok(len == sizeof(value), "expected len = %u, got %u\n",
(DWORD)sizeof(value), len);
+
+ pRtlFreeUnicodeString(&name);
}
static void test_RtlpNtQueryValueKey(void)
@@ -1277,6 +1459,51 @@
pNtClose(key);
}
+static void test_NtQueryKey(void)
+{
+ HANDLE key;
+ NTSTATUS status;
+ OBJECT_ATTRIBUTES attr;
+ ULONG length, len;
+ KEY_NAME_INFORMATION *info = NULL;
+ UNICODE_STRING str;
+
+ InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
+ status = pNtOpenKey(&key, KEY_READ, &attr);
+ ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
+
+ status = pNtQueryKey(key, KeyNameInformation, NULL, 0, &length);
+ if (status == STATUS_INVALID_PARAMETER) {
+ win_skip("KeyNameInformation is not supported\n");
+ pNtClose(key);
+ return;
+ }
+ todo_wine ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryKey Failed:
0x%08x\n", status);
+ info = HeapAlloc(GetProcessHeap(), 0, length);
+
+ /* non-zero buffer size, but insufficient */
+ status = pNtQueryKey(key, KeyNameInformation, info, sizeof(*info), &len);
+ ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryKey Failed: 0x%08x\n",
status);
+ ok(length == len, "got %d, expected %d\n", len, length);
+ ok(info->NameLength == winetestpath.Length, "got %d, expected %d\n",
+ info->NameLength, winetestpath.Length);
+
+ /* correct buffer size */
+ status = pNtQueryKey(key, KeyNameInformation, info, length, &len);
+ ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08x\n", status);
+ ok(length == len, "got %d, expected %d\n", len, length);
+
+ str.Buffer = info->Name;
+ str.Length = info->NameLength;
+ ok(pRtlCompareUnicodeString(&winetestpath, &str, TRUE) == 0,
+ "got %s, expected %s\n",
+ wine_dbgstr_wn(str.Buffer, str.Length/sizeof(WCHAR)),
+ wine_dbgstr_wn(winetestpath.Buffer, winetestpath.Length/sizeof(WCHAR)));
+
+ HeapFree(GetProcessHeap(), 0, info);
+ pNtClose(key);
+}
+
START_TEST(reg)
{
static const WCHAR winetest[] =
{'\\','W','i','n','e','T','e','s','t',0};
@@ -1297,7 +1524,9 @@
test_RtlQueryRegistryValues();
test_RtlpNtQueryValueKey();
test_NtFlushKey();
+ test_NtQueryKey();
test_NtQueryValueKey();
+ test_NtQueryLicenseKey();
test_long_value_name();
test_NtDeleteKey();
test_symlinks();
Modified: trunk/rostests/winetests/ntdll/rtl.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ntdll/rtl.c?rev…
==============================================================================
--- trunk/rostests/winetests/ntdll/rtl.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/ntdll/rtl.c [iso-8859-1] Tue Mar 10 10:10:04 2015
@@ -62,6 +62,8 @@
/* Function ptrs for ntdll calls */
static HMODULE hntdll = 0;
+static PVOID (WINAPI *pWinSqmStartSession)(PVOID unknown1, DWORD unknown2, DWORD
unknown3);
+static NTSTATUS (WINAPI *pWinSqmEndSession)(PVOID unknown1);
static SIZE_T (WINAPI *pRtlCompareMemory)(LPCVOID,LPCVOID,SIZE_T);
static SIZE_T (WINAPI *pRtlCompareMemoryUlong)(PULONG, SIZE_T, ULONG);
static NTSTATUS (WINAPI *pRtlDeleteTimer)(HANDLE, HANDLE, HANDLE);
@@ -89,9 +91,14 @@
static CHAR * (WINAPI *pRtlIpv4AddressToStringA)(const IN_ADDR *, LPSTR);
static NTSTATUS (WINAPI *pRtlIpv4AddressToStringExA)(const IN_ADDR *, USHORT, LPSTR,
PULONG);
static NTSTATUS (WINAPI *pRtlIpv4StringToAddressA)(PCSTR, BOOLEAN, PCSTR *, IN_ADDR *);
+static NTSTATUS (WINAPI *pRtlIpv4StringToAddressExA)(PCSTR, BOOLEAN, IN_ADDR *,
PUSHORT);
static NTSTATUS (WINAPI *pLdrAddRefDll)(ULONG, HMODULE);
static NTSTATUS (WINAPI *pLdrLockLoaderLock)(ULONG, ULONG*, ULONG_PTR*);
static NTSTATUS (WINAPI *pLdrUnlockLoaderLock)(ULONG, ULONG_PTR);
+static NTSTATUS (WINAPI *pRtlGetCompressionWorkSpaceSize)(USHORT, PULONG, PULONG);
+static NTSTATUS (WINAPI *pRtlDecompressBuffer)(USHORT, PUCHAR, ULONG, const UCHAR*,
ULONG, PULONG);
+static NTSTATUS (WINAPI *pRtlDecompressFragment)(USHORT, PUCHAR, ULONG, const UCHAR*,
ULONG, ULONG, PULONG, PVOID);
+static NTSTATUS (WINAPI *pRtlCompressBuffer)(USHORT, const UCHAR*, ULONG, PUCHAR, ULONG,
ULONG, PULONG, PVOID);
static HMODULE hkernel32 = 0;
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
@@ -109,6 +116,8 @@
hntdll = LoadLibraryA("ntdll.dll");
ok(hntdll != 0, "LoadLibrary failed\n");
if (hntdll) {
+ pWinSqmStartSession = (void *)GetProcAddress(hntdll,
"WinSqmStartSession");
+ pWinSqmEndSession = (void *)GetProcAddress(hntdll,
"WinSqmEndSession");
pRtlCompareMemory = (void *)GetProcAddress(hntdll, "RtlCompareMemory");
pRtlCompareMemoryUlong = (void *)GetProcAddress(hntdll,
"RtlCompareMemoryUlong");
pRtlDeleteTimer = (void *)GetProcAddress(hntdll, "RtlDeleteTimer");
@@ -136,9 +145,14 @@
pRtlIpv4AddressToStringA = (void *)GetProcAddress(hntdll,
"RtlIpv4AddressToStringA");
pRtlIpv4AddressToStringExA = (void *)GetProcAddress(hntdll,
"RtlIpv4AddressToStringExA");
pRtlIpv4StringToAddressA = (void *)GetProcAddress(hntdll,
"RtlIpv4StringToAddressA");
+ pRtlIpv4StringToAddressExA = (void *)GetProcAddress(hntdll,
"RtlIpv4StringToAddressExA");
pLdrAddRefDll = (void *)GetProcAddress(hntdll, "LdrAddRefDll");
pLdrLockLoaderLock = (void *)GetProcAddress(hntdll,
"LdrLockLoaderLock");
pLdrUnlockLoaderLock = (void *)GetProcAddress(hntdll,
"LdrUnlockLoaderLock");
+ pRtlGetCompressionWorkSpaceSize = (void *)GetProcAddress(hntdll,
"RtlGetCompressionWorkSpaceSize");
+ pRtlDecompressBuffer = (void *)GetProcAddress(hntdll,
"RtlDecompressBuffer");
+ pRtlDecompressFragment = (void *)GetProcAddress(hntdll,
"RtlDecompressFragment");
+ pRtlCompressBuffer = (void *)GetProcAddress(hntdll,
"RtlCompressBuffer");
}
hkernel32 = LoadLibraryA("kernel32.dll");
ok(hkernel32 != 0, "LoadLibrary failed\n");
@@ -148,6 +162,46 @@
strcpy((char*)src_aligned_block, src_src);
ok(strlen(src) == 15, "Source must be 16 bytes long!\n");
}
+
+#ifdef __i386__
+const char stdcall3_thunk[] =
+ "\x56" /* push %esi */
+ "\x89\xE6" /* mov %esp, %esi */
+ "\xFF\x74\x24\x14" /* pushl 20(%esp) */
+ "\xFF\x74\x24\x14" /* pushl 20(%esp) */
+ "\xFF\x74\x24\x14" /* pushl 20(%esp) */
+ "\xFF\x54\x24\x14" /* calll 20(%esp) */
+ "\x89\xF0" /* mov %esi, %eax */
+ "\x29\xE0" /* sub %esp, %eax */
+ "\x89\xF4" /* mov %esi, %esp */
+ "\x5E" /* pop %esi */
+ "\xC2\x10\x00" /* ret $16 */
+;
+
+static INT (WINAPI *call_stdcall_func3)(PVOID func, PVOID arg0, DWORD arg1, DWORD arg2) =
NULL;
+
+static void test_WinSqm(void)
+{
+ INT args;
+
+ if (!pWinSqmStartSession)
+ {
+ win_skip("WinSqmStartSession() is not available\n");
+ return;
+ }
+
+ call_stdcall_func3 = (void*) VirtualAlloc( NULL, sizeof(stdcall3_thunk) - 1,
MEM_COMMIT,
+ PAGE_EXECUTE_READWRITE );
+ memcpy( call_stdcall_func3, stdcall3_thunk, sizeof(stdcall3_thunk) - 1 );
+
+ args = 3 - call_stdcall_func3( pWinSqmStartSession, NULL, 0, 0 ) / 4;
+ ok(args == 3, "WinSqmStartSession expected to take %d arguments instead of
3\n", args);
+ args = 3 - call_stdcall_func3( pWinSqmEndSession, NULL, 0, 0 ) / 4;
+ ok(args == 1, "WinSqmEndSession expected to take %d arguments instead of
1\n", args);
+
+ VirtualFree( call_stdcall_func3, 0, MEM_RELEASE );
+}
+#endif
#define COMP(str1,str2,cmplen,len) size = pRtlCompareMemory(str1, str2, cmplen); \
ok(size == len, "Expected %ld, got %ld\n", size, (SIZE_T)len)
@@ -1492,6 +1546,94 @@
}
}
+static void test_RtlIpv4StringToAddressEx(void)
+{
+ NTSTATUS res;
+ IN_ADDR ip, expected_ip;
+ USHORT port;
+ struct
+ {
+ PCSTR address;
+ NTSTATUS res;
+ int ip[4];
+ USHORT port;
+ } tests[] =
+ {
+ { "", STATUS_INVALID_PARAMETER, { -1 }, 0xdead
},
+ { " ", STATUS_INVALID_PARAMETER, { -1 }, 0xdead
},
+ { "1.1.1.1:", STATUS_INVALID_PARAMETER, { 1, 1, 1, 1 }, 0xdead
},
+ { "1.1.1.1+", STATUS_INVALID_PARAMETER, { 1, 1, 1, 1 }, 0xdead
},
+ { "1.1.1.1:1", STATUS_SUCCESS, { 1, 1, 1, 1 }, 0x100
},
+ { "0.0.0.0:0", STATUS_INVALID_PARAMETER, { 0, 0, 0, 0 }, 0xdead
},
+ { "0.0.0.0:1", STATUS_SUCCESS, { 0, 0, 0, 0 }, 0x100
},
+ { "1.2.3.4:65535", STATUS_SUCCESS, { 1, 2, 3, 4 }, 65535
},
+ { "1.2.3.4:65536", STATUS_INVALID_PARAMETER, { 1, 2, 3, 4 }, 0xdead
},
+ { "1.2.3.4:0xffff", STATUS_SUCCESS, { 1, 2, 3, 4 }, 65535
},
+ { "1.2.3.4:0XfFfF", STATUS_SUCCESS, { 1, 2, 3, 4 }, 65535
},
+ { "1.2.3.4:011064", STATUS_SUCCESS, { 1, 2, 3, 4 }, 0x3412
},
+ { "1.2.3.4:1234a", STATUS_INVALID_PARAMETER, { 1, 2, 3, 4 }, 0xdead
},
+ { "1.2.3.4:1234+", STATUS_INVALID_PARAMETER, { 1, 2, 3, 4 }, 0xdead
},
+ { "1.2.3.4: 1234", STATUS_INVALID_PARAMETER, { 1, 2, 3, 4 }, 0xdead
},
+ { "1.2.3.4:\t1234", STATUS_INVALID_PARAMETER, { 1, 2, 3, 4 }, 0xdead
},
+ };
+ const int testcount = sizeof(tests) / sizeof(tests[0]);
+ int i, Strict;
+
+ if (!pRtlIpv4StringToAddressExA)
+ {
+ skip("RtlIpv4StringToAddressEx not available\n");
+ return;
+ }
+
+ /* do not crash, and do not touch the ip / port. */
+ ip.S_un.S_addr = 0xabababab;
+ port = 0xdead;
+ res = pRtlIpv4StringToAddressExA(NULL, FALSE, &ip, &port);
+ ok(res == STATUS_INVALID_PARAMETER, "[null address] res = 0x%08x, expected
0x%08x\n", res, STATUS_INVALID_PARAMETER);
+ ok(ip.S_un.S_addr == 0xabababab, "RtlIpv4StringToAddressExA should not touch the
ip!, ip == %x\n", ip.S_un.S_addr);
+ ok(port == 0xdead, "RtlIpv4StringToAddressExA should not touch the port!, port
== %x\n", port);
+
+ port = 0xdead;
+ res = pRtlIpv4StringToAddressExA("1.1.1.1", FALSE, NULL, &port);
+ ok(res == STATUS_INVALID_PARAMETER, "[null ip] res = 0x%08x, expected
0x%08x\n", res, STATUS_INVALID_PARAMETER);
+ ok(port == 0xdead, "RtlIpv4StringToAddressExA should not touch the port!, port
== %x\n", port);
+
+ ip.S_un.S_addr = 0xabababab;
+ port = 0xdead;
+ res = pRtlIpv4StringToAddressExA("1.1.1.1", FALSE, &ip, NULL);
+ ok(res == STATUS_INVALID_PARAMETER, "[null port] res = 0x%08x, expected
0x%08x\n", res, STATUS_INVALID_PARAMETER);
+ ok(ip.S_un.S_addr == 0xabababab, "RtlIpv4StringToAddressExA should not touch the
ip!, ip == %x\n", ip.S_un.S_addr);
+ ok(port == 0xdead, "RtlIpv4StringToAddressExA should not touch the port!, port
== %x\n", port);
+
+ for (i = 0; i < testcount; i++)
+ {
+ /* Strict is only relevant for the ip address, so make sure that it does not
influence the port */
+ for (Strict = 0; Strict < 2; Strict++)
+ {
+ ip.S_un.S_addr = 0xabababab;
+ port = 0xdead;
+ res = pRtlIpv4StringToAddressExA(tests[i].address, Strict, &ip,
&port);
+ if (tests[i].ip[0] == -1)
+ {
+ expected_ip.S_un.S_addr = 0xabababab;
+ }
+ else
+ {
+ expected_ip.S_un.S_un_b.s_b1 = tests[i].ip[0];
+ expected_ip.S_un.S_un_b.s_b2 = tests[i].ip[1];
+ expected_ip.S_un.S_un_b.s_b3 = tests[i].ip[2];
+ expected_ip.S_un.S_un_b.s_b4 = tests[i].ip[3];
+ }
+ ok(res == tests[i].res, "[%s] res = 0x%08x, expected 0x%08x\n",
+ tests[i].address, res, tests[i].res);
+ ok(ip.S_un.S_addr == expected_ip.S_un.S_addr, "[%s] ip = %08x, expected
%08x\n",
+ tests[i].address, ip.S_un.S_addr, expected_ip.S_un.S_addr);
+ ok(port == tests[i].port, "[%s] port = %u, expected %u\n",
+ tests[i].address, port, tests[i].port);
+ }
+ }
+}
+
static void test_LdrAddRefDll(void)
{
HMODULE mod, mod2;
@@ -1599,9 +1741,744 @@
pLdrUnlockLoaderLock(0, magic);
}
+static void test_RtlGetCompressionWorkSpaceSize(void)
+{
+ ULONG compress_workspace, decompress_workspace;
+ NTSTATUS status;
+
+ if (!pRtlGetCompressionWorkSpaceSize)
+ {
+ win_skip("RtlGetCompressionWorkSpaceSize is not available\n");
+ return;
+ }
+
+ status = pRtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_NONE,
&compress_workspace,
+ &decompress_workspace);
+ ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n",
status);
+
+ status = pRtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_DEFAULT,
&compress_workspace,
+ &decompress_workspace);
+ ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n",
status);
+
+ status = pRtlGetCompressionWorkSpaceSize(0xFF, &compress_workspace,
&decompress_workspace);
+ ok(status == STATUS_UNSUPPORTED_COMPRESSION, "got wrong status 0x%08x\n",
status);
+
+ compress_workspace = decompress_workspace = 0xdeadbeef;
+ status = pRtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1,
&compress_workspace,
+ &decompress_workspace);
+ ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
+ ok(compress_workspace != 0, "got wrong compress_workspace %d\n",
compress_workspace);
+ ok(decompress_workspace == 0x1000, "got wrong decompress_workspace %d\n",
decompress_workspace);
+
+ compress_workspace = decompress_workspace = 0xdeadbeef;
+ status = pRtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1 |
COMPRESSION_ENGINE_MAXIMUM,
+ &compress_workspace,
&decompress_workspace);
+ ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
+ ok(compress_workspace != 0, "got wrong compress_workspace %d\n",
compress_workspace);
+ ok(decompress_workspace == 0x1000, "got wrong decompress_workspace %d\n",
decompress_workspace);
+}
+
+/* helper for test_RtlDecompressBuffer, checks if a chunk is incomplete */
+static BOOL is_incomplete_chunk(const UCHAR *compressed, ULONG compressed_size, BOOL
check_all)
+{
+ ULONG chunk_size;
+ if (compressed_size <= sizeof(WORD))
+ return TRUE;
+ while (compressed_size >= sizeof(WORD))
+ {
+ chunk_size = (*(WORD *)compressed & 0xFFF) + 1;
+ if (compressed_size < sizeof(WORD) + chunk_size)
+ return TRUE;
+ if (!check_all)
+ break;
+ compressed += sizeof(WORD) + chunk_size;
+ compressed_size -= sizeof(WORD) + chunk_size;
+ }
+ return FALSE;
+}
+
+#define DECOMPRESS_BROKEN_TRUNCATED 1
+#define DECOMPRESS_BROKEN_FRAGMENT0 2
+#define DECOMPRESS_BROKEN_FRAGMENT1 4
+#define DECOMPRESS_BROKEN_FRAGMENT4095 8
+
+static void test_RtlDecompressBuffer(void)
+{
+ static const UCHAR test_multiple_chunks[] = {0x03, 0x30, 'W', 'i',
'n', 'e',
+ 0x03, 0x30, 'W', 'i',
'n', 'e'};
+ static const struct
+ {
+ UCHAR compressed[32];
+ ULONG compressed_size;
+ NTSTATUS status;
+ UCHAR uncompressed[32];
+ ULONG uncompressed_size;
+ DWORD broken_flags;
+ }
+ test_lznt[] =
+ {
+ /* 4 byte uncompressed chunk */
+ {
+ {0x03, 0x30, 'W', 'i', 'n', 'e'},
+ 6,
+ STATUS_SUCCESS,
+ "Wine",
+ 4,
+ DECOMPRESS_BROKEN_FRAGMENT4095 |
+ DECOMPRESS_BROKEN_FRAGMENT1 |
+ DECOMPRESS_BROKEN_FRAGMENT0
+ },
+ /* 8 byte uncompressed chunk */
+ {
+ {0x07, 0x30, 'W', 'i', 'n', 'e', 'W',
'i', 'n', 'e'},
+ 10,
+ STATUS_SUCCESS,
+ "WineWine",
+ 8,
+ DECOMPRESS_BROKEN_FRAGMENT4095 |
+ DECOMPRESS_BROKEN_FRAGMENT1 |
+ DECOMPRESS_BROKEN_FRAGMENT0
+ },
+ /* 4 byte compressed chunk */
+ {
+ {0x04, 0xB0, 0x00, 'W', 'i', 'n', 'e'},
+ 7,
+ STATUS_SUCCESS,
+ "Wine",
+ 4
+ },
+ /* 8 byte compressed chunk */
+ {
+ {0x08, 0xB0, 0x00, 'W', 'i', 'n', 'e',
'W', 'i', 'n', 'e'},
+ 11,
+ STATUS_SUCCESS,
+ "WineWine",
+ 8
+ },
+ /* compressed chunk using backwards reference */
+ {
+ {0x06, 0xB0, 0x10, 'W', 'i', 'n', 'e', 0x01,
0x30},
+ 9,
+ STATUS_SUCCESS,
+ "WineWine",
+ 8,
+ DECOMPRESS_BROKEN_TRUNCATED
+ },
+ /* compressed chunk using backwards reference with length > bytes_read */
+ {
+ {0x06, 0xB0, 0x10, 'W', 'i', 'n', 'e', 0x05,
0x30},
+ 9,
+ STATUS_SUCCESS,
+ "WineWineWine",
+ 12,
+ DECOMPRESS_BROKEN_TRUNCATED
+ },
+ /* same as above, but unused bits != 0 */
+ {
+ {0x06, 0xB0, 0x30, 'W', 'i', 'n', 'e', 0x01,
0x30},
+ 9,
+ STATUS_SUCCESS,
+ "WineWine",
+ 8,
+ DECOMPRESS_BROKEN_TRUNCATED
+ },
+ /* compressed chunk without backwards reference and unused bits != 0 */
+ {
+ {0x01, 0xB0, 0x02, 'W'},
+ 4,
+ STATUS_SUCCESS,
+ "W",
+ 1
+ },
+ /* termination sequence after first chunk */
+ {
+ {0x03, 0x30, 'W', 'i', 'n', 'e', 0x00, 0x00,
0x03, 0x30, 'W', 'i', 'n', 'e'},
+ 14,
+ STATUS_SUCCESS,
+ "Wine",
+ 4,
+ DECOMPRESS_BROKEN_FRAGMENT4095 |
+ DECOMPRESS_BROKEN_FRAGMENT1 |
+ DECOMPRESS_BROKEN_FRAGMENT0
+ },
+ /* compressed chunk using backwards reference with 4 bit offset, 12 bit length
*/
+ {
+ {0x14, 0xB0, 0x00, 'A', 'B', 'C', 'D',
'E', 'F', 'G', 'H',
+ 0x00, 'I', 'J', 'K', 'L',
'M', 'N', 'O', 'P',
+ 0x01, 0x01, 0xF0},
+ 23,
+ STATUS_SUCCESS,
+ "ABCDEFGHIJKLMNOPABCD",
+ 20,
+ DECOMPRESS_BROKEN_TRUNCATED
+ },
+ /* compressed chunk using backwards reference with 5 bit offset, 11 bit length
*/
+ {
+ {0x15, 0xB0, 0x00, 'A', 'B', 'C', 'D',
'E', 'F', 'G', 'H',
+ 0x00, 'I', 'J', 'K', 'L',
'M', 'N', 'O', 'P',
+ 0x02, 'A', 0x00, 0x78},
+ 24,
+ STATUS_SUCCESS,
+ "ABCDEFGHIJKLMNOPABCD",
+ 20,
+ DECOMPRESS_BROKEN_TRUNCATED
+ },
+ /* uncompressed chunk with invalid magic */
+ {
+ {0x03, 0x20, 'W', 'i', 'n', 'e'},
+ 6,
+ STATUS_SUCCESS,
+ "Wine",
+ 4,
+ DECOMPRESS_BROKEN_FRAGMENT4095 |
+ DECOMPRESS_BROKEN_FRAGMENT1 |
+ DECOMPRESS_BROKEN_FRAGMENT0
+ },
+ /* compressed chunk with invalid magic */
+ {
+ {0x04, 0xA0, 0x00, 'W', 'i', 'n', 'e'},
+ 7,
+ STATUS_SUCCESS,
+ "Wine",
+ 4
+ },
+ /* garbage byte after end of buffer */
+ {
+ {0x00, 0xB0, 0x02, 0x01},
+ 4,
+ STATUS_SUCCESS,
+ "",
+ 0
+ },
+ /* empty compressed chunk */
+ {
+ {0x00, 0xB0, 0x00},
+ 3,
+ STATUS_SUCCESS,
+ "",
+ 0
+ },
+ /* empty compressed chunk with unused bits != 0 */
+ {
+ {0x00, 0xB0, 0x01},
+ 3,
+ STATUS_SUCCESS,
+ "",
+ 0
+ },
+ /* empty input buffer */
+ {
+ {0},
+ 0,
+ STATUS_BAD_COMPRESSION_BUFFER,
+ },
+ /* incomplete chunk header */
+ {
+ {0x01},
+ 1,
+ STATUS_BAD_COMPRESSION_BUFFER
+ },
+ /* incomplete chunk header */
+ {
+ {0x00, 0x30},
+ 2,
+ STATUS_BAD_COMPRESSION_BUFFER
+ },
+ /* compressed chunk with invalid backwards reference */
+ {
+ {0x06, 0xB0, 0x10, 'W', 'i', 'n', 'e', 0x05,
0x40},
+ 9,
+ STATUS_BAD_COMPRESSION_BUFFER
+ },
+ /* compressed chunk with incomplete backwards reference */
+ {
+ {0x05, 0xB0, 0x10, 'W', 'i', 'n', 'e',
0x05},
+ 8,
+ STATUS_BAD_COMPRESSION_BUFFER
+ },
+ /* incomplete uncompressed chunk */
+ {
+ {0x07, 0x30, 'W', 'i', 'n', 'e'},
+ 6,
+ STATUS_BAD_COMPRESSION_BUFFER
+ },
+ /* incomplete compressed chunk */
+ {
+ {0x08, 0xB0, 0x00, 'W', 'i', 'n', 'e'},
+ 7,
+ STATUS_BAD_COMPRESSION_BUFFER
+ },
+ /* two compressed chunks, the second one incomplete */
+ {
+ {0x00, 0xB0, 0x02, 0x00, 0xB0},
+ 5,
+ STATUS_BAD_COMPRESSION_BUFFER,
+ }
+ };
+
+ static UCHAR buf[0x2000], workspace[0x1000];
+ NTSTATUS status, expected_status;
+ ULONG final_size;
+ int i;
+
+ if (!pRtlDecompressBuffer || !pRtlDecompressFragment)
+ {
+ win_skip("RtlDecompressBuffer or RtlDecompressFragment is not
available\n");
+ return;
+ }
+
+ /* test compression format / engine */
+ final_size = 0xdeadbeef;
+ status = pRtlDecompressBuffer(COMPRESSION_FORMAT_NONE, buf, sizeof(buf) - 1,
test_lznt[0].compressed,
+ test_lznt[0].compressed_size, &final_size);
+ ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n",
status);
+ ok(final_size == 0xdeadbeef, "got wrong final_size %d\n", final_size);
+
+ final_size = 0xdeadbeef;
+ status = pRtlDecompressBuffer(COMPRESSION_FORMAT_DEFAULT, buf, sizeof(buf) - 1,
test_lznt[0].compressed,
+ test_lznt[0].compressed_size, &final_size);
+ ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n",
status);
+ ok(final_size == 0xdeadbeef, "got wrong final_size %d\n", final_size);
+
+ final_size = 0xdeadbeef;
+ status = pRtlDecompressBuffer(0xFF, buf, sizeof(buf) - 1, test_lznt[0].compressed,
+ test_lznt[0].compressed_size, &final_size);
+ ok(status == STATUS_UNSUPPORTED_COMPRESSION, "got wrong status 0x%08x\n",
status);
+ ok(final_size == 0xdeadbeef, "got wrong final_size %d\n", final_size);
+
+ /* regular tests for RtlDecompressBuffer */
+ for (i = 0; i < sizeof(test_lznt) / sizeof(test_lznt[0]); i++)
+ {
+ trace("Running test %d (compressed_size=%d, compressed_size=%d,
status=%d)\n",
+ i, test_lznt[i].compressed_size, test_lznt[i].compressed_size,
test_lznt[i].status);
+
+ /* test with very big buffer */
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf),
test_lznt[i].compressed,
+ test_lznt[i].compressed_size, &final_size);
+ ok(status == test_lznt[i].status, "%d: got wrong status 0x%08x\n", i,
status);
+ if (!status)
+ {
+ ok(final_size == test_lznt[i].uncompressed_size,
+ "%d: got wrong final_size %d\n", i, final_size);
+ ok(!memcmp(buf, test_lznt[i].uncompressed, test_lznt[i].uncompressed_size),
+ "%d: got wrong decoded data\n", i);
+ ok(buf[test_lznt[i].uncompressed_size] == 0x11,
+ "%d: buf[%d] overwritten\n", i,
test_lznt[i].uncompressed_size);
+ }
+
+ /* test that modifier for compression engine is ignored */
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1 |
COMPRESSION_ENGINE_MAXIMUM, buf, sizeof(buf),
+ test_lznt[i].compressed,
test_lznt[i].compressed_size, &final_size);
+ ok(status == test_lznt[i].status, "%d: got wrong status 0x%08x\n", i,
status);
+ if (!status)
+ {
+ ok(final_size == test_lznt[i].uncompressed_size,
+ "%d: got wrong final_size %d\n", i, final_size);
+ ok(!memcmp(buf, test_lznt[i].uncompressed, test_lznt[i].uncompressed_size),
+ "%d: got wrong decoded data\n", i);
+ ok(buf[test_lznt[i].uncompressed_size] == 0x11,
+ "%d: buf[%d] overwritten\n", i,
test_lznt[i].uncompressed_size);
+ }
+
+ /* test with expected output size */
+ if (test_lznt[i].uncompressed_size > 0)
+ {
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf,
test_lznt[i].uncompressed_size,
+ test_lznt[i].compressed,
test_lznt[i].compressed_size, &final_size);
+ ok(status == test_lznt[i].status, "%d: got wrong status 0x%08x\n",
i, status);
+ if (!status)
+ {
+ ok(final_size == test_lznt[i].uncompressed_size,
+ "%d: got wrong final_size %d\n", i, final_size);
+ ok(!memcmp(buf, test_lznt[i].uncompressed,
test_lznt[i].uncompressed_size),
+ "%d: got wrong decoded data\n", i);
+ ok(buf[test_lznt[i].uncompressed_size] == 0x11,
+ "%d: buf[%d] overwritten\n", i,
test_lznt[i].uncompressed_size);
+ }
+ }
+
+ /* test with smaller output size */
+ if (test_lznt[i].uncompressed_size > 1)
+ {
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf,
test_lznt[i].uncompressed_size - 1,
+ test_lznt[i].compressed,
test_lznt[i].compressed_size, &final_size);
+ ok(status == test_lznt[i].status || broken(status ==
STATUS_BAD_COMPRESSION_BUFFER &&
+ (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_TRUNCATED)), "%d:
got wrong status 0x%08x\n", i, status);
+ if (!status)
+ {
+ ok(final_size == test_lznt[i].uncompressed_size - 1,
+ "%d: got wrong final_size %d\n", i, final_size);
+ ok(!memcmp(buf, test_lznt[i].uncompressed, test_lznt[i].uncompressed_size
- 1),
+ "%d: got wrong decoded data\n", i);
+ ok(buf[test_lznt[i].uncompressed_size - 1] == 0x11,
+ "%d: buf[%d] overwritten\n", i,
test_lznt[i].uncompressed_size - 1);
+ }
+ }
+
+ /* test with zero output size */
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, 0,
test_lznt[i].compressed,
+ test_lznt[i].compressed_size, &final_size);
+ if (is_incomplete_chunk(test_lznt[i].compressed, test_lznt[i].compressed_size,
FALSE))
+ {
+ ok(status == STATUS_BAD_COMPRESSION_BUFFER, "%d: got wrong status
0x%08x\n", i, status);
+ }
+ else
+ {
+ ok(status == STATUS_SUCCESS, "%d: got wrong status 0x%08x\n", i,
status);
+ ok(final_size == 0, "%d: got wrong final_size %d\n", i,
final_size);
+ ok(buf[0] == 0x11, "%d: buf[%d] overwritten\n", i,
test_lznt[i].uncompressed_size);
+ }
+
+ /* test RtlDecompressBuffer with offset = 0 */
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf),
test_lznt[i].compressed,
+ test_lznt[i].compressed_size, 0, &final_size,
workspace);
+ ok(status == test_lznt[i].status || broken(status ==
STATUS_BAD_COMPRESSION_BUFFER &&
+ (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_FRAGMENT0)), "%d: got
wrong status 0x%08x\n", i, status);
+ if (!status)
+ {
+ ok(final_size == test_lznt[i].uncompressed_size,
+ "%d: got wrong final_size %d\n", i, final_size);
+ ok(!memcmp(buf, test_lznt[i].uncompressed, test_lznt[i].uncompressed_size),
+ "%d: got wrong decoded data\n", i);
+ ok(buf[test_lznt[i].uncompressed_size] == 0x11,
+ "%d: buf[%d] overwritten\n", i,
test_lznt[i].uncompressed_size);
+ }
+
+ /* test RtlDecompressBuffer with offset = 1 */
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf),
test_lznt[i].compressed,
+ test_lznt[i].compressed_size, 1, &final_size,
workspace);
+ ok(status == test_lznt[i].status || broken(status ==
STATUS_BAD_COMPRESSION_BUFFER &&
+ (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_FRAGMENT1)), "%d: got
wrong status 0x%08x\n", i, status);
+ if (!status)
+ {
+ if (test_lznt[i].uncompressed_size == 0)
+ {
+ todo_wine
+ ok(final_size == 4095,
+ "%d: got wrong final size %d\n", i, final_size);
+ /* Buffer doesn't contain any useful value on Windows */
+ ok(buf[4095] == 0x11,
+ "%d: buf[4095] overwritten\n", i);
+ }
+ else
+ {
+ ok(final_size == test_lznt[i].uncompressed_size - 1,
+ "%d: got wrong final_size %d\n", i, final_size);
+ ok(!memcmp(buf, test_lznt[i].uncompressed + 1,
test_lznt[i].uncompressed_size - 1),
+ "%d: got wrong decoded data\n", i);
+ ok(buf[test_lznt[i].uncompressed_size - 1] == 0x11,
+ "%d: buf[%d] overwritten\n", i,
test_lznt[i].uncompressed_size - 1);
+ }
+ }
+
+ /* test RtlDecompressBuffer with offset = 4095 */
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf),
test_lznt[i].compressed,
+ test_lznt[i].compressed_size, 4095,
&final_size, workspace);
+ ok(status == test_lznt[i].status || broken(status ==
STATUS_BAD_COMPRESSION_BUFFER &&
+ (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_FRAGMENT4095)), "%d:
got wrong status 0x%08x\n", i, status);
+ if (!status)
+ {
+ todo_wine
+ ok(final_size == 1,
+ "%d: got wrong final size %d\n", i, final_size);
+ todo_wine
+ ok(buf[0] == 0,
+ "%d: padding is not zero\n", i);
+ ok(buf[1] == 0x11,
+ "%d: buf[1] overwritten\n", i);
+ }
+
+ /* test RtlDecompressBuffer with offset = 4096 */
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf),
test_lznt[i].compressed,
+ test_lznt[i].compressed_size, 4096,
&final_size, workspace);
+ expected_status = is_incomplete_chunk(test_lznt[i].compressed,
test_lznt[i].compressed_size, TRUE) ?
+ test_lznt[i].status : STATUS_SUCCESS;
+ ok(status == expected_status, "%d: got wrong status 0x%08x, expected
0x%08x\n", i, status, expected_status);
+ if (!status)
+ {
+ ok(final_size == 0,
+ "%d: got wrong final size %d\n", i, final_size);
+ ok(buf[0] == 0x11,
+ "%d: buf[4096] overwritten\n", i);
+ }
+ }
+
+ /* test decoding of multiple chunks with pRtlDecompressBuffer */
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf),
test_multiple_chunks,
+ sizeof(test_multiple_chunks), &final_size);
+ ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
+ if (!status)
+ {
+ ok(final_size == 4100, "got wrong final_size %d\n", final_size);
+ ok(!memcmp(buf, "Wine", 4), "got wrong decoded data at offset
0\n");
+ ok(buf[4] == 0 && buf[4095] == 0, "padding is not zero\n");
+ ok(!memcmp(buf + 4096, "Wine", 4), "got wrong decoded data at
offset 4096\n");
+ ok(buf[4100] == 0x11, "buf[4100] overwritten\n");
+ }
+
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, 4097,
test_multiple_chunks,
+ sizeof(test_multiple_chunks), &final_size);
+ ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
+ if (!status)
+ {
+ ok(final_size == 4097, "got wrong final_size %d\n", final_size);
+ ok(!memcmp(buf, "Wine", 4), "got wrong decoded data at offset
0\n");
+ ok(buf[4] == 0 && buf[4095] == 0, "padding is not zero\n");
+ ok(buf[4096], "got wrong decoded data at offset 4096\n");
+ ok(buf[4097] == 0x11, "buf[4097] overwritten\n");
+ }
+
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, 4096,
test_multiple_chunks,
+ sizeof(test_multiple_chunks), &final_size);
+ ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
+ if (!status)
+ {
+ ok(final_size == 4, "got wrong final_size %d\n", final_size);
+ ok(!memcmp(buf, "Wine", 4), "got wrong decoded data at offset
0\n");
+ ok(buf[4] == 0x11, "buf[4] overwritten\n");
+ }
+
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, 4,
test_multiple_chunks,
+ sizeof(test_multiple_chunks), &final_size);
+ ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
+ if (!status)
+ {
+ ok(final_size == 4, "got wrong final_size %d\n", final_size);
+ ok(!memcmp(buf, "Wine", 4), "got wrong decoded data at offset
0\n");
+ ok(buf[4] == 0x11, "buf[4] overwritten\n");
+ }
+
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, 3,
test_multiple_chunks,
+ sizeof(test_multiple_chunks), &final_size);
+ ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
+ if (!status)
+ {
+ ok(final_size == 3, "got wrong final_size %d\n", final_size);
+ ok(!memcmp(buf, "Wine", 3), "got wrong decoded data at offset
0\n");
+ ok(buf[3] == 0x11, "buf[3] overwritten\n");
+ }
+
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, 0,
test_multiple_chunks,
+ sizeof(test_multiple_chunks), &final_size);
+ ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
+ if (!status)
+ {
+ ok(final_size == 0, "got wrong final_size %d\n", final_size);
+ ok(buf[0] == 0x11, "buf[0] overwritten\n");
+ }
+
+ /* test multiple chunks in combination with RtlDecompressBuffer and offset=1 */
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf),
test_multiple_chunks,
+ sizeof(test_multiple_chunks), 1, &final_size,
workspace);
+ ok(status == STATUS_SUCCESS || broken(status == STATUS_BAD_COMPRESSION_BUFFER),
+ "got wrong status 0x%08x\n", status);
+ if (!status)
+ {
+ ok(final_size == 4099, "got wrong final_size %d\n", final_size);
+ ok(!memcmp(buf, "ine", 3), "got wrong decoded data at offset
0\n");
+ ok(buf[3] == 0 && buf[4094] == 0, "padding is not zero\n");
+ ok(!memcmp(buf + 4095, "Wine", 4), "got wrong decoded data at
offset 4095\n");
+ ok(buf[4099] == 0x11, "buf[4099] overwritten\n");
+ }
+
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, 4096,
test_multiple_chunks,
+ sizeof(test_multiple_chunks), 1, &final_size,
workspace);
+ ok(status == STATUS_SUCCESS || broken(status == STATUS_BAD_COMPRESSION_BUFFER),
+ "got wrong status 0x%08x\n", status);
+ if (!status)
+ {
+ ok(final_size == 4096, "got wrong final_size %d\n", final_size);
+ ok(!memcmp(buf, "ine", 3), "got wrong decoded data at offset
0\n");
+ ok(buf[3] == 0 && buf[4094] == 0, "padding is not zero\n");
+ ok(buf[4095] == 'W', "got wrong decoded data at offset
4095\n");
+ ok(buf[4096] == 0x11, "buf[4096] overwritten\n");
+ }
+
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, 4095,
test_multiple_chunks,
+ sizeof(test_multiple_chunks), 1, &final_size,
workspace);
+ ok(status == STATUS_SUCCESS || broken(status == STATUS_BAD_COMPRESSION_BUFFER),
+ "got wrong status 0x%08x\n", status);
+ if (!status)
+ {
+ ok(final_size == 3, "got wrong final_size %d\n", final_size);
+ ok(!memcmp(buf, "ine", 3), "got wrong decoded data at offset
0\n");
+ ok(buf[4] == 0x11, "buf[4] overwritten\n");
+ }
+
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, 3,
test_multiple_chunks,
+ sizeof(test_multiple_chunks), 1, &final_size,
workspace);
+ ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
+ if (!status)
+ {
+ ok(final_size == 3, "got wrong final_size %d\n", final_size);
+ ok(!memcmp(buf, "ine", 3), "got wrong decoded data at offset
0\n");
+ ok(buf[3] == 0x11, "buf[3] overwritten\n");
+ }
+
+ /* test multiple chunks in combination with RtlDecompressBuffer and offset=4 */
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf),
test_multiple_chunks,
+ sizeof(test_multiple_chunks), 4, &final_size,
workspace);
+ ok(status == STATUS_SUCCESS || broken(status == STATUS_BAD_COMPRESSION_BUFFER),
+ "got wrong status 0x%08x\n", status);
+ if (!status)
+ {
+ ok(final_size == 4096, "got wrong final_size %d\n", final_size);
+ ok(buf[0] == 0 && buf[4091] == 0, "padding is not zero\n");
+ ok(!memcmp(buf + 4092, "Wine", 4), "got wrong decoded data at
offset 4092\n");
+ ok(buf[4096] == 0x11, "buf[4096] overwritten\n");
+ }
+
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf),
test_multiple_chunks,
+ sizeof(test_multiple_chunks), 4095, &final_size,
workspace);
+ ok(status == STATUS_SUCCESS || broken(status == STATUS_BAD_COMPRESSION_BUFFER),
+ "got wrong status 0x%08x\n", status);
+ if (!status)
+ {
+ ok(final_size == 5, "got wrong final_size %d\n", final_size);
+ ok(buf[0] == 0, "padding is not zero\n");
+ ok(!memcmp(buf + 1, "Wine", 4), "got wrong decoded data at offset
1\n");
+ ok(buf[5] == 0x11, "buf[5] overwritten\n");
+ }
+
+ final_size = 0xdeadbeef;
+ memset(buf, 0x11, sizeof(buf));
+ status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf),
test_multiple_chunks,
+ sizeof(test_multiple_chunks), 4096, &final_size,
workspace);
+ ok(status == STATUS_SUCCESS || broken(status == STATUS_BAD_COMPRESSION_BUFFER),
+ "got wrong status 0x%08x\n", status);
+ if (!status)
+ {
+ ok(final_size == 4, "got wrong final_size %d\n", final_size);
+ ok(!memcmp(buf, "Wine", 4), "got wrong decoded data at offset
0\n");
+ ok(buf[4] == 0x11, "buf[4] overwritten\n");
+ }
+
+}
+
+static void test_RtlCompressBuffer(void)
+{
+ ULONG compress_workspace, decompress_workspace;
+ static const UCHAR test_buffer[] = "WineWineWine";
+ static UCHAR buf1[0x1000], buf2[0x1000], *workspace;
+ ULONG final_size, buf_size;
+ NTSTATUS status;
+
+ if (!pRtlCompressBuffer || !pRtlGetCompressionWorkSpaceSize)
+ {
+ win_skip("RtlCompressBuffer or RtlGetCompressionWorkSpaceSize is not
available\n");
+ return;
+ }
+
+ compress_workspace = decompress_workspace = 0xdeadbeef;
+ status = pRtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1,
&compress_workspace,
+ &decompress_workspace);
+ ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
+ ok(compress_workspace != 0, "got wrong compress_workspace %d\n",
compress_workspace);
+
+ workspace = HeapAlloc( GetProcessHeap(), 0, compress_workspace );
+ ok(workspace != NULL, "HeapAlloc failed %x\n", GetLastError());
+
+ /* test compression format / engine */
+ final_size = 0xdeadbeef;
+ status = pRtlCompressBuffer(COMPRESSION_FORMAT_NONE, test_buffer,
sizeof(test_buffer),
+ buf1, sizeof(buf1) - 1, 4096, &final_size,
workspace);
+ ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n",
status);
+ ok(final_size == 0xdeadbeef, "got wrong final_size %d\n", final_size);
+
+ final_size = 0xdeadbeef;
+ status = pRtlCompressBuffer(COMPRESSION_FORMAT_DEFAULT, test_buffer,
sizeof(test_buffer),
+ buf1, sizeof(buf1) - 1, 4096, &final_size,
workspace);
+ ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n",
status);
+ ok(final_size == 0xdeadbeef, "got wrong final_size %d\n", final_size);
+
+ final_size = 0xdeadbeef;
+ status = pRtlCompressBuffer(0xFF, test_buffer, sizeof(test_buffer),
+ buf1, sizeof(buf1) - 1, 4096, &final_size,
workspace);
+ ok(status == STATUS_UNSUPPORTED_COMPRESSION, "got wrong status 0x%08x\n",
status);
+ ok(final_size == 0xdeadbeef, "got wrong final_size %d\n", final_size);
+
+ /* test compression */
+ final_size = 0xdeadbeef;
+ memset(buf1, 0x11, sizeof(buf1));
+ status = pRtlCompressBuffer(COMPRESSION_FORMAT_LZNT1, test_buffer,
sizeof(test_buffer),
+ buf1, sizeof(buf1), 4096, &final_size, workspace);
+ ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
+ ok((*(WORD *)buf1 & 0x7000) == 0x3000, "no chunk signature found
%04x\n", *(WORD *)buf1);
+ buf_size = final_size;
+ todo_wine
+ ok(final_size < sizeof(test_buffer), "got wrong final_size %d\n",
final_size);
+
+ /* test decompression */
+ final_size = 0xdeadbeef;
+ memset(buf2, 0x11, sizeof(buf2));
+ status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf2, sizeof(buf2),
+ buf1, buf_size, &final_size);
+ ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
+ ok(final_size == sizeof(test_buffer), "got wrong final_size %d\n",
final_size);
+ ok(!memcmp(buf2, test_buffer, sizeof(test_buffer)), "got wrong decoded
data\n");
+ ok(buf2[sizeof(test_buffer)] == 0x11, "buf[%u] overwritten\n",
(DWORD)sizeof(test_buffer));
+
+ /* buffer too small */
+ final_size = 0xdeadbeef;
+ memset(buf1, 0x11, sizeof(buf1));
+ status = pRtlCompressBuffer(COMPRESSION_FORMAT_LZNT1, test_buffer,
sizeof(test_buffer),
+ buf1, 4, 4096, &final_size, workspace);
+ ok(status == STATUS_BUFFER_TOO_SMALL, "got wrong status 0x%08x\n",
status);
+
+ HeapFree(GetProcessHeap(), 0, workspace);
+}
+
START_TEST(rtl)
{
InitFunctionPtrs();
+
+#ifdef __i386__
+ test_WinSqm();
+#else
+ skip("stdcall-style parameter checks are not supported on this
platform.\n");
+#endif
test_RtlCompareMemory();
test_RtlCompareMemoryUlong();
@@ -1623,6 +2500,10 @@
test_RtlIpv4AddressToString();
test_RtlIpv4AddressToStringEx();
test_RtlIpv4StringToAddress();
+ test_RtlIpv4StringToAddressEx();
test_LdrAddRefDll();
test_LdrLockLoaderLock();
-}
+ test_RtlGetCompressionWorkSpaceSize();
+ test_RtlDecompressBuffer();
+ test_RtlCompressBuffer();
+}
Modified: trunk/rostests/winetests/ntdll/string.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ntdll/string.c?…
==============================================================================
--- trunk/rostests/winetests/ntdll/string.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/ntdll/string.c [iso-8859-1] Tue Mar 10 10:10:04 2015
@@ -1083,8 +1083,8 @@
result = p_atoi64(str2longlong[test_num].str);
if (str2longlong[test_num].overflow)
ok(result == str2longlong[test_num].value ||
- (result == (str2longlong[test_num].overflow == -1) ?
- ULL(0x80000000,0x00000000) : ULL(0x7fffffff,0xffffffff)),
+ (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);
@@ -1108,8 +1108,8 @@
result = p_wtoi64(uni.Buffer);
if (str2longlong[test_num].overflow)
ok(result == str2longlong[test_num].value ||
- (result == (str2longlong[test_num].overflow == -1) ?
- ULL(0x80000000,0x00000000) : ULL(0x7fffffff,0xffffffff)),
+ (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);