Hello Amine,
Although I agreed to sync our stuff with wine staging, I am not sure it
is a good idea to use their tests. My understanding is that patches
present in the wine staging tree implement missing features but did not
yet pass the wine quality requirement. Although it might be worth it for
modules, I'm not sure this is a good idea to include tests which were
not proven as good enough.
Simply put: I don't want to chase unexisting bugs just because we're
using a flaky test suite.
Regards
Jérôme
Le 10/03/2015 11:10, akhaldi(a)svn.reactos.org a écrit :
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);