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