:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / 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 = DEBUG_ULTRA;
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 socket(
98   IN  INT af,
99   IN  INT type,
100   IN  INT protocol)
101 {
102   return WSASocketA(af, type, protocol, NULL, 0, 0);
103 }
104
105
106 SOCKET
107 EXPORT
108 WSASocketA(
109     IN  INT af,
110     IN  INT type,
111     IN  INT protocol,
112     IN  LPWSAPROTOCOL_INFOA lpProtocolInfo,
113     IN  GROUP g,
114     IN  DWORD dwFlags)
115 /*
116  * FUNCTION: Creates a new socket
117  */
118 {
119   WSAPROTOCOL_INFOW ProtocolInfoW;
120   LPWSAPROTOCOL_INFOW p;
121   UNICODE_STRING StringU;
122   ANSI_STRING StringA;
123
124         WS_DbgPrint(MAX_TRACE, ("af (%d)  type (%d)  protocol (%d).\n",
125     af, type, protocol));
126
127   if (lpProtocolInfo) {
128     memcpy(&ProtocolInfoW,
129       lpProtocolInfo,
130       sizeof(WSAPROTOCOL_INFOA) -
131       sizeof(CHAR) * (WSAPROTOCOL_LEN + 1));
132     RtlInitAnsiString(&StringA, (LPSTR)lpProtocolInfo->szProtocol);
133     RtlInitUnicodeString(&StringU, (LPWSTR)&ProtocolInfoW.szProtocol);
134     RtlAnsiStringToUnicodeString(&StringU, &StringA, FALSE);
135     p = &ProtocolInfoW;
136   } else {
137     p = NULL;
138   }
139
140   return WSASocketW(af,
141     type,
142     protocol,
143     p,
144     g,
145     dwFlags);
146 }
147
148
149 SOCKET
150 EXPORT
151 WSASocketW(
152     IN  INT af,
153     IN  INT type,
154     IN  INT protocol,
155     IN  LPWSAPROTOCOL_INFOW lpProtocolInfo,
156     IN  GROUP g,
157     IN  DWORD dwFlags)
158 /*
159  * FUNCTION: Creates a new socket descriptor
160  * ARGUMENTS:
161  *     af             = Address family
162  *     type           = Socket type
163  *     protocol       = Protocol type
164  *     lpProtocolInfo = Pointer to protocol information
165  *     g              = Reserved
166  *     dwFlags        = Socket flags
167  * RETURNS:
168  *     Created socket descriptor, or INVALID_SOCKET if it could not be created
169  */
170 {
171   INT Status;
172   SOCKET Socket;
173   PCATALOG_ENTRY Provider;
174   WSAPROTOCOL_INFOW ProtocolInfo;
175
176   WS_DbgPrint(MAX_TRACE, ("af (%d)  type (%d)  protocol (%d).\n",
177       af, type, protocol));
178
179   if (!WSAINITIALIZED) {
180       WSASetLastError(WSANOTINITIALISED);
181       return INVALID_SOCKET;
182   }
183
184   if (!lpProtocolInfo) {
185     lpProtocolInfo = &ProtocolInfo;
186     ZeroMemory(&ProtocolInfo, sizeof(WSAPROTOCOL_INFOW));
187
188     ProtocolInfo.iAddressFamily = af;
189     ProtocolInfo.iSocketType    = type;
190     ProtocolInfo.iProtocol      = protocol;
191   }
192
193   Provider = LocateProvider(lpProtocolInfo);
194   if (!Provider) {
195     WSASetLastError(WSAEAFNOSUPPORT);
196     return INVALID_SOCKET;
197   }
198
199   Status = LoadProvider(Provider, lpProtocolInfo);
200   if (Status != NO_ERROR) {
201     WSASetLastError(Status);
202     return INVALID_SOCKET;
203   }
204
205   WS_DbgPrint(MAX_TRACE, ("Calling WSPSocket at (0x%X).\n",
206     Provider->ProcTable.lpWSPSocket));
207
208   assert(Provider->ProcTable.lpWSPSocket);
209
210   Socket = Provider->ProcTable.lpWSPSocket(
211     af,
212     type,
213     protocol,
214     lpProtocolInfo,
215     g,
216     dwFlags,
217     &Status);
218         if (Status != NO_ERROR) {
219     WSASetLastError(Status);
220     return INVALID_SOCKET;
221   }
222
223   return Socket;
224 }
225
226
227 INT
228 EXPORT
229 closesocket(
230     IN  SOCKET s)
231 /*
232  * FUNCTION: Closes a socket descriptor
233  * ARGUMENTS:
234  *     s = Socket descriptor
235  * RETURNS:
236  *     0, or SOCKET_ERROR if an error ocurred
237  */
238 {
239   PCATALOG_ENTRY Provider;
240   INT Status;
241   INT Errno;
242
243   WS_DbgPrint(MAX_TRACE, ("s (0x%X).\n", s));
244
245   if (!WSAINITIALIZED) {
246     WSASetLastError(WSANOTINITIALISED);
247     return SOCKET_ERROR;
248   }
249
250   if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
251     WSASetLastError(WSAENOTSOCK);
252     return SOCKET_ERROR;
253   }
254
255   CloseProviderHandle((HANDLE)s);
256
257   DereferenceProviderByPointer(Provider);
258
259   Status = Provider->ProcTable.lpWSPCloseSocket(s, &Errno);
260   if (Status == SOCKET_ERROR)
261     WSASetLastError(Errno);
262
263   return 0;
264 }
265
266
267 INT
268 EXPORT
269 select(
270     IN      INT nfds, 
271     IN OUT  LPFD_SET readfds, 
272     IN OUT  LPFD_SET writefds, 
273     IN OUT  LPFD_SET exceptfds, 
274     IN      CONST LPTIMEVAL timeout)
275 /*
276  * FUNCTION: Returns status of one or more sockets
277  * ARGUMENTS:
278  *     nfds      = Always ignored
279  *     readfds   = Pointer to socket set to be checked for readability (optional)
280  *     writefds  = Pointer to socket set to be checked for writability (optional)
281  *     exceptfds = Pointer to socket set to be checked for errors (optional)
282  *     timeout   = Pointer to a TIMEVAL structure indicating maximum wait time
283  *                 (NULL means wait forever)
284  * RETURNS:
285  *     Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred
286  */
287 {
288   PCATALOG_ENTRY Provider;
289   INT Count;
290   INT Errno;
291   ULONG i;
292
293   WS_DbgPrint(MAX_TRACE, ("readfds (0x%X)  writefds (0x%X)  exceptfds (0x%X).\n",
294     readfds, writefds, exceptfds));
295
296   if (!WSAINITIALIZED) {
297     WSASetLastError(WSANOTINITIALISED);
298     return SOCKET_ERROR;
299   }
300
301   /* FIXME: Sockets in FD_SETs should be sorted by their provider */
302
303   /* FIXME: For now, assume only one service provider */
304   if ((readfds != NULL) && (readfds->fd_count > 0)) {
305     if (!ReferenceProviderByHandle((HANDLE)readfds->fd_array[0], &Provider)) {
306       WSASetLastError(WSAENOTSOCK);
307       return SOCKET_ERROR;
308     }
309   } else if ((writefds != NULL) && (writefds->fd_count > 0)) {
310     if (!ReferenceProviderByHandle((HANDLE)writefds->fd_array[0], &Provider)) {
311       WSASetLastError(WSAENOTSOCK);
312       return SOCKET_ERROR;
313     }
314   } else if ((exceptfds != NULL) && (exceptfds->fd_count > 0)) {
315     if (!ReferenceProviderByHandle((HANDLE)exceptfds->fd_array[0], &Provider)) {
316       WSASetLastError(WSAENOTSOCK);
317       return SOCKET_ERROR;
318     }
319   } else {
320     WSASetLastError(WSAEINVAL);
321     return SOCKET_ERROR;
322   }
323
324   Count = Provider->ProcTable.lpWSPSelect(
325     nfds, readfds, writefds, exceptfds, timeout, &Errno);
326
327   WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider));
328
329   DereferenceProviderByPointer(Provider);
330
331   if (Errno != NO_ERROR) {
332     WSASetLastError(Errno);
333     return SOCKET_ERROR;
334   }
335
336   return Count;
337 }
338
339
340 INT
341 EXPORT
342 bind(
343   IN  SOCKET s,
344   IN  CONST LPSOCKADDR name,
345   IN  INT namelen)
346 {
347   PCATALOG_ENTRY Provider;
348   INT Status;
349   INT Errno;
350
351   if (!WSAINITIALIZED) {
352     WSASetLastError(WSANOTINITIALISED);
353     return SOCKET_ERROR;
354   }
355
356   if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
357     WSASetLastError(WSAENOTSOCK);
358     return SOCKET_ERROR;
359   }
360
361   Status = Provider->ProcTable.lpWSPBind(
362     s, name, namelen, &Errno);
363
364   DereferenceProviderByPointer(Provider);
365
366   if (Status == SOCKET_ERROR) {
367     WSASetLastError(Errno);
368   }
369
370   return Status;
371 }
372
373
374 INT
375 EXPORT
376 listen(
377     IN  SOCKET s,
378     IN  INT backlog)
379 {
380   PCATALOG_ENTRY Provider;
381   INT Status;
382   INT Errno;
383
384   if (!WSAINITIALIZED) {
385     WSASetLastError(WSANOTINITIALISED);
386     return SOCKET_ERROR;
387   }
388
389   if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
390     WSASetLastError(WSAENOTSOCK);
391     return SOCKET_ERROR;
392   }
393
394   Status = Provider->ProcTable.lpWSPListen(
395     s, backlog, &Errno);
396
397   DereferenceProviderByPointer(Provider);
398
399   if (Status == SOCKET_ERROR) {
400     WSASetLastError(Errno);
401   }
402
403   return Status;
404 }
405
406
407 SOCKET
408 EXPORT
409 accept(
410   IN  SOCKET s,
411   OUT LPSOCKADDR addr,
412   OUT INT FAR* addrlen)
413 {
414   return WSAAccept(s, addr, addrlen, NULL, 0);
415 }
416
417
418 SOCKET
419 EXPORT
420 WSAAccept(
421   IN      SOCKET s,
422   OUT     LPSOCKADDR addr,
423   IN OUT  LPINT addrlen,
424   IN      LPCONDITIONPROC lpfnCondition,
425   IN      DWORD dwCallbackData)
426 {
427   PCATALOG_ENTRY Provider;
428   SOCKET Socket;
429   INT Errno;
430
431   if (!WSAINITIALIZED) {
432     WSASetLastError(WSANOTINITIALISED);
433     return SOCKET_ERROR;
434   }
435
436   if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
437     WSASetLastError(WSAENOTSOCK);
438     return SOCKET_ERROR;
439   }
440
441   Socket = Provider->ProcTable.lpWSPAccept(
442     s, addr, addrlen, lpfnCondition, dwCallbackData, &Errno);
443
444   DereferenceProviderByPointer(Provider);
445
446   if (Socket == INVALID_SOCKET) {
447     WSASetLastError(Errno);
448   }
449
450   return Socket;
451 }
452
453
454 INT
455 EXPORT
456 connect(
457   IN  SOCKET s,
458   IN  CONST LPSOCKADDR name,
459   IN  INT namelen)
460 {
461   return WSAConnect(s, name, namelen, NULL, NULL, NULL, NULL);
462 }
463
464
465 INT
466 EXPORT
467 WSAConnect(
468   IN  SOCKET s,
469   IN  CONST LPSOCKADDR name,
470   IN  INT namelen,
471   IN  LPWSABUF lpCallerData,
472   OUT LPWSABUF lpCalleeData,
473   IN  LPQOS lpSQOS,
474   IN  LPQOS lpGQOS)
475 {
476   PCATALOG_ENTRY Provider;
477   INT Status;
478   INT Errno;
479
480   if (!WSAINITIALIZED) {
481     WSASetLastError(WSANOTINITIALISED);
482     return SOCKET_ERROR;
483   }
484
485   if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
486     WSASetLastError(WSAENOTSOCK);
487     return SOCKET_ERROR;
488   }
489
490   Status = Provider->ProcTable.lpWSPConnect(
491     s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, &Errno);
492
493   DereferenceProviderByPointer(Provider);
494
495   if (Status == SOCKET_ERROR) {
496     WSASetLastError(Errno);
497   }
498
499   return Status;
500 }
501
502
503 BOOL
504 STDCALL
505 DllMain(HANDLE hInstDll,
506         ULONG dwReason,
507         LPVOID lpReserved)
508 {
509   PWINSOCK_THREAD_BLOCK p;
510
511   WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll.\n"));
512
513   switch (dwReason) {
514   case DLL_PROCESS_ATTACH:
515     GlobalHeap = GetProcessHeap();
516
517     CreateCatalog();
518
519     InitProviderHandleTable();
520
521     UpcallTable.lpWPUCloseEvent         = WPUCloseEvent;
522     UpcallTable.lpWPUCloseSocketHandle  = WPUCloseSocketHandle;
523     UpcallTable.lpWPUCreateEvent        = WPUCreateEvent;
524     UpcallTable.lpWPUCreateSocketHandle = WPUCreateSocketHandle;
525     UpcallTable.lpWPUFDIsSet            = WPUFDIsSet;
526     UpcallTable.lpWPUGetProviderPath    = WPUGetProviderPath;
527     UpcallTable.lpWPUModifyIFSHandle    = WPUModifyIFSHandle;
528     UpcallTable.lpWPUPostMessage        = WPUPostMessage;
529     UpcallTable.lpWPUQueryBlockingCallback    = WPUQueryBlockingCallback;
530     UpcallTable.lpWPUQuerySocketHandleContext = WPUQuerySocketHandleContext;
531     UpcallTable.lpWPUQueueApc           = WPUQueueApc;
532     UpcallTable.lpWPUResetEvent         = WPUResetEvent;
533     UpcallTable.lpWPUSetEvent           = WPUSetEvent;
534     UpcallTable.lpWPUOpenCurrentThread  = WPUOpenCurrentThread;
535     UpcallTable.lpWPUCloseThread        = WPUCloseThread;
536
537     /* Fall through to thread attachment handler */
538
539   case DLL_THREAD_ATTACH:
540     p = HeapAlloc(GlobalHeap, 0, sizeof(WINSOCK_THREAD_BLOCK));
541
542     WS_DbgPrint(MAX_TRACE, ("Thread block at 0x%X.\n", p));
543         
544     if (!p) {
545       return FALSE;
546     }
547
548     p->LastErrorValue = NO_ERROR;
549     p->Initialized    = FALSE;
550
551     NtCurrentTeb()->WinSockData = p;
552     break;
553
554   case DLL_PROCESS_DETACH:
555     p = NtCurrentTeb()->WinSockData;
556
557     if (p)
558       HeapFree(GlobalHeap, 0, p);
559
560     DestroyCatalog();
561
562     FreeProviderHandleTable();
563     break;
564
565   case DLL_THREAD_DETACH:
566     p = NtCurrentTeb()->WinSockData;
567
568     if (p)
569       HeapFree(GlobalHeap, 0, p);
570     break;
571   }
572
573   WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll. Leaving.\n"));
574
575   return TRUE;
576 }
577
578 /* EOF */