Index: modules/rostests/apitests/iphlpapi/CMakeLists.txt =================================================================== --- modules/rostests/apitests/iphlpapi/CMakeLists.txt (revision 72518) +++ modules/rostests/apitests/iphlpapi/CMakeLists.txt (working copy) @@ -7,5 +7,5 @@ add_executable(iphlpapi_apitest ${SOURCE}) target_link_libraries(iphlpapi_apitest wine ${PSEH_LIB}) set_module_type(iphlpapi_apitest win32cui) -add_importlibs(iphlpapi_apitest iphlpapi msvcrt kernel32 ntdll) +add_importlibs(iphlpapi_apitest ws2_32 iphlpapi msvcrt kernel32 ntdll) add_cd_file(TARGET iphlpapi_apitest DESTINATION reactos/bin FOR all) Index: modules/rostests/apitests/iphlpapi/icmp.c =================================================================== --- modules/rostests/apitests/iphlpapi/icmp.c (revision 72518) +++ modules/rostests/apitests/iphlpapi/icmp.c (working copy) @@ -10,8 +10,20 @@ #include #include + static void +CALLBACK +ApcRoutine(PVOID Context) +{ + if (Context != NULL) + trace("ApcRoutine called (%s)\n", (PCHAR)Context); + else + trace("ApcRoutine called (NULL)\n"); +} + +static +void test_IcmpCreateFile(void) { HANDLE hIcmp; @@ -60,6 +72,10 @@ bRet = IcmpCloseHandle(hIcmp); ok(bRet, "IcmpCloseHandle failed unexpectedly: %lu\n", GetLastError()); } + else + { + skip("Unable to create ICMP file handle: %lu\n", GetLastError()); + } SetLastError(0xDEADBEEF); hIcmp = Icmp6CreateFile(); @@ -68,6 +84,10 @@ bRet = IcmpCloseHandle(hIcmp); ok(bRet, "IcmpCloseHandle failed unexpectedly: %lu\n", GetLastError()); } + else + { + skip("Unable to create ICMPv6 file handle: %lu\n", GetLastError()); + } hIcmp = INVALID_HANDLE_VALUE; SetLastError(0xDEADBEEF); @@ -82,9 +102,859 @@ ok_err(ERROR_INVALID_HANDLE); } +static +void +test_IcmpSendEcho(void) +{ + HANDLE hIcmp; + IPAddr Address; + DWORD nReplies; + PICMP_ECHO_REPLY pEcho; + IP_OPTION_INFORMATION IpOptions; + UCHAR OptsData; + + char SendData[32]; + char ReplyBuffer[sizeof(ICMP_ECHO_REPLY) + sizeof(SendData)]; + DWORD ReplySize = sizeof(ReplyBuffer); + + ZeroMemory(SendData, sizeof(SendData)); + + Address = htonl(INADDR_LOOPBACK); + + // Test an invalid handle. + hIcmp = INVALID_HANDLE_VALUE; + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho( + hIcmp, Address, + SendData, sizeof(SendData), NULL, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "IcmpSendEcho succeeded unexpectedly\n"); + ok_err(ERROR_INVALID_HANDLE); + + // Test a NULL handle. + hIcmp = NULL; + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho( + hIcmp, Address, + SendData, sizeof(SendData), NULL, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "IcmpSendEcho succeeded unexpectedly\n"); + ok_err(ERROR_INVALID_HANDLE); + + // Test an ICMPv6 handle (if IPv6 is available). + hIcmp = Icmp6CreateFile(); + if (hIcmp != INVALID_HANDLE_VALUE) + { + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho( + hIcmp, Address, + SendData, sizeof(SendData), NULL, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(ERROR_SUCCESS); + + IcmpCloseHandle(hIcmp); + } + else + { + skip("Unable to create ICMPv6 file handle: %lu\n", GetLastError()); + } + + hIcmp = IcmpCreateFile(); + if (hIcmp == INVALID_HANDLE_VALUE) + { + skip("Unable to create ICMP file handle: %lu\n", GetLastError()); + return; + } + + // Test a bad DestinationAddress. + Address = htonl(INADDR_ANY); + ZeroMemory(ReplyBuffer, ReplySize); + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho( + hIcmp, Address, + SendData, sizeof(SendData), NULL, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "IcmpSendEcho succeeded unexpectedly\n"); + ok_err(IP_BAD_DESTINATION); + + pEcho = (PICMP_ECHO_REPLY)ReplyBuffer; + ok(pEcho->Status == IP_BAD_DESTINATION, "Expected IP_BAD_DESTINATION, got %lu\n", pEcho->Status); + + Address = htonl(INADDR_LOOPBACK); + + if (0) + { + // Crashes on Server 2003. + // Test a bad SendData. + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho( + hIcmp, Address, + NULL, sizeof(SendData), NULL, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "IcmpSendEcho succeeded unexpectedly\n"); + } + + // Test a bad SendData with a zero SendSize. + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho( + hIcmp, Address, + NULL, 0, NULL, + ReplyBuffer, ReplySize, 1000); + ok(nReplies, "IcmpSendEcho failed unexpectedly: %lu\n", GetLastError()); + + // Test a zero SendSize. + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho( + hIcmp, Address, + SendData, 0, NULL, + ReplyBuffer, ReplySize, 1000); + ok(nReplies, "IcmpSendEcho failed unexpectedly: %lu\n", GetLastError()); + + // Test a bad ReplyBuffer; + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho( + hIcmp, Address, + SendData, sizeof(SendData), NULL, + NULL, ReplySize, 1000); + ok(!nReplies, "IcmpSendEcho succeeded unexpectedly\n"); + ok_err(ERROR_INVALID_PARAMETER); + + // Test a bad ReplyBuffer with a zero ReplySize. + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho( + hIcmp, Address, + SendData, sizeof(SendData), NULL, + NULL, 0, 1000); + ok(!nReplies, "IcmpSendEcho succeeded unexpectedly\n"); + ok_err(ERROR_INSUFFICIENT_BUFFER); + + // Test a zero ReplySize. + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho( + hIcmp, Address, + SendData, sizeof(SendData), NULL, + ReplyBuffer, 0, 1000); + ok(!nReplies, "IcmpSendEcho succeeded unexpectedly\n"); + ok_err(ERROR_INSUFFICIENT_BUFFER); + + // Test a small ReplySize. + ZeroMemory(ReplyBuffer, ReplySize); + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho( + hIcmp, Address, + SendData, sizeof(SendData), NULL, + ReplyBuffer, ReplySize - 1, 1000); + ok(!nReplies, "IcmpSendEcho succeeded unexpectedly\n"); + ok_err(IP_BUF_TOO_SMALL); + + pEcho = (PICMP_ECHO_REPLY)ReplyBuffer; + ok(pEcho->Status == IP_BUF_TOO_SMALL, "Expected IP_BUF_TOO_SMALL, got %lu\n", pEcho->Status); + + // Test minimum ReplySize with a zero RequestSize. + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho( + hIcmp, Address, + SendData, 0, NULL, + ReplyBuffer, sizeof(ICMP_ECHO_REPLY), 1000); + ok(nReplies, "IcmpSendEcho failed unexpectedly: %lu\n", GetLastError()); + + // Test a zero Timeoout. + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho( + hIcmp, Address, + SendData, sizeof(SendData), NULL, + ReplyBuffer, ReplySize, 0); + ok(nReplies, "IcmpSendEcho failed unexpectedly: %lu\n", GetLastError()); + + // Test a proper call. + ZeroMemory(ReplyBuffer, ReplySize); + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho( + hIcmp, Address, + SendData, sizeof(SendData), NULL, + ReplyBuffer, ReplySize, 1000); + ok(nReplies, "IcmpSendEcho failed unexpectedly: %lu\n", GetLastError()); + + if (nReplies) + { + pEcho = (PICMP_ECHO_REPLY)ReplyBuffer; + ok(pEcho->Status == IP_SUCCESS, "Expected 0, got %lu\n", pEcho->Status); + ok(pEcho->Reserved == 0, "Expected 0, got %d\n", pEcho->Reserved); + } + + /* + * Tests using RequestOptions. + */ + ZeroMemory(&IpOptions, sizeof(IpOptions)); + + // Test a bad Flags. + IpOptions.Flags = 0x22; + ZeroMemory(ReplyBuffer, ReplySize); + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho( + hIcmp, Address, + SendData, sizeof(SendData), &IpOptions, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "IcmpSendEcho succeeded unexpectedly\n"); + ok_err(IP_BAD_OPTION); + + pEcho = (PICMP_ECHO_REPLY)ReplyBuffer; + ok(pEcho->Status == IP_BAD_OPTION, "Expected IP_BAD_OPTION, got %lu\n", pEcho->Status); + + IpOptions.Flags = 0; + + // Test a bad OptionsData. + OptsData = 0xFF; + IpOptions.OptionsSize = 1; + IpOptions.OptionsData = &OptsData; + + ZeroMemory(ReplyBuffer, ReplySize); + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho( + hIcmp, Address, + SendData, sizeof(SendData), &IpOptions, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "IcmpSendEcho succeeded unexpectedly\n"); + ok_err(IP_BAD_OPTION); + + pEcho = (PICMP_ECHO_REPLY)ReplyBuffer; + ok(pEcho->Status == IP_BAD_OPTION, "Expected IP_BAD_OPTION, got %lu\n", pEcho->Status); + + IcmpCloseHandle(hIcmp); +} + +static +void +test_IcmpSendEcho2(void) +{ + HANDLE hIcmp, hEvent; + IPAddr Address; + DWORD nReplies; + PICMP_ECHO_REPLY pEcho; + + char SendData[32]; + char ReplyBuffer[sizeof(ICMP_ECHO_REPLY) + sizeof(SendData) + 8]; + DWORD ReplySize = sizeof(ReplyBuffer); + + char ApcContext[] = "ApcContext"; + + ZeroMemory(SendData, sizeof(SendData)); + ZeroMemory(ReplyBuffer, ReplySize); + + Address = htonl(INADDR_ANY); + + // Test an invalid handle. + hIcmp = INVALID_HANDLE_VALUE; + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho2( + hIcmp, NULL, + NULL, NULL, + Address, + SendData, sizeof(SendData), NULL, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "IcmpSendEcho2 succeeded unexpectedly\n"); + ok_err(ERROR_INVALID_HANDLE); + + hIcmp = IcmpCreateFile(); + if (hIcmp == INVALID_HANDLE_VALUE) + { + skip("Unable to create ICMP file handle: %lu\n", GetLastError()); + return; + } + + // Test a bad DestinationAddress. + Address = htonl(INADDR_ANY); + ZeroMemory(ReplyBuffer, ReplySize); + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho2( + hIcmp, NULL, + NULL, NULL, + Address, + SendData, sizeof(SendData), NULL, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "IcmpSendEcho succeeded unexpectedly\n"); + ok_err(IP_BAD_DESTINATION); + + pEcho = (PICMP_ECHO_REPLY)ReplyBuffer; + ok(pEcho->Status == IP_BAD_DESTINATION, "Expected IP_BAD_DESTINATION, got %lu\n", pEcho->Status); + + Address = htonl(INADDR_LOOPBACK); + + // Test minimum size for IcmpSendEcho. + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho2( + hIcmp, NULL, + NULL, NULL, + Address, + SendData, 0, NULL, + ReplyBuffer, sizeof(ICMP_ECHO_REPLY), 1000); + ok(!nReplies, "IcmpSendEcho2 succeeded unexpectedly\n"); + ok_err(ERROR_INSUFFICIENT_BUFFER); + + // Test minimum ReplySize with a zero RequestSize. + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho2( + hIcmp, NULL, + NULL, NULL, + Address, + NULL, 0, NULL, + ReplyBuffer, sizeof(ICMP_ECHO_REPLY) + 8, 1000); + ok(nReplies, "IcmpSendEcho2 failed unexpectedly: %lu\n", GetLastError()); + + // Test an invalid Event. + hEvent = INVALID_HANDLE_VALUE; + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho2( + hIcmp, hEvent, + NULL, NULL, + Address, + SendData, sizeof(SendData), NULL, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "IcmpSendEcho2 succeeded unexpectedly\n"); + ok_err(ERROR_INVALID_HANDLE); + + // Test an Event. + hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho2( + hIcmp, hEvent, + NULL, NULL, + Address, + SendData, sizeof(SendData), NULL, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(ERROR_IO_PENDING); + + if(GetLastError() == ERROR_IO_PENDING) + { + ULONG Status; + + Status = WaitForSingleObject(hEvent, 1000); + ok(Status == WAIT_OBJECT_0, "Expected WAIT_OBJECT_0, got %lu\n", Status); + + if (Status == WAIT_OBJECT_0) + { + nReplies = IcmpParseReplies(ReplyBuffer, ReplySize); + ok(nReplies, "Failed to parse echo replies: %lu\n", GetLastError()); + } + } + + CloseHandle(hEvent); + + // Test an Event with an ApcContext. + hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho2( + hIcmp, hEvent, + NULL, ApcContext, + Address, + SendData, sizeof(SendData), NULL, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(ERROR_IO_PENDING); + + if(GetLastError() == ERROR_IO_PENDING) + { + ULONG Status; + + Status = WaitForSingleObject(hEvent, 1000); + ok(Status == WAIT_OBJECT_0, "Expected WAIT_OBJECT_0, got %lu\n", Status); + + if (Status == WAIT_OBJECT_0) + { + nReplies = IcmpParseReplies(ReplyBuffer, ReplySize); + ok(nReplies, "Failed to parse echo replies: %lu\n", GetLastError()); + } + } + + CloseHandle(hEvent); + + // Test an ApcRoutine. + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho2( + hIcmp, NULL, + (FARPROC)ApcRoutine, ApcContext, + Address, + SendData, sizeof(SendData), NULL, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(ERROR_IO_PENDING); + + if(GetLastError() == ERROR_IO_PENDING) + { + // Wait for the callback. + SleepEx(1000, TRUE); + } + + // Test an ApcRoutine without an ApcContext. + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho2( + hIcmp, NULL, + (FARPROC)ApcRoutine, NULL, + Address, + SendData, sizeof(SendData), NULL, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(ERROR_IO_PENDING); + + if(GetLastError() == ERROR_IO_PENDING) + { + // Wait for the callback. + SleepEx(1000, TRUE); + } + + // Test an Event with an ApcRoutine. + hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + SetLastError(0xDEADBEEF); + nReplies = IcmpSendEcho2( + hIcmp, hEvent, + (FARPROC)ApcRoutine, ApcContext, + Address, + SendData, sizeof(SendData), NULL, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(ERROR_IO_PENDING); + + if(GetLastError() == ERROR_IO_PENDING) + { + ULONG Status; + + Status = WaitForSingleObject(hEvent, 1000); + ok(Status == WAIT_OBJECT_0, "Expected WAIT_OBJECT_0, got %lu\n", Status); + + if (Status == WAIT_OBJECT_0) + { + nReplies = IcmpParseReplies(ReplyBuffer, ReplySize); + ok(nReplies, "Failed to parse echo replies: %lu\n", GetLastError()); + } + + // Wait for the callback. + SleepEx(1000, TRUE); + } + + CloseHandle(hEvent); + + IcmpCloseHandle(hIcmp); +} + +static +void +test_IcmpParseReplies(void) +{ + HANDLE hIcmp, hEvent; + IPAddr Address; + DWORD nReplies; + PICMP_ECHO_REPLY pEcho; + ULONG Status; + + char SendData[32]; + char ReplyBuffer[sizeof(ICMP_ECHO_REPLY) + sizeof(SendData) + 8]; + DWORD ReplySize = sizeof(ReplyBuffer); + + ZeroMemory(SendData, sizeof(SendData)); + ZeroMemory(ReplyBuffer, ReplySize); + + Address = htonl(INADDR_LOOPBACK); + + hIcmp = IcmpCreateFile(); + if (hIcmp == INVALID_HANDLE_VALUE) + { + skip("Unable to create ICMP file handle: %lu\n", GetLastError()); + return; + } + + hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + + IcmpSendEcho2( + hIcmp, hEvent, + NULL, NULL, + Address, + SendData, sizeof(SendData), NULL, + ReplyBuffer, ReplySize, 1000); + + if (GetLastError() != ERROR_IO_PENDING) + { + skip("Asynchronous call to IcmpSendEcho2 failed\n"); + goto cleanup; + } + + Status = WaitForSingleObject(hEvent, 1000); + if (Status != WAIT_OBJECT_0) + { + skip("Failed waiting for event\n"); + goto cleanup; + } + + pEcho = (PICMP_ECHO_REPLY)ReplyBuffer; + ok(pEcho->Reserved != 0, "No replies in buffer\n"); + + // Test a bad ReplyBuffer with a zero ReplySize. + SetLastError(0xDEADBEEF); + nReplies = IcmpParseReplies(NULL, 0); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(0xDEADBEEF); + + // Test a bad ReplyBuffer. + SetLastError(0xDEADBEEF); + nReplies = IcmpParseReplies(NULL, ReplySize); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(0xDEADBEEF); + + // Test a zero ReplySize. + SetLastError(0xDEADBEEF); + nReplies = IcmpParseReplies(ReplyBuffer, 0); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(0xDEADBEEF); + + // Test a proper call. + SetLastError(0xDEADBEEF); + nReplies = IcmpParseReplies(ReplyBuffer, ReplySize); + ok(nReplies, "Failed to parse echo replies: %lu\n", GetLastError()); + ok_err(0xDEADBEEF); + ok(pEcho->Reserved == 0, "Echo reply not parsed\n"); + + // Test an already parsed ReplyBuffer. + SetLastError(0xDEADBEEF); + nReplies = IcmpParseReplies(ReplyBuffer, ReplySize); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(ERROR_SUCCESS); + + CloseHandle(hEvent); + hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + + ZeroMemory(ReplyBuffer, ReplySize); + + // Test a bad destination. + IcmpSendEcho2( + hIcmp, hEvent, + NULL, NULL, + 0, + SendData, sizeof(SendData), NULL, + ReplyBuffer, ReplySize, 1000); + + if (GetLastError() != ERROR_IO_PENDING) + { + skip("Asynchronous call to IcmpSendEcho2 failed\n"); + goto cleanup; + } + + Status = WaitForSingleObject(hEvent, 1000); + if (Status != WAIT_OBJECT_0) + { + skip("Failed waiting for event\n"); + goto cleanup; + } + + SetLastError(0xDEADBEEF); + nReplies = IcmpParseReplies(ReplyBuffer, ReplySize); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(IP_BAD_DESTINATION); + +cleanup: + CloseHandle(hEvent); + IcmpCloseHandle(hIcmp); +} + +static +void +test_Icmp6SendEcho2(void) +{ + HANDLE hIcmp, hEvent; + struct sockaddr_in6 Source; + struct sockaddr_in6 Destination; + IP_OPTION_INFORMATION IpOptions; + const IN6_ADDR Loopback = {{ IN6ADDR_LOOPBACK_INIT }}; + DWORD nReplies; + + char SendData[64]; + char ReplyBuffer[sizeof(ICMPV6_ECHO_REPLY) + sizeof(SendData) + 8]; + DWORD ReplySize = sizeof(ReplyBuffer); + + char ApcContext[] = "ApcContext"; + + ZeroMemory(&Source, sizeof(Source)); + ZeroMemory(&Destination, sizeof(Destination)); + ZeroMemory(&IpOptions, sizeof(IpOptions)); + ZeroMemory(&SendData, sizeof(SendData)); + ZeroMemory(ReplyBuffer, ReplySize); + + hIcmp = Icmp6CreateFile(); + if (hIcmp == INVALID_HANDLE_VALUE) + { + skip("Unable to create ICMPv6 file handle: %lu\n", GetLastError()); + return; + } + + // Test a bad destination address. + SetLastError(0xDEADBEEF); + nReplies = Icmp6SendEcho2( + hIcmp, NULL, + NULL, NULL, + &Source, &Destination, + SendData, sizeof(SendData), &IpOptions, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "Icmp6SendEcho2 succeeded unexpectedly\n"); + ok_err(IP_PARAM_PROBLEM); + + Destination.sin6_addr = Loopback; + + // Test a bad source address. + memset(&Source.sin6_addr, '1', sizeof(Source.sin6_addr)); + SetLastError(0xDEADBEEF); + nReplies = Icmp6SendEcho2( + hIcmp, NULL, + NULL, NULL, + &Source, &Destination, + SendData, sizeof(SendData), &IpOptions, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "Icmp6SendEcho2 succeeded unexpectedly\n"); + ok_err(IP_BAD_ROUTE); + + ZeroMemory(&Source.sin6_addr, sizeof(Source.sin6_addr)); + + // Test a proper call. + SetLastError(0xDEADBEEF); + nReplies = Icmp6SendEcho2( + hIcmp, NULL, + NULL, NULL, + &Source, &Destination, + NULL, 0, &IpOptions, + ReplyBuffer, ReplySize, 1000); + ok(nReplies, "Icmp6SendEcho2 failed unexpectedly: %lu\n", GetLastError()); + + // Test a bad Flags. + IpOptions.Flags = 0xF0; + SetLastError(0xDEADBEEF); + nReplies = Icmp6SendEcho2( + hIcmp, NULL, + NULL, NULL, + &Source, &Destination, + SendData, 32, &IpOptions, + ReplyBuffer, ReplySize, 1000); + ok(nReplies, "Icmp6SendEcho2 failed unexpectedly: %lu\n", GetLastError()); + + IpOptions.Flags = 0; + + // Test an invalid Event. + hEvent = INVALID_HANDLE_VALUE; + SetLastError(0xDEADBEEF); + nReplies = Icmp6SendEcho2( + hIcmp, hEvent, + NULL, NULL, + &Source, &Destination, + SendData, sizeof(SendData), &IpOptions, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "IcmpSendEcho2 succeeded unexpectedly\n"); + ok_err(ERROR_INVALID_HANDLE); + + // Test an Event. + hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + SetLastError(0xDEADBEEF); + nReplies = Icmp6SendEcho2( + hIcmp, hEvent, + NULL, NULL, + &Source, &Destination, + SendData, sizeof(SendData), &IpOptions, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(ERROR_IO_PENDING); + + if(GetLastError() == ERROR_IO_PENDING) + { + ULONG Status; + + Status = WaitForSingleObject(hEvent, 1000); + ok(Status == WAIT_OBJECT_0, "Expected WAIT_OBJECT_0, got %lu\n", Status); + + if (Status == WAIT_OBJECT_0) + { + nReplies = Icmp6ParseReplies(ReplyBuffer, ReplySize); + ok(nReplies, "Failed to parse echo replies: %lu\n", GetLastError()); + } + } + + CloseHandle(hEvent); + + // Test an ApcRoutine. + SetLastError(0xDEADBEEF); + nReplies = Icmp6SendEcho2( + hIcmp, NULL, + (FARPROC)ApcRoutine, ApcContext, + &Source, &Destination, + SendData, sizeof(SendData), &IpOptions, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(ERROR_IO_PENDING); + + if(GetLastError() == ERROR_IO_PENDING) + { + // Wait for the callback. + SleepEx(1000, TRUE); + } + + // Test an Event with an ApcRoutine. + hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + SetLastError(0xDEADBEEF); + nReplies = Icmp6SendEcho2( + hIcmp, hEvent, + (FARPROC)ApcRoutine, ApcContext, + &Source, &Destination, + SendData, sizeof(SendData), &IpOptions, + ReplyBuffer, ReplySize, 1000); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(ERROR_IO_PENDING); + + if(GetLastError() == ERROR_IO_PENDING) + { + ULONG Status; + + Status = WaitForSingleObject(hEvent, 1000); + ok(Status == WAIT_OBJECT_0, "Expected WAIT_OBJECT_0, got %lu\n", Status); + + if (Status == WAIT_OBJECT_0) + { + nReplies = Icmp6ParseReplies(ReplyBuffer, ReplySize); + ok(nReplies, "Failed to parse echo replies: %lu\n", GetLastError()); + } + + // Wait for the callback. + SleepEx(1000, TRUE); + } + + CloseHandle(hEvent); + IcmpCloseHandle(hIcmp); +} + +static +void +test_Icmp6ParseReplies(void) +{ + HANDLE hIcmp, hEvent; + struct sockaddr_in6 Source; + struct sockaddr_in6 Destination; + IP_OPTION_INFORMATION IpOptions; + DWORD nReplies; + ULONG Status; + const IN6_ADDR Loopback = {{ IN6ADDR_LOOPBACK_INIT }}; + + char SendData[32]; + char ReplyBuffer[sizeof(ICMPV6_ECHO_REPLY) + sizeof(SendData) + 8]; + DWORD ReplySize = sizeof(ReplyBuffer); + + ZeroMemory(&Source, sizeof(Source)); + ZeroMemory(&Destination, sizeof(Destination)); + ZeroMemory(&IpOptions, sizeof(IpOptions)); + ZeroMemory(SendData, sizeof(SendData)); + ZeroMemory(ReplyBuffer, ReplySize); + + Destination.sin6_addr = Loopback; + + hIcmp = Icmp6CreateFile(); + if (hIcmp == INVALID_HANDLE_VALUE) + { + skip("Unable to create ICMPv6 file handle: %lu\n", GetLastError()); + return; + } + + hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + + Icmp6SendEcho2( + hIcmp, hEvent, + NULL, NULL, + &Source, &Destination, + SendData, sizeof(SendData), &IpOptions, + ReplyBuffer, ReplySize, 1000); + + if (GetLastError() != ERROR_IO_PENDING) + { + skip("Asynchronous call to IcmpSendEcho2 failed\n"); + goto cleanup; + } + + Status = WaitForSingleObject(hEvent, 1000); + if (Status != WAIT_OBJECT_0) + { + skip("Failed waiting for event\n"); + goto cleanup; + } + + // Test a bad ReplyBuffer with a zero ReplySize. + SetLastError(0xDEADBEEF); + nReplies = Icmp6ParseReplies(NULL, 0); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(0xDEADBEEF); + + // Test a bad ReplyBuffer. + SetLastError(0xDEADBEEF); + nReplies = Icmp6ParseReplies(NULL, ReplySize); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(0xDEADBEEF); + + // Test a zero ReplySize. + SetLastError(0xDEADBEEF); + nReplies = Icmp6ParseReplies(ReplyBuffer, 0); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(0xDEADBEEF); + + // Test a proper call. + SetLastError(0xDEADBEEF); + nReplies = Icmp6ParseReplies(ReplyBuffer, ReplySize); + ok(nReplies, "Failed to parse echo replies: %lu\n", GetLastError()); + ok_err(0xDEADBEEF); + + // Test an already parsed ReplyBuffer. + SetLastError(0xDEADBEEF); + nReplies = Icmp6ParseReplies(ReplyBuffer, ReplySize); + ok(nReplies, "Failed to parse echo replies: %lu\n", GetLastError()); + ok_err(0xDEADBEEF); + + CloseHandle(hEvent); + hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + + ZeroMemory(ReplyBuffer, ReplySize); + + // Test a bad destination. + ZeroMemory(&Destination, sizeof(Destination)); + Icmp6SendEcho2( + hIcmp, hEvent, + NULL, NULL, + &Source, &Destination, + SendData, sizeof(SendData), &IpOptions, + ReplyBuffer, ReplySize, 1000); + + if (GetLastError() != ERROR_IO_PENDING) + { + skip("Asynchronous call to IcmpSendEcho2 failed\n"); + goto cleanup; + } + + Status = WaitForSingleObject(hEvent, 1000); + if (Status != WAIT_OBJECT_0) + { + skip("Failed waiting for event\n"); + goto cleanup; + } + + SetLastError(0xDEADBEEF); + nReplies = Icmp6ParseReplies(ReplyBuffer, ReplySize); + ok(!nReplies, "Expected 0 replies, got %lu\n", nReplies); + ok_err(IP_PARAM_PROBLEM); + +cleanup: + CloseHandle(hEvent); + IcmpCloseHandle(hIcmp); +} + + START_TEST(icmp) { test_IcmpCreateFile(); test_Icmp6CreateFile(); test_IcmpCloseHandle(); + test_IcmpSendEcho(); + test_IcmpSendEcho2(); + test_IcmpParseReplies(); + test_Icmp6SendEcho2(); + test_Icmp6ParseReplies(); } Index: modules/rostests/winetests/iphlpapi/iphlpapi.c =================================================================== --- modules/rostests/winetests/iphlpapi/iphlpapi.c (revision 72518) +++ modules/rostests/winetests/iphlpapi/iphlpapi.c (working copy) @@ -917,6 +917,7 @@ "got %u, expected %u\n", ret, ERROR_MR_MID_NOT_FOUND); } +#ifndef __REACTOS__ static void testIcmpSendEcho(void) { HANDLE icmp; @@ -1084,6 +1085,7 @@ skip ("Failed to ping with error %d, is lo interface down?.\n", error); } } +#endif /* still-to-be-tested NT4-onward functions: @@ -1117,7 +1119,9 @@ testGetTcpTable(); testGetUdpTable(); testSetTcpEntry(); +#ifndef __REACTOS__ testIcmpSendEcho(); +#endif } static void testGetInterfaceInfo(void)