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