1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         GPLv2+ - See COPYING in the top level directory
4  * PURPOSE:         Test for WSAStartup
5  * PROGRAMMER:      Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #include "ws2_32.h"
9 #include <apitest_guard.h>
10 
11 static
12 BOOLEAN
13 CheckStringBuffer(
14     PCSTR Buffer,
15     SIZE_T MaximumLength,
16     PCSTR Expected,
17     UCHAR Fill)
18 {
19     SIZE_T Length = strlen(Expected);
20     SIZE_T EqualLength;
21     BOOLEAN Result = TRUE;
22     SIZE_T i;
23 
24     EqualLength = RtlCompareMemory(Buffer, Expected, Length);
25     if (EqualLength != Length)
26     {
27         ok(0, "String is '%.*s', expected '%s'\n", (int)MaximumLength, Buffer, Expected);
28         Result = FALSE;
29     }
30 
31     if (Buffer[Length] != ANSI_NULL)
32     {
33         ok(0, "Not null terminated\n");
34         Result = FALSE;
35     }
36 
37     /* The function nulls the rest of the buffer! */
38     for (i = Length + 1; i < MaximumLength; i++)
39     {
40         UCHAR Char = ((PUCHAR)Buffer)[i];
41         if (Char != Fill)
42         {
43             ok(0, "Found 0x%x at offset %lu, expected 0x%x\n", Char, (ULONG)i, Fill);
44             /* Don't count this as a failure unless the string was actually wrong */
45             //Result = FALSE;
46             /* Don't flood the log */
47             break;
48         }
49     }
50 
51     return Result;
52 }
53 
54 static
55 BOOLEAN
56 IsWinsockInitialized(VOID)
57 {
58     struct hostent *Hostent;
59 
60     Hostent = gethostbyname("localhost");
61     if (!Hostent)
62         ok_dec(WSAGetLastError(), WSANOTINITIALISED);
63     return Hostent != NULL;
64 }
65 
66 static
67 BOOLEAN
68 AreLegacyFunctionsSupported(VOID)
69 {
70     int Error;
71 
72     Error = WSACancelBlockingCall();
73     ok(Error == SOCKET_ERROR, "Error = %d\n", Error);
74     ok(WSAGetLastError() == WSAEOPNOTSUPP ||
75        WSAGetLastError() == WSAEINVAL, "WSAGetLastError = %d\n", WSAGetLastError());
76 
77     return WSAGetLastError() != WSAEOPNOTSUPP;
78 }
79 
80 START_TEST(WSAStartup)
81 {
82     BOOLEAN Okay;
83     LPWSADATA WsaData;
84     int Error;
85     struct
86     {
87         WORD Version;
88         BOOLEAN ExpectedSuccess;
89         WORD ExpectedVersion;
90     } Tests[] =
91     {
92         { MAKEWORD(0, 0),   FALSE, MAKEWORD(2, 2) },
93         { MAKEWORD(0, 9),   FALSE, MAKEWORD(2, 2) },
94         { MAKEWORD(1, 0),   TRUE },
95         { MAKEWORD(1, 1),   TRUE },
96         { MAKEWORD(1, 2),   TRUE, MAKEWORD(1, 1) },
97         { MAKEWORD(1, 15),  TRUE, MAKEWORD(1, 1) },
98         { MAKEWORD(1, 255), TRUE, MAKEWORD(1, 1) },
99         { MAKEWORD(2, 0),   TRUE },
100         { MAKEWORD(2, 1),   TRUE },
101         { MAKEWORD(2, 2),   TRUE },
102         { MAKEWORD(2, 3),   TRUE, MAKEWORD(2, 2) },
103         { MAKEWORD(2, 15),  TRUE, MAKEWORD(2, 2) },
104         { MAKEWORD(2, 255), TRUE, MAKEWORD(2, 2) },
105         { MAKEWORD(3, 0),   TRUE, MAKEWORD(2, 2) },
106         { MAKEWORD(3, 1),   TRUE, MAKEWORD(2, 2) },
107         { MAKEWORD(3, 2),   TRUE, MAKEWORD(2, 2) },
108         { MAKEWORD(3, 3),   TRUE, MAKEWORD(2, 2) },
109         { MAKEWORD(3, 15),  TRUE, MAKEWORD(2, 2) },
110         { MAKEWORD(3, 255), TRUE, MAKEWORD(2, 2) },
111         { MAKEWORD(15, 255), TRUE, MAKEWORD(2, 2) },
112         { MAKEWORD(255, 255), TRUE, MAKEWORD(2, 2) },
113     };
114     const INT TestCount = sizeof(Tests) / sizeof(Tests[0]);
115     INT i;
116 
117     ok(!IsWinsockInitialized(), "Winsock unexpectedly initialized\n");
118 
119     /* parameter checks */
120     StartSeh()
121         Error = WSAStartup(0, NULL);
122         ok_dec(Error, WSAVERNOTSUPPORTED);
123         ok_dec(WSAGetLastError(), WSANOTINITIALISED);
124     EndSeh(STATUS_SUCCESS);
125     StartSeh()
126         Error = WSAStartup(MAKEWORD(2, 2), NULL);
127         ok_dec(Error, WSAEFAULT);
128         ok_dec(WSAGetLastError(), WSANOTINITIALISED);
129     EndSeh(STATUS_SUCCESS);
130     ok(!IsWinsockInitialized(), "Winsock unexpectedly initialized\n");
131 
132     WsaData = AllocateGuarded(sizeof(*WsaData));
133     if (!WsaData)
134     {
135         skip("Out of memory\n");
136         return;
137     }
138 
139     /* test different version */
140     for (i = 0; i < TestCount; i++)
141     {
142         trace("%d: version %d.%d\n",
143               i, LOBYTE(Tests[i].Version), HIBYTE(Tests[i].Version));
144         FillMemory(WsaData, sizeof(*WsaData), 0x55);
145         Error = WSANO_RECOVERY;
146         StartSeh()
147             Error = WSAStartup(Tests[i].Version, WsaData);
148         EndSeh(STATUS_SUCCESS);
149         if (Error)
150         {
151             ok(!Tests[i].ExpectedSuccess, "WSAStartup failed unexpectedly\n");
152             ok_dec(Error, WSAVERNOTSUPPORTED);
153             ok_dec(WSAGetLastError(), WSANOTINITIALISED);
154             ok(!IsWinsockInitialized(), "Winsock unexpectedly initialized\n");
155         }
156         else
157         {
158             ok(Tests[i].ExpectedSuccess, "WSAStartup succeeded unexpectedly\n");
159             ok_dec(WSAGetLastError(), 0);
160             ok(IsWinsockInitialized(), "Winsock not initialized despite success\n");
161             if (LOBYTE(Tests[i].Version) < 2)
162                 ok(AreLegacyFunctionsSupported(), "Legacy function failed\n");
163             else
164                 ok(!AreLegacyFunctionsSupported(), "Legacy function succeeded\n");
165             WSACleanup();
166             ok(!IsWinsockInitialized(), "Winsock still initialized after cleanup\n");
167         }
168         if (Tests[i].ExpectedVersion)
169             ok_hex(WsaData->wVersion, Tests[i].ExpectedVersion);
170         else
171             ok_hex(WsaData->wVersion, Tests[i].Version);
172         ok_hex(WsaData->wHighVersion, MAKEWORD(2, 2));
173         Okay = CheckStringBuffer(WsaData->szDescription,
174                                  sizeof(WsaData->szDescription),
175                                  "WinSock 2.0",
176                                  0x55);
177         ok(Okay, "CheckStringBuffer failed\n");
178         Okay = CheckStringBuffer(WsaData->szSystemStatus,
179                                  sizeof(WsaData->szSystemStatus),
180                                  "Running",
181                                  0x55);
182         ok(Okay, "CheckStringBuffer failed\n");
183         if (LOBYTE(WsaData->wVersion) >= 2)
184         {
185             ok_dec(WsaData->iMaxSockets, 0);
186             ok_dec(WsaData->iMaxUdpDg, 0);
187         }
188         else
189         {
190             ok_dec(WsaData->iMaxSockets, 32767);
191             ok_dec(WsaData->iMaxUdpDg, 65467);
192         }
193         ok_ptr(WsaData->lpVendorInfo, (PVOID)0x5555555555555555ULL);
194     }
195 
196     /* upgrade the version */
197     FillMemory(WsaData, sizeof(*WsaData), 0x55);
198     Error = WSAStartup(MAKEWORD(1, 1), WsaData);
199     ok_dec(Error, 0);
200     ok_dec(WSAGetLastError(), 0);
201     ok_hex(WsaData->wVersion, MAKEWORD(1, 1));
202     ok_hex(WsaData->wHighVersion, MAKEWORD(2, 2));
203     Okay = CheckStringBuffer(WsaData->szDescription,
204                              sizeof(WsaData->szDescription),
205                              "WinSock 2.0",
206                              0x55);
207     ok(Okay, "CheckStringBuffer failed\n");
208     Okay = CheckStringBuffer(WsaData->szSystemStatus,
209                              sizeof(WsaData->szSystemStatus),
210                              "Running",
211                              0x55);
212     ok(Okay, "CheckStringBuffer failed\n");
213     ok_dec(WsaData->iMaxSockets, 32767);
214     ok_dec(WsaData->iMaxUdpDg, 65467);
215     ok_ptr(WsaData->lpVendorInfo, (PVOID)0x5555555555555555ULL);
216     ok(IsWinsockInitialized(), "Winsock not initialized\n");
217     if (!Error)
218     {
219         ok(AreLegacyFunctionsSupported(), "Legacy function failed\n");
220         FillMemory(WsaData, sizeof(*WsaData), 0x55);
221         Error = WSAStartup(MAKEWORD(2, 2), WsaData);
222         ok_dec(Error, 0);
223         ok_hex(WsaData->wVersion, MAKEWORD(2, 2));
224         ok_hex(WsaData->wHighVersion, MAKEWORD(2, 2));
225         Okay = CheckStringBuffer(WsaData->szDescription,
226                                  sizeof(WsaData->szDescription),
227                                  "WinSock 2.0",
228                                  0x55);
229         ok(Okay, "CheckStringBuffer failed\n");
230         Okay = CheckStringBuffer(WsaData->szSystemStatus,
231                                  sizeof(WsaData->szSystemStatus),
232                                  "Running",
233                                  0x55);
234         ok(Okay, "CheckStringBuffer failed\n");
235         ok_dec(WsaData->iMaxSockets, 0);
236         ok_dec(WsaData->iMaxUdpDg, 0);
237         ok_ptr(WsaData->lpVendorInfo, (PVOID)0x5555555555555555ULL);
238         if (!Error)
239         {
240             ok(AreLegacyFunctionsSupported(), "Legacy function failed\n");
241             WSACleanup();
242             ok(IsWinsockInitialized(), "Winsock prematurely uninitialized\n");
243         }
244         WSACleanup();
245         ok(!IsWinsockInitialized(), "Winsock still initialized after cleanup\n");
246     }
247 
248     /* downgrade the version */
249     FillMemory(WsaData, sizeof(*WsaData), 0x55);
250     Error = WSAStartup(MAKEWORD(2, 2), WsaData);
251     ok_dec(Error, 0);
252     ok_dec(WSAGetLastError(), 0);
253     ok_hex(WsaData->wVersion, MAKEWORD(2, 2));
254     ok_hex(WsaData->wHighVersion, MAKEWORD(2, 2));
255     Okay = CheckStringBuffer(WsaData->szDescription,
256                              sizeof(WsaData->szDescription),
257                              "WinSock 2.0",
258                              0x55);
259     ok(Okay, "CheckStringBuffer failed\n");
260     Okay = CheckStringBuffer(WsaData->szSystemStatus,
261                              sizeof(WsaData->szSystemStatus),
262                              "Running",
263                              0x55);
264     ok(Okay, "CheckStringBuffer failed\n");
265     ok_dec(WsaData->iMaxSockets, 0);
266     ok_dec(WsaData->iMaxUdpDg, 0);
267     ok_ptr(WsaData->lpVendorInfo, (PVOID)0x5555555555555555ULL);
268     ok(IsWinsockInitialized(), "Winsock not initialized\n");
269     if (!Error)
270     {
271         ok(!AreLegacyFunctionsSupported(), "Legacy function succeeded\n");
272         FillMemory(WsaData, sizeof(*WsaData), 0x55);
273         Error = WSAStartup(MAKEWORD(1, 1), WsaData);
274         ok_dec(Error, 0);
275         ok_hex(WsaData->wVersion, MAKEWORD(1, 1));
276         ok_hex(WsaData->wHighVersion, MAKEWORD(2, 2));
277         Okay = CheckStringBuffer(WsaData->szDescription,
278                                  sizeof(WsaData->szDescription),
279                                  "WinSock 2.0",
280                                  0x55);
281         ok(Okay, "CheckStringBuffer failed\n");
282         Okay = CheckStringBuffer(WsaData->szSystemStatus,
283                                  sizeof(WsaData->szSystemStatus),
284                                  "Running",
285                                  0x55);
286         ok(Okay, "CheckStringBuffer failed\n");
287         ok_dec(WsaData->iMaxSockets, 32767);
288         ok_dec(WsaData->iMaxUdpDg, 65467);
289         ok_ptr(WsaData->lpVendorInfo, (PVOID)0x5555555555555555ULL);
290         if (!Error)
291         {
292             ok(AreLegacyFunctionsSupported(), "Legacy function failed\n");
293             WSACleanup();
294             ok(IsWinsockInitialized(), "Winsock prematurely uninitialized\n");
295         }
296         WSACleanup();
297         ok(!IsWinsockInitialized(), "Winsock still initialized after cleanup\n");
298     }
299 
300     FreeGuarded(WsaData);
301 }
302