Index: modules/rostests/apitests/ws2_32/recv.c =================================================================== --- modules/rostests/apitests/ws2_32/recv.c (revision 72927) +++ modules/rostests/apitests/ws2_32/recv.c (working copy) @@ -119,8 +119,184 @@ return 1; } +static int count = 0; +void +CALLBACK completion( + DWORD dwError, + DWORD cbTransferred, + LPWSAOVERLAPPED lpOverlapped, + DWORD dwFlags) +{ + //trace("completion called dwFlags %ld cbTransferred %ld lpOverlapped %p dwFlags %ld\n", dwError, cbTransferred, lpOverlapped, dwFlags); + count++; + ok(count == 1, "completion sould be called only once count = %ld\n", count); + ok(dwError == 0, "dwError = %ld\n", dwError); + ok(cbTransferred == RECV_BUF, "cbTransferred %ld != %d\n", cbTransferred, RECV_BUF); + ok(lpOverlapped != NULL, "lpOverlapped %p\n", lpOverlapped); + if (lpOverlapped) + { + ok(lpOverlapped->hEvent != INVALID_HANDLE_VALUE, "lpOverlapped->hEvent %d\n", (int)lpOverlapped->hEvent); + if (lpOverlapped->hEvent != INVALID_HANDLE_VALUE) + WSASetEvent(lpOverlapped->hEvent); + } +} + +#define WSARecv_TIMEOUT 2000 + +void Test_WSARecv() +{ + const char szDummyBytes[RECV_BUF] = { 0xFF, 0x00, 0xFF, 0x00 }; + + char szBuf[RECV_BUF]; + int iResult, err; + SOCKET sck; + WSADATA wdata; + WSABUF buffers; + DWORD dwRecv, dwSent, dwFlags; + WSAOVERLAPPED overlapped; + char szGetRequest[] = "GET / HTTP/1.0\r\n\r\n"; + struct fd_set readable; + + /* Start up Winsock */ + iResult = WSAStartup(MAKEWORD(2, 2), &wdata); + ok(iResult == 0, "WSAStartup failed, iResult == %d\n", iResult); + + /* If we call recv without a socket, it should return with an error and do nothing. */ + memcpy(szBuf, szDummyBytes, RECV_BUF); + buffers.buf = szBuf; + buffers.len = sizeof(szBuf); + dwFlags = 0; + dwRecv = 0; + iResult = WSARecv(0, &buffers, 1, &dwRecv, &dwFlags, NULL, NULL); + ok(iResult == SOCKET_ERROR, "iRseult = %d\n", iResult); + ok(!memcmp(szBuf, szDummyBytes, RECV_BUF), "not equal\n"); + + /* Create the socket */ + sck = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); + if(sck == INVALID_SOCKET) + { + WSACleanup(); + skip("CreateSocket failed. Aborting test.\n"); + return; + } + + /* Now we can pass at least a socket, but we have no connection yet. Should return with an error and do nothing. */ + memcpy(szBuf, szDummyBytes, RECV_BUF); + buffers.buf = szBuf; + buffers.len = sizeof(szBuf); + dwFlags = 0; + dwRecv = 0; + iResult = WSARecv(sck, &buffers, 1, &dwRecv, &dwFlags, NULL, NULL); + ok(iResult == SOCKET_ERROR, "iResult = %d\n", iResult); + ok(!memcmp(szBuf, szDummyBytes, RECV_BUF), "not equal\n"); + + /* Connect to "www.reactos.org" */ + if (!ConnectToReactOSWebsite(sck)) + { + WSACleanup(); + skip("ConnectToReactOSWebsite failed. Aborting test.\n"); + return; + } + + /* prepare overlapped */ + memset(&overlapped, 0, sizeof(overlapped)); + overlapped.hEvent = WSACreateEvent(); + + /* Send the GET request */ + buffers.buf = szGetRequest; + buffers.len = strlen(szGetRequest); + dwSent = 0; + iResult = WSASend(sck, &buffers, 1, &dwSent, 0, &overlapped, NULL); + ok(iResult != SOCKET_ERROR && (WSA_IO_PENDING != (err = WSAGetLastError())), "iResult = %d, %d\n", iResult, err); + ok(WSAGetLastError() == 0, "WSAGetLastError failed %d\n", WSAGetLastError()); + iResult = WSAWaitForMultipleEvents(1, &overlapped.hEvent, TRUE, WSARecv_TIMEOUT, TRUE); + ok(iResult != WSA_WAIT_FAILED, "WSAWaitForMultipleEvents failed %d\n", iResult); + ok(WSAGetOverlappedResult(sck, &overlapped, &dwSent, TRUE, &dwFlags), "WSAGetOverlappedResult failed %d\n", WSAGetLastError()); + ok(dwSent == strlen(szGetRequest), "dwSent %ld != 0\n", dwSent); +#if 0 + /* Shutdown the SEND connection */ + iResult = shutdown(sck, SD_SEND); + ok(iResult != SOCKET_ERROR, "iResult = %d\n", iResult); +#endif + /* Wait until we're ready to read */ + FD_ZERO(&readable); + FD_SET(sck, &readable); + + iResult = select(0, &readable, NULL, NULL, NULL); + ok(iResult != SOCKET_ERROR, "iResult = %d\n", iResult); + + /* Receive the data. */ + buffers.buf = szBuf; + buffers.len = sizeof(szBuf); + dwRecv = sizeof(szBuf); + iResult = WSARecv(sck, &buffers, 1, &dwRecv, &dwFlags, NULL, NULL); + ok(iResult != SOCKET_ERROR, "iResult = %d\n", iResult); + ok(dwRecv == sizeof(szBuf), "dwRecv %ld != %d\n", dwRecv, sizeof(szBuf)); + /* MSG_PEEK is invalid for overlapped, but passes?. */ + dwFlags = MSG_PEEK; + dwRecv = sizeof(szBuf); + ok(overlapped.hEvent != NULL, "WSACreateEvent failed %d\n", WSAGetLastError()); + iResult = WSARecv(sck, &buffers, 1, &dwRecv, &dwFlags, &overlapped, NULL); + ok(iResult != SOCKET_ERROR && (WSA_IO_PENDING != (err = WSAGetLastError())), "iResult = %d, %d\n", iResult, err); + ok(WSAGetLastError() == 0, "WSAGetLastError failed %d\n", WSAGetLastError()); + iResult = WSAWaitForMultipleEvents(1, &overlapped.hEvent, TRUE, WSARecv_TIMEOUT, TRUE); + ok(iResult != WSA_WAIT_FAILED, "WSAWaitForMultipleEvents failed %d\n", iResult); + ok(WSAGetOverlappedResult(sck, &overlapped, &dwRecv, TRUE, &dwFlags), "WSAGetOverlappedResult failed %d\n", WSAGetLastError()); + ok(dwRecv == sizeof(szBuf), "dwRecv %ld != %d\n", dwRecv, sizeof(szBuf)); + /* normal overlapped, no completion */ + buffers.buf = szBuf; + buffers.len = sizeof(szBuf); + dwFlags = 0; + dwRecv = sizeof(szBuf); + WSAResetEvent(overlapped.hEvent); + iResult = WSARecv(sck, &buffers, 1, &dwRecv, &dwFlags, &overlapped, NULL); + ok(iResult != SOCKET_ERROR && (WSA_IO_PENDING != (err = WSAGetLastError())), "iResult = %d, %d\n", iResult, err); + ok(WSAGetLastError() == 0, "WSAGetLastError failed %d\n", WSAGetLastError()); + iResult = WSAWaitForMultipleEvents(1, &overlapped.hEvent, TRUE, WSARecv_TIMEOUT, TRUE); + ok(iResult != WSA_WAIT_FAILED, "WSAWaitForMultipleEvents failed %d\n", iResult); + ok(dwRecv == sizeof(szBuf) || dwRecv == 0, "dwRecv %ld != %d and 0\n", dwRecv, sizeof(szBuf)); + if (!dwRecv) + { + dwFlags = 0; + ok(WSAGetOverlappedResult(sck, &overlapped, &dwRecv, TRUE, &dwFlags), "WSAGetOverlappedResult failed %d\n", WSAGetLastError()); + ok(dwRecv == sizeof(szBuf), "dwRecv %ld != %d\n", dwRecv, sizeof(szBuf)); + ok(WSAGetLastError() == 0, "WSAGetLastError failed %d\n", WSAGetLastError()); + } + /* overlapped with completion */ + dwFlags = 0; + dwRecv = sizeof(szBuf); + WSAResetEvent(overlapped.hEvent); + iResult = WSARecv(sck, &buffers, 1, &dwRecv, &dwFlags, &overlapped, &completion); + ok(iResult != SOCKET_ERROR && (WSA_IO_PENDING != (err = WSAGetLastError())), "iResult = %d, %d\n", iResult, err); + ok(WSAGetLastError() == 0, "WSAGetLastError failed %d\n", WSAGetLastError()); + iResult = WSAWaitForMultipleEvents(1, &overlapped.hEvent, TRUE, WSARecv_TIMEOUT, TRUE); + ok(iResult != WSA_WAIT_FAILED, "WSAWaitForMultipleEvents failed %d\n", iResult); + ok(WSACloseEvent(overlapped.hEvent), "WSAGetOverlappedResult failed %d\n", WSAGetLastError()); + ok(dwRecv == sizeof(szBuf) || dwRecv == 0, "dwRecv %ld != %d and 0\n", dwRecv, sizeof(szBuf)); + if (!dwRecv) + { + dwFlags = 0; + ok(WSAGetOverlappedResult(sck, &overlapped, &dwRecv, TRUE, &dwFlags), "WSAGetOverlappedResult failed %d\n", WSAGetLastError()); + ok(dwRecv == sizeof(szBuf), "dwRecv %ld != %d\n", dwRecv, sizeof(szBuf)); + ok(WSAGetLastError() == 0, "WSAGetLastError failed %d\n", WSAGetLastError()); + } + /* no overlapped with completion */ + dwFlags = 0; + dwRecv = sizeof(szBuf); + /* call doesn't fail, but completion is not called */ + iResult = WSARecv(sck, &buffers, 1, &dwRecv, &dwFlags, NULL, &completion); + ok(iResult != SOCKET_ERROR && (WSA_IO_PENDING != (err = WSAGetLastError())), "iResult = %d, %d\n", iResult, err); + ok(WSAGetLastError() == 0, "WSAGetLastError failed %d\n", WSAGetLastError()); + ok(dwRecv == sizeof(szBuf) || dwRecv == 0, "dwRecv %ld != %d and 0\n", dwRecv, sizeof(szBuf)); + + closesocket(sck); + WSACleanup(); + return; +} + START_TEST(recv) { Test_recv(); + Test_WSARecv(); }