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