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