Author: akhaldi
Date: Sat Sep 20 20:08:51 2014
New Revision: 64209
URL:
http://svn.reactos.org/svn/reactos?rev=64209&view=rev
Log:
[NTDLL_WINETEST]
* Sync with Wine 1.7.27.
CORE-8540
Modified:
trunk/rostests/winetests/ntdll/exception.c
trunk/rostests/winetests/ntdll/file.c
trunk/rostests/winetests/ntdll/pipe.c
trunk/rostests/winetests/ntdll/rtl.c
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] Sat Sep 20 20:08:51 2014
@@ -43,6 +43,7 @@
static NTSTATUS (WINAPI *pNtGetContextThread)(HANDLE,CONTEXT*);
static NTSTATUS (WINAPI *pNtSetContextThread)(HANDLE,CONTEXT*);
static NTSTATUS (WINAPI *pRtlRaiseException)(EXCEPTION_RECORD *rec);
+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 NTSTATUS (WINAPI *pNtReadVirtualMemory)(HANDLE, const void*, void*, SIZE_T,
SIZE_T*);
@@ -390,6 +391,83 @@
run_rtlraiseexception_test(EXCEPTION_INVALID_HANDLE);
}
+static DWORD unwind_expected_eax;
+
+static DWORD unwind_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD
*frame,
+ CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher
)
+{
+ trace("exception: %08x flags:%x addr:%p context: Eip:%x\n",
+ rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
context->Eip);
+
+ ok(rec->ExceptionCode == STATUS_UNWIND, "ExceptionCode is %08x instead of
%08x\n",
+ rec->ExceptionCode, STATUS_UNWIND);
+ ok(rec->ExceptionAddress == (char *)code_mem + 0x22, "ExceptionAddress at %p
instead of %p\n",
+ rec->ExceptionAddress, (char *)code_mem + 0x22);
+ ok(context->Eax == unwind_expected_eax, "context->Eax is %08x instead of
%08x\n",
+ context->Eax, unwind_expected_eax);
+
+ context->Eax += 1;
+ return ExceptionContinueSearch;
+}
+
+static const BYTE call_unwind_code[] = {
+ 0x55, /* push %ebp */
+ 0x53, /* push %ebx */
+ 0x56, /* push %esi */
+ 0x57, /* push %edi */
+ 0xe8, 0x00, 0x00, 0x00, 0x00, /* call 0 */
+ 0x58, /* 0: pop %eax */
+ 0x05, 0x1e, 0x00, 0x00, 0x00, /* add $0x1e,%eax */
+ 0xff, 0x74, 0x24, 0x20, /* push 0x20(%esp) */
+ 0xff, 0x74, 0x24, 0x20, /* push 0x20(%esp) */
+ 0x50, /* push %eax */
+ 0xff, 0x74, 0x24, 0x24, /* push 0x24(%esp) */
+ 0x8B, 0x44, 0x24, 0x24, /* mov 0x24(%esp),%eax */
+ 0xff, 0xd0, /* call *%eax */
+ 0x5f, /* pop %edi */
+ 0x5e, /* pop %esi */
+ 0x5b, /* pop %ebx */
+ 0x5d, /* pop %ebp */
+ 0xc3, /* ret */
+ 0xcc, /* int $3 */
+};
+
+static void test_unwind(void)
+{
+ EXCEPTION_REGISTRATION_RECORD frames[2], *frame2 = &frames[0], *frame1 =
&frames[1];
+ DWORD (*func)(void* function, EXCEPTION_REGISTRATION_RECORD *pEndFrame,
EXCEPTION_RECORD* record, DWORD retval) = code_mem;
+ DWORD retval;
+
+ memcpy(code_mem, call_unwind_code, sizeof(call_unwind_code));
+
+ /* add first unwind handler */
+ frame1->Handler = unwind_handler;
+ frame1->Prev = pNtCurrentTeb()->Tib.ExceptionList;
+ pNtCurrentTeb()->Tib.ExceptionList = frame1;
+
+ /* add second unwind handler */
+ frame2->Handler = unwind_handler;
+ frame2->Prev = pNtCurrentTeb()->Tib.ExceptionList;
+ pNtCurrentTeb()->Tib.ExceptionList = frame2;
+
+ /* test unwind to current frame */
+ unwind_expected_eax = 0xDEAD0000;
+ retval = func(pRtlUnwind, frame2, NULL, 0xDEAD0000);
+ ok(retval == 0xDEAD0000, "RtlUnwind returned eax %08x instead of %08x\n",
retval, 0xDEAD0000);
+ ok(pNtCurrentTeb()->Tib.ExceptionList == frame2, "Exception record points to
%p instead of %p\n",
+ pNtCurrentTeb()->Tib.ExceptionList, frame2);
+
+ /* unwind to frame1 */
+ unwind_expected_eax = 0xDEAD0000;
+ retval = func(pRtlUnwind, frame1, NULL, 0xDEAD0000);
+ ok(retval == 0xDEAD0001, "RtlUnwind returned eax %08x instead of %08x\n",
retval, 0xDEAD0001);
+ ok(pNtCurrentTeb()->Tib.ExceptionList == frame1, "Exception record points to
%p instead of %p\n",
+ pNtCurrentTeb()->Tib.ExceptionList, frame1);
+
+ /* restore original handler */
+ pNtCurrentTeb()->Tib.ExceptionList = frame1->Prev;
+}
+
static DWORD handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
{
@@ -865,6 +943,51 @@
ok(!status, "NtSetContextThread failed with 0x%x\n", status);
}
}
+ else if (de.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT)
+ {
+ int stage;
+ char buffer[64];
+
+ status = pNtReadVirtualMemory(pi.hProcess, &test_stage, &stage,
+ sizeof(stage), &size_read);
+ ok(!status,"NtReadVirtualMemory failed with 0x%x\n", status);
+
+ ok(!de.u.DebugString.fUnicode, "unepxected unicode debug string
event\n");
+ ok(de.u.DebugString.nDebugStringLength < sizeof(buffer) - 1, "buffer
not large enough to hold %d bytes\n",
+ de.u.DebugString.nDebugStringLength);
+
+ memset(buffer, 0, sizeof(buffer));
+ status = pNtReadVirtualMemory(pi.hProcess,
de.u.DebugString.lpDebugStringData, buffer,
+ de.u.DebugString.nDebugStringLength,
&size_read);
+ ok(!status,"NtReadVirtualMemory failed with 0x%x\n", status);
+
+ if (stage == 3 || stage == 4)
+ ok(!strcmp(buffer, "Hello World"), "got unexpected debug
string '%s'\n", buffer);
+ else /* ignore unrelated debug strings like 'SHIMVIEW:
ShimInfo(Complete)' */
+ ok(strstr(buffer, "SHIMVIEW") != NULL, "unexpected stage
%x, got debug string event '%s'\n", stage, buffer);
+
+ if (stage == 4) continuestatus = DBG_EXCEPTION_NOT_HANDLED;
+ }
+ else if (de.dwDebugEventCode == RIP_EVENT)
+ {
+ int stage;
+
+ status = pNtReadVirtualMemory(pi.hProcess, &test_stage, &stage,
+ sizeof(stage), &size_read);
+ ok(!status,"NtReadVirtualMemory failed with 0x%x\n", status);
+
+ if (stage == 5 || stage == 6)
+ {
+ ok(de.u.RipInfo.dwError == 0x11223344, "got unexpected rip error
code %08x, expected %08x\n",
+ de.u.RipInfo.dwError, 0x11223344);
+ ok(de.u.RipInfo.dwType == 0x55667788, "got unexpected rip type
%08x, expected %08x\n",
+ de.u.RipInfo.dwType, 0x55667788);
+ }
+ else
+ ok(FALSE, "unexpected stage %x\n", stage);
+
+ if (stage == 6) continuestatus = DBG_EXCEPTION_NOT_HANDLED;
+ }
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, continuestatus);
@@ -1487,8 +1610,8 @@
func = pRtlLookupFunctionEntry( (ULONG_PTR)code_mem + code_offset + 16, &base,
NULL );
ok( func == NULL,
"RtlLookupFunctionEntry returned unexpected function, expected: NULL, got:
%p\n", func );
- ok( base == 0xdeadbeef,
- "RtlLookupFunctionEntry modified base address, expected: 0xdeadbeef, got:
%lx\n", base );
+ ok( !base || broken(base == 0xdeadbeef),
+ "RtlLookupFunctionEntry modified base address, expected: 0, got:
%lx\n", base );
/* Test with pointer inside of our function */
base = 0xdeadbeef;
@@ -1546,8 +1669,8 @@
func = pRtlLookupFunctionEntry( (ULONG_PTR)code_mem + code_offset + 32, &base,
NULL );
ok( func == NULL,
"RtlLookupFunctionEntry returned unexpected function, expected: NULL, got:
%p\n", func );
- ok( base == 0xdeadbeef,
- "RtlLookupFunctionEntry modified base address, expected: 0xdeadbeef, got:
%lx\n", base );
+ ok( !base || broken(base == 0xdeadbeef),
+ "RtlLookupFunctionEntry modified base address, expected: 0, got:
%lx\n", base );
ok( !count,
"RtlLookupFunctionEntry issued %d unexpected calls to
dynamic_unwind_callback\n", count );
@@ -1572,6 +1695,99 @@
#endif /* __x86_64__ */
+static DWORD outputdebugstring_exceptions;
+
+static LONG CALLBACK outputdebugstring_vectored_handler(EXCEPTION_POINTERS
*ExceptionInfo)
+{
+ PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord;
+ trace("vect. handler %08x addr:%p\n", rec->ExceptionCode,
rec->ExceptionAddress);
+
+ ok(rec->ExceptionCode == DBG_PRINTEXCEPTION_C, "ExceptionCode is %08x instead
of %08x\n",
+ rec->ExceptionCode, DBG_PRINTEXCEPTION_C);
+ ok(rec->NumberParameters == 2, "ExceptionParameters is %d instead of
2\n", rec->NumberParameters);
+ ok(rec->ExceptionInformation[0] == 12, "ExceptionInformation[0] = %d instead
of 12\n", (DWORD)rec->ExceptionInformation[0]);
+ ok(!strcmp((char *)rec->ExceptionInformation[1], "Hello World"),
+ "ExceptionInformation[1] = '%s' instead of 'Hello
World'\n", (char *)rec->ExceptionInformation[1]);
+
+ outputdebugstring_exceptions++;
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+static void test_outputdebugstring(DWORD numexc, BOOL todo)
+{
+ PVOID vectored_handler;
+
+ if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler)
+ {
+ skip("RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler
not found\n");
+ return;
+ }
+
+ vectored_handler = pRtlAddVectoredExceptionHandler(TRUE,
&outputdebugstring_vectored_handler);
+ ok(vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n");
+
+ 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);
+
+ pRtlRemoveVectoredExceptionHandler(vectored_handler);
+}
+
+static DWORD ripevent_exceptions;
+
+static LONG CALLBACK ripevent_vectored_handler(EXCEPTION_POINTERS *ExceptionInfo)
+{
+ PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord;
+ trace("vect. handler %08x addr:%p\n", rec->ExceptionCode,
rec->ExceptionAddress);
+
+ ok(rec->ExceptionCode == DBG_RIPEXCEPTION, "ExceptionCode is %08x instead of
%08x\n",
+ rec->ExceptionCode, DBG_RIPEXCEPTION);
+ ok(rec->NumberParameters == 2, "ExceptionParameters is %d instead of
2\n", rec->NumberParameters);
+ ok(rec->ExceptionInformation[0] == 0x11223344, "ExceptionInformation[0] =
%08x instead of %08x\n",
+ (NTSTATUS)rec->ExceptionInformation[0], 0x11223344);
+ ok(rec->ExceptionInformation[1] == 0x55667788, "ExceptionInformation[1] =
%08x instead of %08x\n",
+ (NTSTATUS)rec->ExceptionInformation[1], 0x55667788);
+
+ ripevent_exceptions++;
+ return (rec->ExceptionCode == DBG_RIPEXCEPTION) ? EXCEPTION_CONTINUE_EXECUTION :
EXCEPTION_CONTINUE_SEARCH;
+}
+
+static void test_ripevent(DWORD numexc)
+{
+ EXCEPTION_RECORD record;
+ PVOID vectored_handler;
+
+ if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler ||
!pRtlRaiseException)
+ {
+ skip("RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler or
RtlRaiseException not found\n");
+ return;
+ }
+
+ vectored_handler = pRtlAddVectoredExceptionHandler(TRUE,
&ripevent_vectored_handler);
+ ok(vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n");
+
+ record.ExceptionCode = DBG_RIPEXCEPTION;
+ record.ExceptionFlags = 0;
+ record.ExceptionRecord = NULL;
+ record.ExceptionAddress = NULL;
+ record.NumberParameters = 2;
+ record.ExceptionInformation[0] = 0x11223344;
+ record.ExceptionInformation[1] = 0x55667788;
+
+ ripevent_exceptions = 0;
+ pRtlRaiseException(&record);
+ ok(ripevent_exceptions == numexc, "RtlRaiseException generated %d exceptions,
expected %d\n",
+ ripevent_exceptions, numexc);
+
+ pRtlRemoveVectoredExceptionHandler(vectored_handler);
+}
+
START_TEST(exception)
{
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
@@ -1586,6 +1802,7 @@
pNtGetContextThread = (void *)GetProcAddress( hntdll, "NtGetContextThread"
);
pNtSetContextThread = (void *)GetProcAddress( hntdll, "NtSetContextThread"
);
pNtReadVirtualMemory = (void *)GetProcAddress( hntdll,
"NtReadVirtualMemory" );
+ pRtlUnwind = (void *)GetProcAddress( hntdll, "RtlUnwind" );
pRtlRaiseException = (void *)GetProcAddress( hntdll, "RtlRaiseException"
);
pNtTerminateProcess = (void *)GetProcAddress( hntdll, "NtTerminateProcess"
);
pRtlAddVectoredExceptionHandler = (void *)GetProcAddress( hntdll,
@@ -1640,6 +1857,14 @@
run_rtlraiseexception_test(0x12345);
run_rtlraiseexception_test(EXCEPTION_BREAKPOINT);
run_rtlraiseexception_test(EXCEPTION_INVALID_HANDLE);
+ test_stage = 3;
+ test_outputdebugstring(0, FALSE);
+ test_stage = 4;
+ test_outputdebugstring(2, TRUE); /* is this a Windows bug? */
+ test_stage = 5;
+ test_ripevent(0);
+ test_stage = 6;
+ test_ripevent(1);
}
else
skip( "RtlRaiseException not found\n" );
@@ -1648,13 +1873,16 @@
return;
}
- test_prot_fault();
+ test_unwind();
test_exceptions();
test_rtlraiseexception();
+ test_outputdebugstring(1, FALSE);
+ test_ripevent(1);
test_debugger();
test_simd_exceptions();
test_fpu_exceptions();
test_dpe_exceptions();
+ test_prot_fault();
#elif defined(__x86_64__)
pRtlAddFunctionTable = (void *)GetProcAddress( hntdll,
@@ -1666,6 +1894,8 @@
pRtlLookupFunctionEntry = (void *)GetProcAddress( hntdll,
"RtlLookupFunctionEntry" );
+ test_outputdebugstring(1, FALSE);
+ test_ripevent(1);
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] Sat Sep 20 20:08:51 2014
@@ -267,6 +267,7 @@
FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL,
0);
ok(status == STATUS_OBJECT_NAME_INVALID,
"open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
+ pRtlFreeUnicodeString(&nameW);
pRtlDosPathNameToNtPathName_U(pipeInvalidNameW, &nameW, NULL, NULL);
attr.ObjectName = &nameW;
@@ -281,6 +282,7 @@
FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT, NULL,
0);
ok(status == STATUS_OBJECT_NAME_INVALID,
"open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status);
+ pRtlFreeUnicodeString(&nameW);
}
static void open_file_test(void)
@@ -1966,6 +1968,7 @@
}
}
+ pRtlFreeUnicodeString( &nameW );
SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
DeleteFileW( path );
}
Modified: trunk/rostests/winetests/ntdll/pipe.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ntdll/pipe.c?re…
==============================================================================
--- trunk/rostests/winetests/ntdll/pipe.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/ntdll/pipe.c [iso-8859-1] Sat Sep 20 20:08:51 2014
@@ -34,6 +34,11 @@
#ifndef __WINE_WINTERNL_H
typedef struct {
+ ULONG ReadMode;
+ ULONG CompletionMode;
+} FILE_PIPE_INFORMATION;
+
+typedef struct {
ULONG NamedPipeType;
ULONG NamedPipeConfiguration;
ULONG MaximumInstances;
@@ -68,6 +73,7 @@
ULONG inbound_quota, ULONG outbound_quota,
PLARGE_INTEGER timeout);
static NTSTATUS (WINAPI *pNtQueryInformationFile) (IN HANDLE FileHandle, OUT
PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN
FILE_INFORMATION_CLASS FileInformationClass);
+static NTSTATUS (WINAPI *pNtSetInformationFile) (HANDLE handle, PIO_STATUS_BLOCK io,
PVOID ptr, ULONG len, FILE_INFORMATION_CLASS class);
static NTSTATUS (WINAPI *pNtCancelIoFile) (HANDLE hFile, PIO_STATUS_BLOCK io_status);
static void (WINAPI *pRtlInitUnicodeString) (PUNICODE_STRING target, PCWSTR source);
@@ -87,6 +93,7 @@
loadfunc(NtFsControlFile)
loadfunc(NtCreateNamedPipeFile)
loadfunc(NtQueryInformationFile)
+ loadfunc(NtSetInformationFile)
loadfunc(NtCancelIoFile)
loadfunc(RtlInitUnicodeString)
@@ -479,6 +486,190 @@
CloseHandle(hPipe);
}
+static void _check_pipe_handle_state(int line, HANDLE handle, ULONG read, ULONG
completion)
+{
+ IO_STATUS_BLOCK iosb;
+ FILE_PIPE_INFORMATION fpi;
+ NTSTATUS res;
+ if (handle != INVALID_HANDLE_VALUE)
+ {
+ memset(&fpi, 0x55, sizeof(fpi));
+ res = pNtQueryInformationFile(handle, &iosb, &fpi, sizeof(fpi),
(FILE_INFORMATION_CLASS)23);
+ ok_(__FILE__, line)(!res, "NtQueryInformationFile returned %x\n",
res);
+ ok_(__FILE__, line)(fpi.ReadMode == read, "Unexpected ReadMode, expected %x,
got %x\n",
+ read, fpi.ReadMode);
+ ok_(__FILE__, line)(fpi.CompletionMode == completion, "Unexpected
CompletionMode, expected %x, got %x\n",
+ completion, fpi.CompletionMode);
+ }
+}
+#define check_pipe_handle_state(handle, r, c) _check_pipe_handle_state(__LINE__, handle,
r, c)
+
+static void test_filepipeinfo(void)
+{
+ IO_STATUS_BLOCK iosb;
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING name;
+ LARGE_INTEGER timeout;
+ HANDLE hServer, hClient;
+ FILE_PIPE_INFORMATION fpi;
+ NTSTATUS res;
+
+ pRtlInitUnicodeString(&name, testpipe_nt);
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = &name;
+ attr.Attributes = 0x40; /* case insensitive */
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+
+ timeout.QuadPart = -100000000000ll;
+
+ /* test with INVALID_HANDLE_VALUE */
+ res = pNtQueryInformationFile(INVALID_HANDLE_VALUE, &iosb, &fpi, sizeof(fpi),
(FILE_INFORMATION_CLASS)23);
+ ok(res == STATUS_OBJECT_TYPE_MISMATCH, "NtQueryInformationFile returned
%x\n", res);
+
+ fpi.ReadMode = 0;
+ fpi.CompletionMode = 0;
+ res = pNtSetInformationFile(INVALID_HANDLE_VALUE, &iosb, &fpi, sizeof(fpi),
(FILE_INFORMATION_CLASS)23);
+ ok(res == STATUS_OBJECT_TYPE_MISMATCH, "NtSetInformationFile returned
%x\n", res);
+
+ /* server end with read-only attributes */
+ res = pNtCreateNamedPipeFile(&hServer, FILE_READ_ATTRIBUTES | SYNCHRONIZE,
&attr, &iosb,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, 2 /* FILE_CREATE
*/,
+ 0, 0, 0, 1, 0xFFFFFFFF, 500, 500, &timeout);
+ ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
+
+ check_pipe_handle_state(hServer, 0, 1);
+
+ hClient = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0,
0);
+ ok(hClient != INVALID_HANDLE_VALUE, "can't open pipe, GetLastError:
%x\n", GetLastError());
+
+ check_pipe_handle_state(hServer, 0, 1);
+ check_pipe_handle_state(hClient, 0, 0);
+
+ fpi.ReadMode = 0;
+ fpi.CompletionMode = 0;
+ res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi),
(FILE_INFORMATION_CLASS)23);
+ ok(res == STATUS_ACCESS_DENIED, "NtSetInformationFile returned %x\n",
res);
+
+ check_pipe_handle_state(hServer, 0, 1);
+ check_pipe_handle_state(hClient, 0, 0);
+
+ fpi.ReadMode = 1; /* invalid on a byte stream pipe */
+ fpi.CompletionMode = 1;
+ res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi),
(FILE_INFORMATION_CLASS)23);
+ ok(res == STATUS_ACCESS_DENIED, "NtSetInformationFile returned %x\n",
res);
+
+ check_pipe_handle_state(hServer, 0, 1);
+ check_pipe_handle_state(hClient, 0, 0);
+
+ if (hClient != INVALID_HANDLE_VALUE)
+ {
+ fpi.ReadMode = 1; /* invalid on a byte stream pipe */
+ fpi.CompletionMode = 1;
+ res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi),
(FILE_INFORMATION_CLASS)23);
+ ok(res == STATUS_INVALID_PARAMETER, "NtSetInformationFile returned
%x\n", res);
+ }
+
+ check_pipe_handle_state(hServer, 0, 1);
+ check_pipe_handle_state(hClient, 0, 0);
+
+ if (hClient != INVALID_HANDLE_VALUE)
+ {
+ fpi.ReadMode = 0;
+ fpi.CompletionMode = 1;
+ res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi),
(FILE_INFORMATION_CLASS)23);
+ ok(!res, "NtSetInformationFile returned %x\n", res);
+ }
+
+ check_pipe_handle_state(hServer, 0, 1);
+ check_pipe_handle_state(hClient, 0, 1);
+
+ if (hClient != INVALID_HANDLE_VALUE)
+ {
+ fpi.ReadMode = 0;
+ fpi.CompletionMode = 2; /* not in range 0-1 */
+ res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi),
(FILE_INFORMATION_CLASS)23);
+ ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */,
"NtSetInformationFile returned %x\n", res);
+
+ fpi.ReadMode = 2; /* not in range 0-1 */
+ fpi.CompletionMode = 0;
+ res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi),
(FILE_INFORMATION_CLASS)23);
+ ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */,
"NtSetInformationFile returned %x\n", res);
+ }
+
+ CloseHandle(hClient);
+
+ check_pipe_handle_state(hServer, 0, 1);
+
+ fpi.ReadMode = 0;
+ fpi.CompletionMode = 0;
+ res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi),
(FILE_INFORMATION_CLASS)23);
+ ok(res == STATUS_ACCESS_DENIED, "NtSetInformationFile returned %x\n",
res);
+
+ CloseHandle(hServer);
+
+ /* message mode server with read/write attributes */
+ res = pNtCreateNamedPipeFile(&hServer, FILE_READ_ATTRIBUTES |
FILE_WRITE_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, 2 /* FILE_CREATE
*/,
+ 0, 1, 1, 0, 0xFFFFFFFF, 500, 500, &timeout);
+ ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
+
+ check_pipe_handle_state(hServer, 1, 0);
+
+ hClient = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0,
0);
+ ok(hClient != INVALID_HANDLE_VALUE, "can't open pipe, GetLastError:
%x\n", GetLastError());
+
+ check_pipe_handle_state(hServer, 1, 0);
+ check_pipe_handle_state(hClient, 0, 0);
+
+ if (hClient != INVALID_HANDLE_VALUE)
+ {
+ fpi.ReadMode = 1;
+ fpi.CompletionMode = 1;
+ res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi),
(FILE_INFORMATION_CLASS)23);
+ ok(!res, "NtSetInformationFile returned %x\n", res);
+ }
+
+ check_pipe_handle_state(hServer, 1, 0);
+ check_pipe_handle_state(hClient, 1, 1);
+
+ fpi.ReadMode = 0;
+ fpi.CompletionMode = 1;
+ res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi),
(FILE_INFORMATION_CLASS)23);
+ ok(!res, "NtSetInformationFile returned %x\n", res);
+
+ check_pipe_handle_state(hServer, 0, 1);
+ check_pipe_handle_state(hClient, 1, 1);
+
+ if (hClient != INVALID_HANDLE_VALUE)
+ {
+ fpi.ReadMode = 0;
+ fpi.CompletionMode = 2; /* not in range 0-1 */
+ res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi),
(FILE_INFORMATION_CLASS)23);
+ ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */,
"NtSetInformationFile returned %x\n", res);
+
+ fpi.ReadMode = 2; /* not in range 0-1 */
+ fpi.CompletionMode = 0;
+ res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi),
(FILE_INFORMATION_CLASS)23);
+ ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */,
"NtSetInformationFile returned %x\n", res);
+ }
+
+ CloseHandle(hClient);
+
+ check_pipe_handle_state(hServer, 0, 1);
+
+ fpi.ReadMode = 1;
+ fpi.CompletionMode = 0;
+ res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi),
(FILE_INFORMATION_CLASS)23);
+ ok(!res, "NtSetInformationFile returned %x\n", res);
+
+ check_pipe_handle_state(hServer, 1, 0);
+
+ CloseHandle(hServer);
+}
+
START_TEST(pipe)
{
if (!init_func_ptrs())
@@ -493,6 +684,9 @@
trace("starting overlapped tests\n");
test_overlapped();
+ trace("starting FILE_PIPE_INFORMATION tests\n");
+ test_filepipeinfo();
+
if (!pOpenThread || !pQueueUserAPC)
return;
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] Sat Sep 20 20:08:51 2014
@@ -90,6 +90,8 @@
static NTSTATUS (WINAPI *pRtlIpv4AddressToStringExA)(const IN_ADDR *, USHORT, LPSTR,
PULONG);
static NTSTATUS (WINAPI *pRtlIpv4StringToAddressA)(PCSTR, BOOLEAN, PCSTR *, IN_ADDR *);
static NTSTATUS (WINAPI *pLdrAddRefDll)(ULONG, HMODULE);
+static NTSTATUS (WINAPI *pLdrLockLoaderLock)(ULONG, ULONG*, ULONG_PTR*);
+static NTSTATUS (WINAPI *pLdrUnlockLoaderLock)(ULONG, ULONG_PTR);
static HMODULE hkernel32 = 0;
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
@@ -135,6 +137,8 @@
pRtlIpv4AddressToStringExA = (void *)GetProcAddress(hntdll,
"RtlIpv4AddressToStringExA");
pRtlIpv4StringToAddressA = (void *)GetProcAddress(hntdll,
"RtlIpv4StringToAddressA");
pLdrAddRefDll = (void *)GetProcAddress(hntdll, "LdrAddRefDll");
+ pLdrLockLoaderLock = (void *)GetProcAddress(hntdll,
"LdrLockLoaderLock");
+ pLdrUnlockLoaderLock = (void *)GetProcAddress(hntdll,
"LdrUnlockLoaderLock");
}
hkernel32 = LoadLibraryA("kernel32.dll");
ok(hkernel32 != 0, "LoadLibrary failed\n");
@@ -1551,6 +1555,58 @@
ok(mod2 != NULL, "got %p\n", mod2);
}
+static void test_LdrLockLoaderLock(void)
+{
+ ULONG_PTR magic;
+ ULONG result;
+ NTSTATUS status;
+
+ if (!pLdrLockLoaderLock)
+ {
+ win_skip("LdrLockLoaderLock() is not available\n");
+ return;
+ }
+
+ /* invalid flags */
+ result = 10;
+ magic = 0xdeadbeef;
+ status = pLdrLockLoaderLock(0x10, &result, &magic);
+ ok(status == STATUS_INVALID_PARAMETER_1, "got 0x%08x\n", status);
+ ok(result == 0, "got %d\n", result);
+ ok(magic == 0, "got %lx\n", magic);
+
+ magic = 0xdeadbeef;
+ status = pLdrLockLoaderLock(0x10, NULL, &magic);
+ ok(status == STATUS_INVALID_PARAMETER_1, "got 0x%08x\n", status);
+ ok(magic == 0, "got %lx\n", magic);
+
+ result = 10;
+ status = pLdrLockLoaderLock(0x10, &result, NULL);
+ ok(status == STATUS_INVALID_PARAMETER_1, "got 0x%08x\n", status);
+ ok(result == 0, "got %d\n", result);
+
+ /* non-blocking mode, result is null */
+ magic = 0xdeadbeef;
+ status = pLdrLockLoaderLock(0x2, NULL, &magic);
+ ok(status == STATUS_INVALID_PARAMETER_2, "got 0x%08x\n", status);
+ ok(magic == 0, "got %lx\n", magic);
+
+ /* magic pointer is null */
+ result = 10;
+ status = pLdrLockLoaderLock(0, &result, NULL);
+ ok(status == STATUS_INVALID_PARAMETER_3, "got 0x%08x\n", status);
+ ok(result == 0, "got %d\n", result);
+
+ /* lock in non-blocking mode */
+ result = 0;
+ magic = 0;
+ status = pLdrLockLoaderLock(0x2, &result, &magic);
+ ok(status == STATUS_SUCCESS, "got 0x%08x\n", status);
+ ok(result == 1, "got %d\n", result);
+ ok(magic != 0, "got %lx\n", magic);
+ pLdrUnlockLoaderLock(0, magic);
+}
+
START_TEST(rtl)
{
InitFunctionPtrs();
@@ -1576,4 +1632,5 @@
test_RtlIpv4AddressToStringEx();
test_RtlIpv4StringToAddress();
test_LdrAddRefDll();
-}
+ test_LdrLockLoaderLock();
+}