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?rev... ============================================================================== --- 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?rev... ============================================================================== --- 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(); +}