1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 API
4 * FILE: dll/win32/ws2_32/src/startup.c
5 * PURPOSE: Startup/Cleanup Support
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ws2_32.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* DATA **********************************************************************/
17
18 PWS_SOCK_POST_ROUTINE WsSockPostRoutine = NULL;
19 CRITICAL_SECTION WsStartupLock;
20
21 #define WsStartupLock() EnterCriticalSection(&WsStartupLock)
22 #define WsStartupUnlock() LeaveCriticalSection(&WsStartupLock)
23
24 /* FUNCTIONS *****************************************************************/
25
26 VOID
27 WSAAPI
WsCreateStartupSynchronization(VOID)28 WsCreateStartupSynchronization(VOID)
29 {
30 /* Initialize the startup lock */
31 InitializeCriticalSection(&WsStartupLock);
32 }
33
34 VOID
35 WSAAPI
WsDestroyStartupSynchronization(VOID)36 WsDestroyStartupSynchronization(VOID)
37 {
38 /* Destroy the startup lock */
39 DeleteCriticalSection(&WsStartupLock);
40 }
41
42 /*
43 * @implemented
44 */
45 BOOL
46 WSAAPI
WSApSetPostRoutine(PVOID Routine)47 WSApSetPostRoutine(PVOID Routine)
48 {
49 /* Set the post routine */
50 DPRINT("WSApSetPostRoutine: %p\n", Routine);
51 WsSockPostRoutine = (PWS_SOCK_POST_ROUTINE)Routine;
52 return ERROR_SUCCESS;
53 }
54
55 /*
56 * @implemented
57 */
58 INT
59 WSAAPI
WSACleanup(VOID)60 WSACleanup(VOID)
61 {
62 PWSPROCESS Process;
63 PWSTHREAD Thread;
64 INT ErrorCode;
65 LONG RefCount;
66 DPRINT("WSACleanup\n");
67
68 /* Enter startup lock */
69 WsStartupLock();
70
71 /* Enter prolog */
72 if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS)
73 {
74 /* Decrement process reference count and check if it's zero */
75 if (!(RefCount = InterlockedDecrement(&Process->RefCount)))
76 {
77 /* It's zero, destroy the process structure */
78 WsProcDelete(Process);
79 }
80 else if (RefCount == 1 && WsAsyncThreadInitialized)
81 {
82 /* Kill async thread */
83 WsAsyncTerminateThread();
84 }
85
86 DPRINT("WSACleanup RefCount = %ld\n", RefCount);
87 /* Return success */
88 ErrorCode = ERROR_SUCCESS;
89
90 /* Clear last error */
91 SetLastError(ERROR_SUCCESS);
92 }
93 else
94 {
95 DPRINT("WSACleanup uninitialized\n");
96 /* Weren't initialized */
97 SetLastError(ErrorCode);
98 ErrorCode = SOCKET_ERROR;
99 }
100
101 /* Release startup lock */
102 WsStartupUnlock();
103
104 /* Done */
105 return ErrorCode;
106 }
107
108 /*
109 * @implemented
110 */
111 INT
112 WINAPI
WSAStartup(IN WORD wVersionRequested,OUT LPWSADATA lpWSAData)113 WSAStartup(IN WORD wVersionRequested,
114 OUT LPWSADATA lpWSAData)
115 {
116 WORD VersionReturned = 0;
117 DWORD ErrorCode = ERROR_SUCCESS;
118 PWSPROCESS CurrentProcess;
119 DPRINT("WSAStartup: %wx %d.%d\n", wVersionRequested, LOBYTE(wVersionRequested), HIBYTE(wVersionRequested));
120
121 /* Make sure that we went through DLL Init */
122 if (!WsDllHandle) return WSASYSNOTREADY;
123
124 /* Check which version is being requested */
125 switch (LOBYTE(wVersionRequested))
126 {
127 case 0:
128
129 /* We don't support this unknown version */
130 ErrorCode = WSAVERNOTSUPPORTED;
131 VersionReturned = MAKEWORD(2, 2);
132 break;
133
134 case 1:
135 /* We support only 1.0 and 1.1 */
136 if (HIBYTE(wVersionRequested) <= 1)
137 {
138 /* Caller wants 1.0, return it */
139 VersionReturned = MAKEWORD(1, HIBYTE(wVersionRequested));
140 }
141 else
142 {
143 /* The only other version we support is 1.1 */
144 VersionReturned = MAKEWORD(1, 1);
145 }
146 break;
147
148 case 2:
149 /* We support only 2.0, 2.1 and 2.2 */
150 if (HIBYTE(wVersionRequested) <= 2)
151 {
152 /* Caller wants 2.0-2.2, return it */
153 VersionReturned = MAKEWORD(2, HIBYTE(wVersionRequested));
154 }
155 else
156 {
157 /* The highest version we support is 2.2 */
158 VersionReturned = MAKEWORD(2, 2);
159 }
160 break;
161
162 default:
163
164 /* Return 2.2 */
165 VersionReturned = MAKEWORD(2, 2);
166 break;
167 }
168
169 if (lpWSAData == NULL)
170 {
171 SetLastError(WSANOTINITIALISED);
172 return ErrorCode == ERROR_SUCCESS ? WSAEFAULT : ErrorCode;
173 }
174
175 /* Return the Version Requested, unless error */
176 lpWSAData->wVersion = VersionReturned;
177
178 /* We support Winsock 2.2 */
179 lpWSAData->wHighVersion = MAKEWORD(2,2);
180 lstrcpy(lpWSAData->szDescription, "WinSock 2.0");
181 lstrcpy(lpWSAData->szSystemStatus, "Running");
182
183 /*
184 * On Winsock 1, the following values are returned.
185 * Taken straight from a Winsock Test app on Windows.
186 */
187 if (LOBYTE(wVersionRequested) == 1)
188 {
189 lpWSAData->iMaxSockets = 32767;
190 lpWSAData->iMaxUdpDg = 65467;
191 }
192 else
193 {
194 lpWSAData->iMaxSockets = 0;
195 lpWSAData->iMaxUdpDg = 0;
196 }
197
198 /* Requested invalid version (0) */
199 if (ErrorCode != ERROR_SUCCESS)
200 {
201 SetLastError(WSANOTINITIALISED);
202 return ErrorCode;
203 }
204
205 /* Enter the startup synchronization lock */
206 WsStartupLock();
207
208 /* Now setup all our objects */
209 while (TRUE)
210 {
211 /* Make sure we don't already have a process */
212 CurrentProcess = WsGetProcess();
213 if (CurrentProcess) break;
214
215 /* Setup the process object support */
216 ErrorCode = WsProcStartup();
217 if (ErrorCode != ERROR_SUCCESS) break;
218
219 /* Setup the process object support */
220 ErrorCode = WsSockStartup();
221 if (ErrorCode != ERROR_SUCCESS) break;
222
223 /* Setup the process object support */
224 ErrorCode = WsThreadStartup();
225 if (ErrorCode != ERROR_SUCCESS) break;
226
227 /* Try getting the process now */
228 CurrentProcess = WsGetProcess();
229 if (!CurrentProcess)
230 {
231 /* Something is weird... */
232 ErrorCode = WSASYSNOTREADY;
233 break;
234 }
235 }
236
237 /* Check if all worked */
238 if (ErrorCode == ERROR_SUCCESS)
239 {
240 /* Set the requested version */
241 WsProcSetVersion(CurrentProcess, wVersionRequested);
242
243 /* Increase the reference count */
244 InterlockedIncrement(&CurrentProcess->RefCount);
245 DPRINT("WSAStartup RefCount = %ld\n", CurrentProcess->RefCount);
246
247 /* Clear last error */
248 SetLastError(ERROR_SUCCESS);
249 }
250 else
251 {
252 SetLastError(WSANOTINITIALISED);
253 }
254
255 /* Leave the startup lock */
256 WsStartupUnlock();
257
258 /* Return any Error */
259 return ErrorCode;
260 }
261