1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * PURPOSE:         Test for recv
5  * PROGRAMMERS:     Colin Finck
6  */
7 
8 #include "ws2_32.h"
9 
10 #include <ndk/exfuncs.h>
11 #include <ndk/iofuncs.h>
12 #include <ndk/obfuncs.h>
13 
14 #define RECV_BUF   4
15 
16 /* For valid test results, the ReactOS Website needs to return at least 8 bytes on a "GET / HTTP/1.0" request.
17    Also the first 4 bytes and the last 4 bytes need to be different.
18    Both factors usually apply on standard HTTP responses. */
19 
20 int Test_recv()
21 {
22     const char szDummyBytes[RECV_BUF] = {0xFF, 0x00, 0xFF, 0x00};
23 
24     char szBuf1[RECV_BUF];
25     char szBuf2[RECV_BUF];
26     int iResult;
27     SOCKET sck;
28     WSADATA wdata;
29     NTSTATUS status;
30     IO_STATUS_BLOCK readIosb;
31     HANDLE readEvent;
32     LARGE_INTEGER readOffset;
33 
34     /* Start up Winsock */
35     iResult = WSAStartup(MAKEWORD(2, 2), &wdata);
36     ok(iResult == 0, "WSAStartup failed, iResult == %d\n", iResult);
37 
38     /* If we call recv without a socket, it should return with an error and do nothing. */
39     memcpy(szBuf1, szDummyBytes, RECV_BUF);
40     iResult = recv(0, szBuf1, RECV_BUF, 0);
41     ok(iResult == SOCKET_ERROR, "iRseult = %d\n", iResult);
42     ok(!memcmp(szBuf1, szDummyBytes, RECV_BUF), "not equal\n");
43 
44     /* Create the socket */
45     if (!CreateSocket(&sck))
46     {
47         ok(0, "CreateSocket failed. Aborting test.\n");
48         return 0;
49     }
50 
51     /* Now we can pass at least a socket, but we have no connection yet. Should return with an error and do nothing. */
52     memcpy(szBuf1, szDummyBytes, RECV_BUF);
53     iResult = recv(sck, szBuf1, RECV_BUF, 0);
54     ok(iResult == SOCKET_ERROR, "iResult = %d\n", iResult);
55     ok(!memcmp(szBuf1, szDummyBytes, RECV_BUF), "not equal\n");
56 
57     /* Connect to "www.reactos.org" */
58     if (!ConnectToReactOSWebsite(sck))
59     {
60         ok(0, "ConnectToReactOSWebsite failed. Aborting test.\n");
61         return 0;
62     }
63 
64     /* Send the GET request */
65     if (!GetRequestAndWait(sck))
66     {
67         ok(0, "GetRequestAndWait failed. Aborting test.\n");
68         return 0;
69     }
70 
71     /* Receive the data.
72        MSG_PEEK will not change the internal number of bytes read, so that a subsequent request should return the same bytes again. */
73     SCKTEST(recv(sck, szBuf1, RECV_BUF, MSG_PEEK));
74     SCKTEST(recv(sck, szBuf2, RECV_BUF, 0));
75     ok(!memcmp(szBuf1, szBuf2, RECV_BUF), "not equal\n");
76 
77     /* The last recv() call moved the internal file pointer, so that the next request should return different data. */
78     SCKTEST(recv(sck, szBuf1, RECV_BUF, 0));
79     ok(memcmp(szBuf1, szBuf2, RECV_BUF), "equal\n");
80 
81     /* Create an event for NtReadFile */
82     readOffset.QuadPart = 0LL;
83     memcpy(szBuf1, szBuf2, RECV_BUF);
84     status = NtCreateEvent(&readEvent,
85                            EVENT_ALL_ACCESS,
86                            NULL,
87                            NotificationEvent,
88                            FALSE);
89     if (status != 0)
90     {
91         ok(0, "Failed to create event\n");
92         return 0;
93     }
94 
95     /* Try reading the socket using the NT file API */
96     status = NtReadFile((HANDLE)sck,
97                         readEvent,
98                         NULL,
99                         NULL,
100                         &readIosb,
101                         szBuf1,
102                         RECV_BUF,
103                         &readOffset,
104                         NULL);
105     if (status == STATUS_PENDING)
106     {
107         WaitForSingleObject(readEvent, INFINITE);
108         status = readIosb.Status;
109     }
110 
111     ok(status == 0, "Read failed with status 0x%x\n", (unsigned int)status);
112     ok(memcmp(szBuf2, szBuf1, RECV_BUF), "equal\n");
113     ok(readIosb.Information == RECV_BUF, "Short read\n");
114 
115     NtClose(readEvent);
116     closesocket(sck);
117     WSACleanup();
118     return 1;
119 }
120 
121 START_TEST(recv)
122 {
123     Test_recv();
124 }
125 
126