xref: /reactos/dll/win32/ws2_32/src/startup.c (revision 84344399)
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
28 WsCreateStartupSynchronization(VOID)
29 {
30     /* Initialize the startup lock */
31     InitializeCriticalSection(&WsStartupLock);
32 }
33 
34 VOID
35 WSAAPI
36 WsDestroyStartupSynchronization(VOID)
37 {
38     /* Destroy the startup lock */
39     DeleteCriticalSection(&WsStartupLock);
40 }
41 
42 /*
43  * @implemented
44  */
45 BOOL
46 WSAAPI
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
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
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