d7b10771f7d98d9fae03c9b1e8e76ca4a57d452b
[reactos.git] / reactos / lib / ws2_32 / misc / dllmain.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 DLL
4 * FILE: misc/dllmain.c
5 * PURPOSE: DLL entry point
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/09-2000 Created
9 */
10 #include <ws2_32.h>
11 #include <catalog.h>
12 #include <handle.h>
13 #include <upcall.h>
14
15 #ifdef DBG
16
17 /* See debug.h for debug/trace constants */
18 DWORD DebugTraceLevel = MIN_TRACE;
19 //DWORD DebugTraceLevel = MAX_TRACE;
20
21 #endif /* DBG */
22
23 /* To make the linker happy */
24 VOID STDCALL KeBugCheck (ULONG BugCheckCode) {}
25
26
27 HANDLE GlobalHeap;
28 WSPUPCALLTABLE UpcallTable;
29
30
31 INT
32 EXPORT
33 WSAGetLastError(VOID)
34 {
35 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
36
37 if (p) {
38 return p->LastErrorValue;
39 } else {
40 /* FIXME: What error code should we use here? Can this even happen? */
41 return ERROR_BAD_ENVIRONMENT;
42 }
43 }
44
45
46 VOID
47 EXPORT
48 WSASetLastError(
49 IN INT iError)
50 {
51 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
52
53 if (p)
54 p->LastErrorValue = iError;
55 }
56
57
58 INT
59 EXPORT
60 WSAStartup(
61 IN WORD wVersionRequested,
62 OUT LPWSADATA lpWSAData)
63 {
64 WS_DbgPrint(MAX_TRACE, ("WSAStartup of ws2_32.dll\n"));
65
66 lpWSAData->wVersion = wVersionRequested;
67 lpWSAData->wHighVersion = 2;
68 lstrcpyA(lpWSAData->szDescription, "WinSock 2.0");
69 lstrcpyA(lpWSAData->szSystemStatus, "Running");
70 lpWSAData->iMaxSockets = 0;
71 lpWSAData->iMaxUdpDg = 0;
72 lpWSAData->lpVendorInfo = NULL;
73
74 WSASETINITIALIZED;
75
76 return NO_ERROR;
77 }
78
79
80 INT
81 EXPORT
82 WSACleanup(VOID)
83 {
84 WS_DbgPrint(MAX_TRACE, ("WSACleanup of ws2_32.dll\n"));
85
86 if (!WSAINITIALIZED) {
87 WSASetLastError(WSANOTINITIALISED);
88 return WSANOTINITIALISED;
89 }
90
91 return NO_ERROR;
92 }
93
94
95 SOCKET
96 EXPORT
97 WSASocketA(
98 IN INT af,
99 IN INT type,
100 IN INT protocol,
101 IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
102 IN GROUP g,
103 IN DWORD dwFlags)
104 /*
105 * FUNCTION: Creates a new socket
106 */
107 {
108 WSAPROTOCOL_INFOW ProtocolInfoW;
109 LPWSAPROTOCOL_INFOW p;
110 UNICODE_STRING StringU;
111 ANSI_STRING StringA;
112
113 WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n",
114 af, type, protocol));
115
116 if (lpProtocolInfo) {
117 memcpy(&ProtocolInfoW,
118 lpProtocolInfo,
119 sizeof(WSAPROTOCOL_INFOA) -
120 sizeof(CHAR) * (WSAPROTOCOL_LEN + 1));
121 RtlInitAnsiString(&StringA, (LPSTR)lpProtocolInfo->szProtocol);
122 RtlInitUnicodeString(&StringU, (LPWSTR)&ProtocolInfoW.szProtocol);
123 RtlAnsiStringToUnicodeString(&StringU, &StringA, FALSE);
124 p = &ProtocolInfoW;
125 } else {
126 p = NULL;
127 }
128
129 return WSASocketW(af,
130 type,
131 protocol,
132 p,
133 g,
134 dwFlags);
135 }
136
137
138 SOCKET
139 EXPORT
140 WSASocketW(
141 IN INT af,
142 IN INT type,
143 IN INT protocol,
144 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
145 IN GROUP g,
146 IN DWORD dwFlags)
147 /*
148 * FUNCTION: Creates a new socket descriptor
149 * ARGUMENTS:
150 * af = Address family
151 * type = Socket type
152 * protocol = Protocol type
153 * lpProtocolInfo = Pointer to protocol information
154 * g = Reserved
155 * dwFlags = Socket flags
156 * RETURNS:
157 * Created socket descriptor, or INVALID_SOCKET if it could not be created
158 */
159 {
160 INT Status;
161 SOCKET Socket;
162 PCATALOG_ENTRY Provider;
163 WSAPROTOCOL_INFOW ProtocolInfo;
164
165 WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n",
166 af, type, protocol));
167
168 if (!WSAINITIALIZED) {
169 WSASetLastError(WSANOTINITIALISED);
170 return INVALID_SOCKET;
171 }
172
173 if (!lpProtocolInfo) {
174 lpProtocolInfo = &ProtocolInfo;
175 ZeroMemory(&ProtocolInfo, sizeof(WSAPROTOCOL_INFOW));
176
177 ProtocolInfo.iAddressFamily = af;
178 ProtocolInfo.iSocketType = type;
179 ProtocolInfo.iProtocol = protocol;
180 }
181
182 Provider = LocateProvider(lpProtocolInfo);
183 if (!Provider) {
184 WSASetLastError(WSAEAFNOSUPPORT);
185 return INVALID_SOCKET;
186 }
187
188 Status = LoadProvider(Provider, lpProtocolInfo);
189 if (Status != NO_ERROR) {
190 WSASetLastError(Status);
191 return INVALID_SOCKET;
192 }
193
194 WS_DbgPrint(MAX_TRACE, ("Calling WSPSocket at (0x%X).\n",
195 Provider->ProcTable.lpWSPSocket));
196
197 assert(Provider->ProcTable.lpWSPSocket);
198
199 Socket = Provider->ProcTable.lpWSPSocket(
200 af,
201 type,
202 protocol,
203 lpProtocolInfo,
204 g,
205 dwFlags,
206 &Status);
207 if (Status != NO_ERROR) {
208 WSASetLastError(Status);
209 return INVALID_SOCKET;
210 }
211
212 return Socket;
213 }
214
215
216 INT
217 EXPORT
218 closesocket(
219 IN SOCKET s)
220 /*
221 * FUNCTION: Closes a socket descriptor
222 * ARGUMENTS:
223 * s = Socket descriptor
224 * RETURNS:
225 * 0, or SOCKET_ERROR if an error ocurred
226 */
227 {
228 PCATALOG_ENTRY Provider;
229 INT Errno;
230 INT Code;
231
232 WS_DbgPrint(MAX_TRACE, ("s (0x%X).\n", s));
233
234 if (!WSAINITIALIZED) {
235 WSASetLastError(WSANOTINITIALISED);
236 return SOCKET_ERROR;
237 }
238
239 if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
240 WSASetLastError(WSAENOTSOCK);
241 return SOCKET_ERROR;
242 }
243
244 CloseProviderHandle((HANDLE)s);
245
246 DereferenceProviderByPointer(Provider);
247
248 Code = Provider->ProcTable.lpWSPCloseSocket(s, &Errno);
249 if (Code == SOCKET_ERROR)
250 WSASetLastError(Errno);
251
252 return 0;
253 }
254
255
256 INT
257 EXPORT
258 select(
259 IN INT nfds,
260 IN OUT LPFD_SET readfds,
261 IN OUT LPFD_SET writefds,
262 IN OUT LPFD_SET exceptfds,
263 IN CONST LPTIMEVAL timeout)
264 /*
265 * FUNCTION: Returns status of one or more sockets
266 * ARGUMENTS:
267 * nfds = Always ignored
268 * readfds = Pointer to socket set to be checked for readability (optional)
269 * writefds = Pointer to socket set to be checked for writability (optional)
270 * exceptfds = Pointer to socket set to be checked for errors (optional)
271 * timeout = Pointer to a TIMEVAL structure indicating maximum wait time
272 * (NULL means wait forever)
273 * RETURNS:
274 * Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred
275 */
276 {
277 PCATALOG_ENTRY Provider;
278 INT Count;
279 INT Errno;
280 ULONG i;
281
282 WS_DbgPrint(MAX_TRACE, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n",
283 readfds, writefds, exceptfds));
284
285 if (!WSAINITIALIZED) {
286 WSASetLastError(WSANOTINITIALISED);
287 return SOCKET_ERROR;
288 }
289
290 /* FIXME: Sockets in FD_SETs should be sorted by their provider */
291
292 /* FIXME: For now, assume only one service provider */
293 if ((readfds != NULL) && (readfds->fd_count > 0)) {
294 if (!ReferenceProviderByHandle((HANDLE)readfds->fd_array[0], &Provider)) {
295 WSASetLastError(WSAENOTSOCK);
296 return SOCKET_ERROR;
297 }
298 } else if ((writefds != NULL) && (writefds->fd_count > 0)) {
299 if (!ReferenceProviderByHandle((HANDLE)writefds->fd_array[0], &Provider)) {
300 WSASetLastError(WSAENOTSOCK);
301 return SOCKET_ERROR;
302 }
303 } else if ((exceptfds != NULL) && (exceptfds->fd_count > 0)) {
304 if (!ReferenceProviderByHandle((HANDLE)exceptfds->fd_array[0], &Provider)) {
305 WSASetLastError(WSAENOTSOCK);
306 return SOCKET_ERROR;
307 }
308 } else {
309 WSASetLastError(WSAEINVAL);
310 return SOCKET_ERROR;
311 }
312
313 Count = Provider->ProcTable.lpWSPSelect(
314 nfds, readfds, writefds, exceptfds, timeout, &Errno);
315
316 WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider));
317
318 DereferenceProviderByPointer(Provider);
319
320 WSASetLastError(Errno);
321
322 if (Errno != NO_ERROR)
323 return SOCKET_ERROR;
324
325 return Count;
326 }
327
328
329 BOOL
330 STDCALL
331 DllMain(HANDLE hInstDll,
332 ULONG dwReason,
333 LPVOID lpReserved)
334 {
335 PWINSOCK_THREAD_BLOCK p;
336
337 WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll.\n"));
338
339 switch (dwReason) {
340 case DLL_PROCESS_ATTACH:
341 GlobalHeap = GetProcessHeap();
342
343 CreateCatalog();
344
345 InitProviderHandleTable();
346
347 UpcallTable.lpWPUCloseEvent = WPUCloseEvent;
348 UpcallTable.lpWPUCloseSocketHandle = WPUCloseSocketHandle;
349 UpcallTable.lpWPUCreateEvent = WPUCreateEvent;
350 UpcallTable.lpWPUCreateSocketHandle = WPUCreateSocketHandle;
351 UpcallTable.lpWPUFDIsSet = WPUFDIsSet;
352 UpcallTable.lpWPUGetProviderPath = WPUGetProviderPath;
353 UpcallTable.lpWPUModifyIFSHandle = WPUModifyIFSHandle;
354 UpcallTable.lpWPUPostMessage = WPUPostMessage;
355 UpcallTable.lpWPUQueryBlockingCallback = WPUQueryBlockingCallback;
356 UpcallTable.lpWPUQuerySocketHandleContext = WPUQuerySocketHandleContext;
357 UpcallTable.lpWPUQueueApc = WPUQueueApc;
358 UpcallTable.lpWPUResetEvent = WPUResetEvent;
359 UpcallTable.lpWPUSetEvent = WPUSetEvent;
360 UpcallTable.lpWPUOpenCurrentThread = WPUOpenCurrentThread;
361 UpcallTable.lpWPUCloseThread = WPUCloseThread;
362
363 /* Fall through to thread attachment handler */
364
365 case DLL_THREAD_ATTACH:
366 p = HeapAlloc(GlobalHeap, 0, sizeof(WINSOCK_THREAD_BLOCK));
367
368 WS_DbgPrint(MAX_TRACE, ("Thread block at 0x%X.\n", p));
369
370 if (!p) {
371 return FALSE;
372 }
373
374 p->LastErrorValue = NO_ERROR;
375 p->Initialized = FALSE;
376
377 NtCurrentTeb()->WinSockData = p;
378 break;
379
380 case DLL_PROCESS_DETACH:
381 p = NtCurrentTeb()->WinSockData;
382
383 if (p)
384 HeapFree(GlobalHeap, 0, p);
385
386 DestroyCatalog();
387
388 FreeProviderHandleTable();
389 break;
390
391 case DLL_THREAD_DETACH:
392 p = NtCurrentTeb()->WinSockData;
393
394 if (p)
395 HeapFree(GlobalHeap, 0, p);
396 break;
397 }
398
399 return TRUE;
400 }
401
402 /* EOF */