diff --git a/reactos/dll/win32/ws2_32/misc/dllmain.c b/reactos/dll/win32/ws2_32/misc/dllmain.c index 18b1a02f7a3..c9e07cb4c9f 100644 --- a/reactos/dll/win32/ws2_32/misc/dllmain.c +++ b/reactos/dll/win32/ws2_32/misc/dllmain.c @@ -166,7 +166,7 @@ socket(IN INT af, IN INT type, IN INT protocol) { - return WSASocketA(af, + return WSASocketW(af, type, protocol, NULL, diff --git a/reactos/drivers/network/afd/afd/info.c b/reactos/drivers/network/afd/afd/info.c index 32c02bb85c1..3339f339b67 100644 --- a/reactos/drivers/network/afd/afd/info.c +++ b/reactos/drivers/network/afd/afd/info.c @@ -49,9 +49,9 @@ AfdGetInfo( PDEVICE_OBJECT DeviceObject, PIRP Irp, break; case AFD_INFO_RECEIVE_CONTENT_SIZE: - /* Only touch InfoReq if we actually have a valid connection. + /* Only touch InfoReq if a socket has been set up. Behaviour was verified under WinXP SP2. */ - if(FCB->Connection.Handle) + if(FCB->AddressFile.Object) InfoReq->Information.Ulong = FCB->Recv.Content - FCB->Recv.BytesUsed; break; diff --git a/rostests/apitests/directory.rbuild b/rostests/apitests/directory.rbuild index 372db3db1e8..85e422f710b 100644 --- a/rostests/apitests/directory.rbuild +++ b/rostests/apitests/directory.rbuild @@ -23,4 +23,8 @@ + + + + diff --git a/rostests/apitests/ws2_32/helpers.c b/rostests/apitests/ws2_32/helpers.c new file mode 100644 index 00000000000..9033aed184f --- /dev/null +++ b/rostests/apitests/ws2_32/helpers.c @@ -0,0 +1,65 @@ +/* + * PROJECT: ws2_32.dll API tests + * LICENSE: GPLv2 or any later version + * FILE: apitests/ws2_32/helpers.c + * PURPOSE: Helper functions for the socket tests + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#include "ws2_32.h" + +int CreateSocket(PTESTINFO pti, SOCKET* psck) +{ + /* Create the socket */ + *psck = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + TEST(*psck != INVALID_SOCKET); + + if(*psck == INVALID_SOCKET) + { + printf("Winsock error code is %u\n", WSAGetLastError()); + WSACleanup(); + return APISTATUS_ASSERTION_FAILED; + } + + return APISTATUS_NORMAL; +} + +int ConnectToReactOSWebsite(PTESTINFO pti, SOCKET sck) +{ + int iResult; + struct hostent* host; + struct sockaddr_in sa; + + /* Connect to "www.reactos.org" */ + host = gethostbyname("www.reactos.org"); + + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = *(u_long*)host->h_addr_list[0]; + sa.sin_port = htons(80); + + SCKTEST(connect(sck, (struct sockaddr *)&sa, sizeof(sa))); + + return APISTATUS_NORMAL; +} + +int GetRequestAndWait(PTESTINFO pti, SOCKET sck) +{ + const char szGetRequest[] = "GET / HTTP/1.0\r\n\r\n"; + int iResult; + struct fd_set readable; + + /* Send the GET request */ + SCKTEST(send(sck, szGetRequest, strlen(szGetRequest), 0)); + TEST(iResult == strlen(szGetRequest)); + + /* Shutdown the SEND connection */ + SCKTEST(shutdown(sck, SD_SEND)); + + /* Wait until we're ready to read */ + FD_ZERO(&readable); + FD_SET(sck, &readable); + + SCKTEST(select(0, &readable, NULL, NULL, NULL)); + + return APISTATUS_NORMAL; +} diff --git a/rostests/apitests/ws2_32/testlist.c b/rostests/apitests/ws2_32/testlist.c new file mode 100644 index 00000000000..fa579807f3f --- /dev/null +++ b/rostests/apitests/ws2_32/testlist.c @@ -0,0 +1,33 @@ +/* + * PROJECT: ws2_32.dll API tests + * LICENSE: GPLv2 or any later version + * FILE: apitests/ws2_32/testlist.c + * PURPOSE: Test list file + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#ifndef _WS2_32_TESTLIST_H +#define _WS2_32_TESTLIST_H + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + +#include "ws2_32.h" + +/* include the tests */ +#include "tests/ioctlsocket.c" +#include "tests/recv.c" + +/* The List of tests */ +TESTENTRY TestList[] = +{ + { L"ioctlsocket", Test_ioctlsocket }, + { L"recv", Test_recv } +}; + +/* The function that gives us the number of tests */ +INT NumTests(void) +{ + return ARRAY_SIZE(TestList); +} + +#endif diff --git a/rostests/apitests/ws2_32/tests/ioctlsocket.c b/rostests/apitests/ws2_32/tests/ioctlsocket.c new file mode 100644 index 00000000000..2d291f7eb4e --- /dev/null +++ b/rostests/apitests/ws2_32/tests/ioctlsocket.c @@ -0,0 +1,83 @@ +/* + * PROJECT: ws2_32.dll API tests + * LICENSE: GPLv2 or any later version + * FILE: apitests/ws2_32/tests/ioctlsocket.c + * PURPOSE: Tests for the ioctlsocket function + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#include "../ws2_32.h" + +/* For valid test results, the ReactOS Website needs to return at least 2 bytes on a "GET / HTTP/1.0" request. */ +INT +Test_ioctlsocket(PTESTINFO pti) +{ + LPSTR pszBuf; + int iResult; + SOCKET sck; + ULONG BytesAvailable; + ULONG BytesToRead; + WSADATA wdata; + + /* Start up Winsock */ + TEST(WSAStartup(MAKEWORD(2, 2), &wdata) == 0); + + /* If we call ioctlsocket without a socket, it should return with an error and do nothing. */ + BytesAvailable = 0xdeadbeef; + TEST(ioctlsocket(0, FIONREAD, &BytesAvailable) == SOCKET_ERROR); + TEST(BytesAvailable == 0xdeadbeef); + + /* Create the socket */ + iResult = CreateSocket(pti, &sck); + if(iResult != APISTATUS_NORMAL) + return iResult; + + /* Now we can pass at least a socket, but we have no connection yet. The function should return 0. */ + BytesAvailable = 0xdeadbeef; + TEST(ioctlsocket(sck, FIONREAD, &BytesAvailable) == 0); + TEST(BytesAvailable == 0); + + /* Connect to "www.reactos.org" */ + iResult = ConnectToReactOSWebsite(pti, sck); + if(iResult != APISTATUS_NORMAL) + return iResult; + + /* Even with a connection, there shouldn't be any bytes available. */ + TEST(ioctlsocket(sck, FIONREAD, &BytesAvailable) == 0); + TEST(BytesAvailable == 0); + + /* Send the GET request */ + iResult = GetRequestAndWait(pti, sck); + if(iResult != APISTATUS_NORMAL) + return iResult; + + /* Try ioctlsocket with FIONREAD. There should be bytes available now. */ + SCKTEST(ioctlsocket(sck, FIONREAD, &BytesAvailable)); + TEST(BytesAvailable != 0); + + /* Get half of the data */ + BytesToRead = BytesAvailable / 2; + pszBuf = (LPSTR) HeapAlloc(g_hHeap, 0, BytesToRead); + SCKTEST(recv(sck, pszBuf, BytesToRead, 0)); + HeapFree(g_hHeap, 0, pszBuf); + + BytesToRead = BytesAvailable - BytesToRead; + + /* Now try ioctlsocket again. BytesAvailable should be at the value saved in BytesToRead now. */ + SCKTEST(ioctlsocket(sck, FIONREAD, &BytesAvailable)); + TEST(BytesAvailable == BytesToRead); + + /* Read those bytes */ + pszBuf = (LPSTR) HeapAlloc(g_hHeap, 0, BytesToRead); + SCKTEST(recv(sck, pszBuf, BytesToRead, 0)); + HeapFree(g_hHeap, 0, pszBuf); + + /* Try it for the last time. BytesAvailable should be at 0 now. */ + SCKTEST(ioctlsocket(sck, FIONREAD, &BytesAvailable)); + TEST(BytesAvailable == 0); + + closesocket(sck); + WSACleanup(); + + return APISTATUS_NORMAL; +} diff --git a/rostests/apitests/ws2_32/tests/recv.c b/rostests/apitests/ws2_32/tests/recv.c new file mode 100644 index 00000000000..4df6c0ecabd --- /dev/null +++ b/rostests/apitests/ws2_32/tests/recv.c @@ -0,0 +1,69 @@ +/* + * PROJECT: ws2_32.dll API tests + * LICENSE: GPLv2 or any later version + * FILE: apitests/ws2_32/tests/recv.c + * PURPOSE: Tests for the recv function + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#include "../ws2_32.h" + +#define RECV_BUF 4 + +/* For valid test results, the ReactOS Website needs to return at least 8 bytes on a "GET / HTTP/1.0" request. + Also the first 4 bytes and the last 4 bytes need to be different. + Both factors usually apply on standard HTTP responses. */ +INT +Test_recv(PTESTINFO pti) +{ + const char szDummyBytes[RECV_BUF] = {0xFF, 0x00, 0xFF, 0x00}; + + char szBuf1[RECV_BUF]; + char szBuf2[RECV_BUF]; + int iResult; + SOCKET sck; + WSADATA wdata; + + /* Start up Winsock */ + TEST(WSAStartup(MAKEWORD(2, 2), &wdata) == 0); + + /* If we call recv without a socket, it should return with an error and do nothing. */ + memcpy(szBuf1, szDummyBytes, RECV_BUF); + TEST(recv(0, szBuf1, RECV_BUF, 0) == SOCKET_ERROR); + TEST(!memcmp(szBuf1, szDummyBytes, RECV_BUF)); + + /* Create the socket */ + iResult = CreateSocket(pti, &sck); + if(iResult != APISTATUS_NORMAL) + return iResult; + + /* Now we can pass at least a socket, but we have no connection yet. Should return with an error and do nothing. */ + memcpy(szBuf1, szDummyBytes, RECV_BUF); + TEST(recv(sck, szBuf1, RECV_BUF, 0) == SOCKET_ERROR); + TEST(!memcmp(szBuf1, szDummyBytes, RECV_BUF)); + + /* Connect to "www.reactos.org" */ + iResult = ConnectToReactOSWebsite(pti, sck); + if(iResult != APISTATUS_NORMAL) + return iResult; + + /* Send the GET request */ + iResult = GetRequestAndWait(pti, sck); + if(iResult != APISTATUS_NORMAL) + return iResult; + + /* Receive the data. + MSG_PEEK will not change the internal number of bytes read, so that a subsequent request should return the same bytes again. */ + SCKTEST(recv(sck, szBuf1, RECV_BUF, MSG_PEEK)); + SCKTEST(recv(sck, szBuf2, RECV_BUF, 0)); + TEST(!memcmp(szBuf1, szBuf2, RECV_BUF)); + + /* The last recv() call moved the internal file pointer, so that the next request should return different data. */ + SCKTEST(recv(sck, szBuf1, RECV_BUF, 0)); + TEST(memcmp(szBuf1, szBuf2, RECV_BUF)); + + closesocket(sck); + WSACleanup(); + + return APISTATUS_NORMAL; +} diff --git a/rostests/apitests/ws2_32/ws2_32.c b/rostests/apitests/ws2_32/ws2_32.c new file mode 100644 index 00000000000..42e8a9b68eb --- /dev/null +++ b/rostests/apitests/ws2_32/ws2_32.c @@ -0,0 +1,24 @@ +/* + * PROJECT: ws2_32.dll API tests + * LICENSE: GPLv2 or any later version + * FILE: apitests/ws2_32/ws2_32.c + * PURPOSE: Program entry point + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#include "ws2_32.h" + +HANDLE g_hHeap; + +BOOL +IsFunctionPresent(LPWSTR lpszFunction) +{ + return TRUE; +} + +int wmain() +{ + g_hHeap = GetProcessHeap(); + + return TestMain(L"ws2_32_apitests", L"ws2_32.dll"); +} diff --git a/rostests/apitests/ws2_32/ws2_32.h b/rostests/apitests/ws2_32/ws2_32.h new file mode 100644 index 00000000000..6fe52408fe8 --- /dev/null +++ b/rostests/apitests/ws2_32/ws2_32.h @@ -0,0 +1,36 @@ +/* + * PROJECT: ws2_32.dll API tests + * LICENSE: GPLv2 or any later version + * FILE: apitests/ws2_32/ws2_32.h + * PURPOSE: Main header file + * COPYRIGHT: Copyright 2008 Colin Finck + */ + +#ifndef _WS2_32_APITESTS_H +#define _WS2_32_APITESTS_H + +#include + +#include "../apitest.h" + +/* Simple macro for executing a socket command and doing cleanup operations in case of a failure */ +#define SCKTEST(_cmd_) \ + iResult = _cmd_; \ + TEST(iResult != SOCKET_ERROR); \ + if(iResult == SOCKET_ERROR) \ + { \ + printf("Winsock error code is %u\n", WSAGetLastError()); \ + closesocket(sck); \ + WSACleanup(); \ + return APISTATUS_ASSERTION_FAILED; \ + } + +/* helpers.c */ +int CreateSocket(PTESTINFO pti, SOCKET* sck); +int ConnectToReactOSWebsite(PTESTINFO pti, SOCKET sck); +int GetRequestAndWait(PTESTINFO pti, SOCKET sck); + +/* ws2_32.c */ +extern HANDLE g_hHeap; + +#endif diff --git a/rostests/apitests/ws2_32/ws2_32.rbuild b/rostests/apitests/ws2_32/ws2_32.rbuild new file mode 100644 index 00000000000..e86f3cc04f8 --- /dev/null +++ b/rostests/apitests/ws2_32/ws2_32.rbuild @@ -0,0 +1,11 @@ + + 0x0501 + apitest + kernel32 + user32 + shell32 + ws2_32 + helpers.c + testlist.c + ws2_32.c +