update for HEAD-2003021201
[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
292   WS_DbgPrint(MAX_TRACE, ("readfds (0x%X)  writefds (0x%X)  exceptfds (0x%X).\n",
293     readfds, writefds, exceptfds));
294
295   if (!WSAINITIALIZED) {
296     WSASetLastError(WSANOTINITIALISED);
297     return SOCKET_ERROR;
298   }
299
300   /* FIXME: Sockets in FD_SETs should be sorted by their provider */
301
302   /* FIXME: For now, assume only one service provider */
303   if ((readfds != NULL) && (readfds->fd_count > 0)) {
304     if (!ReferenceProviderByHandle((HANDLE)readfds->fd_array[0], &Provider)) {
305       WSASetLastError(WSAENOTSOCK);
306       return SOCKET_ERROR;
307     }
308   } else if ((writefds != NULL) && (writefds->fd_count > 0)) {
309     if (!ReferenceProviderByHandle((HANDLE)writefds->fd_array[0], &Provider)) {
310       WSASetLastError(WSAENOTSOCK);
311       return SOCKET_ERROR;
312     }
313   } else if ((exceptfds != NULL) && (exceptfds->fd_count > 0)) {
314     if (!ReferenceProviderByHandle((HANDLE)exceptfds->fd_array[0], &Provider)) {
315       WSASetLastError(WSAENOTSOCK);
316       return SOCKET_ERROR;
317     }
318   } else {
319     WSASetLastError(WSAEINVAL);
320     return SOCKET_ERROR;
321   }
322
323   Count = Provider->ProcTable.lpWSPSelect(
324     nfds, readfds, writefds, exceptfds, timeout, &Errno);
325
326   WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider));
327
328   DereferenceProviderByPointer(Provider);
329
330   if (Errno != NO_ERROR) {
331     WSASetLastError(Errno);
332     return SOCKET_ERROR;
333   }
334
335   return Count;
336 }
337
338
339 INT
340 EXPORT
341 bind(
342   IN  SOCKET s,
343   IN  CONST LPSOCKADDR name,
344   IN  INT namelen)
345 {
346   PCATALOG_ENTRY Provider;
347   INT Status;
348   INT Errno;
349
350   if (!WSAINITIALIZED) {
351     WSASetLastError(WSANOTINITIALISED);
352     return SOCKET_ERROR;
353   }
354
355   if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
356     WSASetLastError(WSAENOTSOCK);
357     return SOCKET_ERROR;
358   }
359
360   Status = Provider->ProcTable.lpWSPBind(
361     s, name, namelen, &Errno);
362
363   DereferenceProviderByPointer(Provider);
364
365   if (Status == SOCKET_ERROR) {
366     WSASetLastError(Errno);
367   }
368
369   return Status;
370 }
371
372
373 INT
374 EXPORT
375 listen(
376     IN  SOCKET s,
377     IN  INT backlog)
378 {
379   PCATALOG_ENTRY Provider;
380   INT Status;
381   INT Errno;
382
383   if (!WSAINITIALIZED) {
384     WSASetLastError(WSANOTINITIALISED);
385     return SOCKET_ERROR;
386   }
387
388   if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
389     WSASetLastError(WSAENOTSOCK);
390     return SOCKET_ERROR;
391   }
392
393   Status = Provider->ProcTable.lpWSPListen(
394     s, backlog, &Errno);
395
396   DereferenceProviderByPointer(Provider);
397
398   if (Status == SOCKET_ERROR) {
399     WSASetLastError(Errno);
400   }
401
402   return Status;
403 }
404
405
406 SOCKET
407 EXPORT
408 accept(
409   IN  SOCKET s,
410   OUT LPSOCKADDR addr,
411   OUT INT FAR* addrlen)
412 {
413   return WSAAccept(s, addr, addrlen, NULL, 0);
414 }
415
416
417 SOCKET
418 EXPORT
419 WSAAccept(
420   IN      SOCKET s,
421   OUT     LPSOCKADDR addr,
422   IN OUT  LPINT addrlen,
423   IN      LPCONDITIONPROC lpfnCondition,
424   IN      DWORD dwCallbackData)
425 {
426   PCATALOG_ENTRY Provider;
427   SOCKET Socket;
428   INT Errno;
429
430   if (!WSAINITIALIZED) {
431     WSASetLastError(WSANOTINITIALISED);
432     return SOCKET_ERROR;
433   }
434
435   if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
436     WSASetLastError(WSAENOTSOCK);
437     return SOCKET_ERROR;
438   }
439
440   Socket = Provider->ProcTable.lpWSPAccept(
441     s, addr, addrlen, lpfnCondition, dwCallbackData, &Errno);
442
443   DereferenceProviderByPointer(Provider);
444
445   if (Socket == INVALID_SOCKET) {
446     WSASetLastError(Errno);
447   }
448
449   return Socket;
450 }
451
452
453 INT
454 EXPORT
455 connect(
456   IN  SOCKET s,
457   IN  CONST LPSOCKADDR name,
458   IN  INT namelen)
459 {
460   return WSAConnect(s, name, namelen, NULL, NULL, NULL, NULL);
461 }
462
463
464 INT
465 EXPORT
466 WSAConnect(
467   IN  SOCKET s,
468   IN  CONST LPSOCKADDR name,
469   IN  INT namelen,
470   IN  LPWSABUF lpCallerData,
471   OUT LPWSABUF lpCalleeData,
472   IN  LPQOS lpSQOS,
473   IN  LPQOS lpGQOS)
474 {
475   PCATALOG_ENTRY Provider;
476   INT Status;
477   INT Errno;
478
479   if (!WSAINITIALIZED) {
480     WSASetLastError(WSANOTINITIALISED);
481     return SOCKET_ERROR;
482   }
483
484   if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
485     WSASetLastError(WSAENOTSOCK);
486     return SOCKET_ERROR;
487   }
488
489   Status = Provider->ProcTable.lpWSPConnect(
490     s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, &Errno);
491
492   DereferenceProviderByPointer(Provider);
493
494   if (Status == SOCKET_ERROR) {
495     WSASetLastError(Errno);
496   }
497
498   return Status;
499 }
500
501
502 BOOL
503 STDCALL
504 DllMain(HANDLE hInstDll,
505         ULONG dwReason,
506         LPVOID lpReserved)
507 {
508   PWINSOCK_THREAD_BLOCK p;
509
510   WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll.\n"));
511
512   switch (dwReason) {
513   case DLL_PROCESS_ATTACH:
514     GlobalHeap = GetProcessHeap();
515
516     CreateCatalog();
517
518     InitProviderHandleTable();
519
520     UpcallTable.lpWPUCloseEvent         = WPUCloseEvent;
521     UpcallTable.lpWPUCloseSocketHandle  = WPUCloseSocketHandle;
522     UpcallTable.lpWPUCreateEvent        = WPUCreateEvent;
523     UpcallTable.lpWPUCreateSocketHandle = WPUCreateSocketHandle;
524     UpcallTable.lpWPUFDIsSet            = WPUFDIsSet;
525     UpcallTable.lpWPUGetProviderPath    = WPUGetProviderPath;
526     UpcallTable.lpWPUModifyIFSHandle    = WPUModifyIFSHandle;
527     UpcallTable.lpWPUPostMessage        = WPUPostMessage;
528     UpcallTable.lpWPUQueryBlockingCallback    = WPUQueryBlockingCallback;
529     UpcallTable.lpWPUQuerySocketHandleContext = WPUQuerySocketHandleContext;
530     UpcallTable.lpWPUQueueApc           = WPUQueueApc;
531     UpcallTable.lpWPUResetEvent         = WPUResetEvent;
532     UpcallTable.lpWPUSetEvent           = WPUSetEvent;
533     UpcallTable.lpWPUOpenCurrentThread  = WPUOpenCurrentThread;
534     UpcallTable.lpWPUCloseThread        = WPUCloseThread;
535
536     /* Fall through to thread attachment handler */
537
538   case DLL_THREAD_ATTACH:
539     p = HeapAlloc(GlobalHeap, 0, sizeof(WINSOCK_THREAD_BLOCK));
540
541     WS_DbgPrint(MAX_TRACE, ("Thread block at 0x%X.\n", p));
542         
543     if (!p) {
544       return FALSE;
545     }
546
547     p->LastErrorValue = NO_ERROR;
548     p->Initialized    = FALSE;
549
550     NtCurrentTeb()->WinSockData = p;
551     break;
552
553   case DLL_PROCESS_DETACH:
554     p = NtCurrentTeb()->WinSockData;
555
556     if (p)
557       HeapFree(GlobalHeap, 0, p);
558
559     DestroyCatalog();
560
561     FreeProviderHandleTable();
562     break;
563
564   case DLL_THREAD_DETACH:
565     p = NtCurrentTeb()->WinSockData;
566
567     if (p)
568       HeapFree(GlobalHeap, 0, p);
569     break;
570   }
571
572   WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll. Leaving.\n"));
573
574   return TRUE;
575 }
576
577 /* EOF */