Sync with trunk (r48545)
[reactos.git] / dll / win32 / 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
11 #include <w32api.h>
12 #include <ws2_32.h>
13 #include <catalog.h>
14 #include <handle.h>
15 #include <upcall.h>
16
17 #if DBG
18
19 /* See debug.h for debug/trace constants */
20 //DWORD DebugTraceLevel = MIN_TRACE;
21 //DWORD DebugTraceLevel = MAX_TRACE;
22 //DWORD DebugTraceLevel = DEBUG_ULTRA;
23 DWORD DebugTraceLevel = 0;
24 #endif /* DBG */
25
26 /* To make the linker happy */
27 VOID WINAPI KeBugCheck (ULONG BugCheckCode) {}
28
29 HINSTANCE g_hInstDll;
30 HANDLE GlobalHeap;
31 BOOL WsaInitialized = FALSE; /* TRUE if WSAStartup() has been successfully called */
32 WSPUPCALLTABLE UpcallTable;
33
34
35 /*
36 * @implemented
37 */
38 INT
39 EXPORT
40 WSAGetLastError(VOID)
41 {
42 return GetLastError();
43 }
44
45
46 /*
47 * @implemented
48 */
49 VOID
50 EXPORT
51 WSASetLastError(IN INT iError)
52 {
53 SetLastError(iError);
54 }
55
56
57 /*
58 * @implemented
59 */
60 INT
61 EXPORT
62 WSAStartup(IN WORD wVersionRequested,
63 OUT LPWSADATA lpWSAData)
64 {
65 BYTE Low, High;
66
67 WS_DbgPrint(MAX_TRACE, ("WSAStartup of ws2_32.dll\n"));
68
69 if (!g_hInstDll)
70 return WSASYSNOTREADY;
71
72 if (lpWSAData == NULL)
73 return WSAEFAULT;
74
75 Low = LOBYTE(wVersionRequested);
76 High = HIBYTE(wVersionRequested);
77
78 if (Low < 1)
79 {
80 WS_DbgPrint(MAX_TRACE, ("Bad winsock version requested, %d,%d", Low, High));
81 return WSAVERNOTSUPPORTED;
82 }
83
84 if (Low == 1)
85 {
86 if (High == 0)
87 {
88 lpWSAData->wVersion = wVersionRequested;
89 }
90 else
91 {
92 lpWSAData->wVersion = MAKEWORD(1, 1);
93 }
94 }
95 else if (Low == 2)
96 {
97 if (High <= 2)
98 {
99 lpWSAData->wVersion = MAKEWORD(2, High);
100 }
101 else
102 {
103 lpWSAData->wVersion = MAKEWORD(2, 2);
104 }
105 }
106 else
107 {
108 lpWSAData->wVersion = MAKEWORD(2, 2);
109 }
110
111 lpWSAData->wVersion = wVersionRequested;
112 lpWSAData->wHighVersion = MAKEWORD(2,2);
113 lstrcpyA(lpWSAData->szDescription, "WinSock 2.2");
114 lstrcpyA(lpWSAData->szSystemStatus, "Running");
115 lpWSAData->iMaxSockets = 0;
116 lpWSAData->iMaxUdpDg = 0;
117 lpWSAData->lpVendorInfo = NULL;
118
119 /*FIXME: increment internal counter */
120
121 WSASETINITIALIZED;
122
123 return NO_ERROR;
124 }
125
126
127 /*
128 * @implemented
129 */
130 INT
131 EXPORT
132 WSACleanup(VOID)
133 {
134 WS_DbgPrint(MAX_TRACE, ("WSACleanup of ws2_32.dll\n"));
135
136 if (!WSAINITIALIZED)
137 {
138 WSASetLastError(WSANOTINITIALISED);
139 return WSANOTINITIALISED;
140 }
141
142 return NO_ERROR;
143 }
144
145
146 /*
147 * @implemented
148 */
149 SOCKET
150 EXPORT
151 socket(IN INT af,
152 IN INT type,
153 IN INT protocol)
154 {
155 return WSASocketW(af,
156 type,
157 protocol,
158 NULL,
159 0,
160 0);
161 }
162
163
164 /*
165 * @implemented
166 */
167 SOCKET
168 EXPORT
169 WSASocketA(IN INT af,
170 IN INT type,
171 IN INT protocol,
172 IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
173 IN GROUP g,
174 IN DWORD dwFlags)
175 /*
176 * FUNCTION: Creates a new socket
177 */
178 {
179 WSAPROTOCOL_INFOW ProtocolInfoW;
180 LPWSAPROTOCOL_INFOW p;
181 UNICODE_STRING StringU;
182 ANSI_STRING StringA;
183
184 WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n",
185 af, type, protocol));
186
187 if (lpProtocolInfo)
188 {
189 memcpy(&ProtocolInfoW,
190 lpProtocolInfo,
191 sizeof(WSAPROTOCOL_INFOA) - sizeof(CHAR) * (WSAPROTOCOL_LEN + 1));
192 RtlInitAnsiString(&StringA, (LPSTR)lpProtocolInfo->szProtocol);
193 RtlInitUnicodeString(&StringU, (LPWSTR)&ProtocolInfoW.szProtocol);
194 RtlAnsiStringToUnicodeString(&StringU, &StringA, FALSE);
195 p = &ProtocolInfoW;
196 }
197 else
198 {
199 p = NULL;
200 }
201
202 return WSASocketW(af,
203 type,
204 protocol,
205 p,
206 g,
207 dwFlags);
208 }
209
210
211 /*
212 * @implemented
213 */
214 SOCKET
215 EXPORT
216 WSASocketW(IN INT af,
217 IN INT type,
218 IN INT protocol,
219 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
220 IN GROUP g,
221 IN DWORD dwFlags)
222 /*
223 * FUNCTION: Creates a new socket descriptor
224 * ARGUMENTS:
225 * af = Address family
226 * type = Socket type
227 * protocol = Protocol type
228 * lpProtocolInfo = Pointer to protocol information
229 * g = Reserved
230 * dwFlags = Socket flags
231 * RETURNS:
232 * Created socket descriptor, or INVALID_SOCKET if it could not be created
233 */
234 {
235 INT Status;
236 SOCKET Socket;
237 PCATALOG_ENTRY Provider;
238 WSAPROTOCOL_INFOW ProtocolInfo;
239
240 WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n",
241 af, type, protocol));
242
243 if (!WSAINITIALIZED)
244 {
245 WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d) = WSANOTINITIALISED.\n",
246 af, type, protocol));
247 WSASetLastError(WSANOTINITIALISED);
248 return INVALID_SOCKET;
249 }
250
251 if (!lpProtocolInfo)
252 {
253 lpProtocolInfo = &ProtocolInfo;
254 ZeroMemory(&ProtocolInfo, sizeof(WSAPROTOCOL_INFOW));
255
256 ProtocolInfo.iAddressFamily = af;
257 ProtocolInfo.iSocketType = type;
258 ProtocolInfo.iProtocol = protocol;
259 }
260
261 Provider = LocateProvider(lpProtocolInfo);
262 if (!Provider)
263 {
264 WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d) = WSAEAFNOSUPPORT.\n",
265 af, type, protocol));
266 WSASetLastError(WSAEAFNOSUPPORT);
267 return INVALID_SOCKET;
268 }
269
270 Status = LoadProvider(Provider, lpProtocolInfo);
271 if (Status != NO_ERROR)
272 {
273 WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d) = %d.\n",
274 af, type, protocol, Status));
275 WSASetLastError(Status);
276 return INVALID_SOCKET;
277 }
278
279 WS_DbgPrint(MAX_TRACE, ("Calling WSPSocket at (0x%X).\n",
280 Provider->ProcTable.lpWSPSocket));
281
282 assert(Provider->ProcTable.lpWSPSocket);
283
284 WS_DbgPrint(MAX_TRACE,("About to call provider socket fn\n"));
285
286 Socket = Provider->ProcTable.lpWSPSocket(af,
287 type,
288 protocol,
289 lpProtocolInfo,
290 g,
291 dwFlags,
292 &Status);
293
294 WS_DbgPrint(MAX_TRACE,("Socket: %x, Status: %x\n", Socket, Status));
295
296 if (Status != NO_ERROR)
297 {
298 WSASetLastError(Status);
299 return INVALID_SOCKET;
300 }
301
302 WS_DbgPrint(MAX_TRACE,("Status: %x\n", Status));
303
304 return Socket;
305 }
306
307
308 /*
309 * @implemented
310 */
311 INT
312 EXPORT
313 closesocket(IN SOCKET s)
314 /*
315 * FUNCTION: Closes a socket descriptor
316 * ARGUMENTS:
317 * s = Socket descriptor
318 * RETURNS:
319 * 0, or SOCKET_ERROR if an error ocurred
320 */
321 {
322 PCATALOG_ENTRY Provider;
323 INT Status;
324 INT Errno;
325
326 WS_DbgPrint(MAX_TRACE, ("s (0x%X).\n", s));
327
328 if (!WSAINITIALIZED)
329 {
330 WSASetLastError(WSANOTINITIALISED);
331 return SOCKET_ERROR;
332 }
333
334 if (!ReferenceProviderByHandle((HANDLE)s, &Provider))
335 {
336 WSASetLastError(WSAENOTSOCK);
337 return SOCKET_ERROR;
338 }
339
340 CloseProviderHandle((HANDLE)s);
341
342 WS_DbgPrint(MAX_TRACE,("DereferenceProviderByHandle\n"));
343
344 DereferenceProviderByPointer(Provider);
345
346 WS_DbgPrint(MAX_TRACE,("DereferenceProviderByHandle Done\n"));
347
348 Status = Provider->ProcTable.lpWSPCloseSocket(s, &Errno);
349
350 WS_DbgPrint(MAX_TRACE,("Provider Close Done\n"));
351
352 if (Status == SOCKET_ERROR)
353 WSASetLastError(Errno);
354
355 WS_DbgPrint(MAX_TRACE,("Returning success\n"));
356
357 return 0;
358 }
359
360
361 /*
362 * @implemented
363 */
364 INT
365 EXPORT
366 select(IN INT nfds,
367 IN OUT LPFD_SET readfds,
368 IN OUT LPFD_SET writefds,
369 IN OUT LPFD_SET exceptfds,
370 IN CONST struct timeval *timeout)
371 /*
372 * FUNCTION: Returns status of one or more sockets
373 * ARGUMENTS:
374 * nfds = Always ignored
375 * readfds = Pointer to socket set to be checked for readability (optional)
376 * writefds = Pointer to socket set to be checked for writability (optional)
377 * exceptfds = Pointer to socket set to be checked for errors (optional)
378 * timeout = Pointer to a TIMEVAL structure indicating maximum wait time
379 * (NULL means wait forever)
380 * RETURNS:
381 * Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred
382 */
383 {
384 PCATALOG_ENTRY Provider = NULL;
385 INT Count;
386 INT Errno;
387
388 WS_DbgPrint(MAX_TRACE, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n",
389 readfds, writefds, exceptfds));
390
391 if (!WSAINITIALIZED)
392 {
393 WSASetLastError(WSANOTINITIALISED);
394 WS_DbgPrint(MID_TRACE,("Not initialized\n"));
395 return SOCKET_ERROR;
396 }
397
398 /* FIXME: Sockets in FD_SETs should be sorted by their provider */
399
400 /* FIXME: For now, assume only one service provider */
401 if ((readfds != NULL) && (readfds->fd_count > 0))
402 {
403 if (!ReferenceProviderByHandle((HANDLE)readfds->fd_array[0],
404 &Provider))
405 {
406 WSASetLastError(WSAENOTSOCK);
407 WS_DbgPrint(MID_TRACE,("No provider (read)\n"));
408 return SOCKET_ERROR;
409 }
410 }
411 else if ((writefds != NULL) && (writefds->fd_count > 0))
412 {
413 if (!ReferenceProviderByHandle((HANDLE)writefds->fd_array[0],
414 &Provider))
415 {
416 WSASetLastError(WSAENOTSOCK);
417 WS_DbgPrint(MID_TRACE,("No provider (write)\n"));
418 return SOCKET_ERROR;
419 }
420 }
421 else if ((exceptfds != NULL) && (exceptfds->fd_count > 0))
422 {
423 if (!ReferenceProviderByHandle((HANDLE)exceptfds->fd_array[0], &Provider))
424 {
425 WSASetLastError(WSAENOTSOCK);
426 WS_DbgPrint(MID_TRACE,("No provider (err)\n"));
427 return SOCKET_ERROR;
428 }
429 #if 0 /* XXX empty select is not an error */
430 }
431 else
432 {
433 WSASetLastError(WSAEINVAL);
434 return SOCKET_ERROR;
435 #endif
436 }
437
438 if ( !Provider )
439 {
440 if ( timeout )
441 {
442 WS_DbgPrint(MID_TRACE,("Select: used as timer\n"));
443 Sleep( timeout->tv_sec * 1000 + (timeout->tv_usec / 1000) );
444 }
445 return 0;
446 }
447 else if (Provider->ProcTable.lpWSPSelect)
448 {
449 WS_DbgPrint(MID_TRACE,("Calling WSPSelect:%x\n", Provider->ProcTable.lpWSPSelect));
450 Count = Provider->ProcTable.lpWSPSelect(nfds,
451 readfds,
452 writefds,
453 exceptfds,
454 (LPTIMEVAL)timeout,
455 &Errno);
456
457 WS_DbgPrint(MAX_TRACE, ("[%x] Select: Count %d Errno %x\n",
458 Provider, Count, Errno));
459
460 DereferenceProviderByPointer(Provider);
461
462 if (Count == SOCKET_ERROR)
463 {
464 WSASetLastError(Errno);
465 return SOCKET_ERROR;
466 }
467 }
468 else
469 {
470 WSASetLastError(WSAEINVAL);
471 return SOCKET_ERROR;
472 }
473
474 return Count;
475 }
476
477
478 /*
479 * @implemented
480 */
481 INT
482 EXPORT
483 bind(IN SOCKET s,
484 IN CONST struct sockaddr *name,
485 IN INT namelen)
486 {
487 PCATALOG_ENTRY Provider;
488 INT Status;
489 INT Errno;
490
491 if (!WSAINITIALIZED)
492 {
493 WSASetLastError(WSANOTINITIALISED);
494 return SOCKET_ERROR;
495 }
496
497 if (!ReferenceProviderByHandle((HANDLE)s,
498 &Provider))
499 {
500 WSASetLastError(WSAENOTSOCK);
501 return SOCKET_ERROR;
502 }
503
504 #if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
505 Status = Provider->ProcTable.lpWSPBind(s,
506 (CONST LPSOCKADDR)name,
507 namelen,
508 &Errno);
509 #else
510 Status = Provider->ProcTable.lpWSPBind(s,
511 name,
512 namelen,
513 &Errno);
514 #endif /* __W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5 */
515
516 DereferenceProviderByPointer(Provider);
517
518 if (Status == SOCKET_ERROR)
519 WSASetLastError(Errno);
520
521 return Status;
522 }
523
524
525 /*
526 * @implemented
527 */
528 INT
529 EXPORT
530 listen(IN SOCKET s,
531 IN INT backlog)
532 {
533 PCATALOG_ENTRY Provider;
534 INT Status;
535 INT Errno;
536
537 if (!WSAINITIALIZED)
538 {
539 WSASetLastError(WSANOTINITIALISED);
540 return SOCKET_ERROR;
541 }
542
543 if (!ReferenceProviderByHandle((HANDLE)s,
544 &Provider))
545 {
546 WSASetLastError(WSAENOTSOCK);
547 return SOCKET_ERROR;
548 }
549
550 Status = Provider->ProcTable.lpWSPListen(s,
551 backlog,
552 &Errno);
553
554 DereferenceProviderByPointer(Provider);
555
556 if (Status == SOCKET_ERROR)
557 WSASetLastError(Errno);
558
559 return Status;
560 }
561
562
563 /*
564 * @implemented
565 */
566 SOCKET
567 EXPORT
568 accept(IN SOCKET s,
569 OUT LPSOCKADDR addr,
570 OUT INT FAR* addrlen)
571 {
572 return WSAAccept(s,
573 addr,
574 addrlen,
575 NULL,
576 0);
577 }
578
579
580 /*
581 * @implemented
582 */
583 INT
584 EXPORT
585 ioctlsocket(IN SOCKET s,
586 IN LONG cmd,
587 IN OUT ULONG FAR* argp)
588 {
589 ULONG tmp;
590
591 return WSAIoctl(s,
592 cmd,
593 argp,
594 sizeof(ULONG),
595 argp,
596 sizeof(ULONG),
597 &tmp,
598 0,
599 0);
600 }
601
602
603 /*
604 * @implemented
605 */
606 SOCKET
607 EXPORT
608 WSAAccept(IN SOCKET s,
609 OUT LPSOCKADDR addr,
610 IN OUT LPINT addrlen,
611 IN LPCONDITIONPROC lpfnCondition,
612 IN DWORD_PTR dwCallbackData)
613 {
614 PCATALOG_ENTRY Provider;
615 SOCKET Socket;
616 INT Errno;
617
618 if (!WSAINITIALIZED)
619 {
620 WSASetLastError(WSANOTINITIALISED);
621 return SOCKET_ERROR;
622 }
623
624 if (!ReferenceProviderByHandle((HANDLE)s, &Provider))
625 {
626 WSASetLastError(WSAENOTSOCK);
627 return SOCKET_ERROR;
628 }
629
630 WS_DbgPrint(MAX_TRACE,("Calling provider accept\n"));
631
632 Socket = Provider->ProcTable.lpWSPAccept(s,
633 addr,
634 addrlen,
635 lpfnCondition,
636 dwCallbackData,
637 &Errno);
638
639 WS_DbgPrint(MAX_TRACE,("Calling provider accept -> Socket %x, Errno %x\n",
640 Socket, Errno));
641
642 DereferenceProviderByPointer(Provider);
643
644 if (Socket == INVALID_SOCKET)
645 WSASetLastError(Errno);
646
647 if ( addr && addrlen )
648 {
649 #if DBG
650 LPSOCKADDR_IN sa = (LPSOCKADDR_IN)addr;
651 WS_DbgPrint(MAX_TRACE,("Returned address: %d %s:%d (len %d)\n",
652 sa->sin_family,
653 inet_ntoa(sa->sin_addr),
654 ntohs(sa->sin_port),
655 *addrlen));
656 #endif
657 }
658
659 return Socket;
660 }
661
662
663 /*
664 * @implemented
665 */
666 INT
667 EXPORT
668 connect(IN SOCKET s,
669 IN CONST struct sockaddr *name,
670 IN INT namelen)
671 {
672 return WSAConnect(s,
673 name,
674 namelen,
675 NULL,
676 NULL,
677 NULL,
678 NULL);
679 }
680
681
682 /*
683 * @implemented
684 */
685 INT
686 EXPORT
687 WSAConnect(IN SOCKET s,
688 IN CONST struct sockaddr *name,
689 IN INT namelen,
690 IN LPWSABUF lpCallerData,
691 OUT LPWSABUF lpCalleeData,
692 IN LPQOS lpSQOS,
693 IN LPQOS lpGQOS)
694 {
695 PCATALOG_ENTRY Provider;
696 INT Status;
697 INT Errno;
698
699 if (!WSAINITIALIZED)
700 {
701 WSASetLastError(WSANOTINITIALISED);
702 return SOCKET_ERROR;
703 }
704
705 if (!ReferenceProviderByHandle((HANDLE)s, &Provider))
706 {
707 WSASetLastError(WSAENOTSOCK);
708 return SOCKET_ERROR;
709 }
710
711 #if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
712 Status = Provider->ProcTable.lpWSPConnect(s,
713 (CONST LPSOCKADDR)name,
714 namelen,
715 lpCallerData,
716 lpCalleeData,
717 lpSQOS,
718 lpGQOS,
719 &Errno);
720 #else
721 Status = Provider->ProcTable.lpWSPConnect(s,
722 name,
723 namelen,
724 lpCallerData,
725 lpCalleeData,
726 lpSQOS,
727 lpGQOS,
728 &Errno);
729 #endif
730
731 DereferenceProviderByPointer(Provider);
732
733 if (Status == SOCKET_ERROR)
734 WSASetLastError(Errno);
735
736 return Status;
737 }
738
739
740 /*
741 * @implemented
742 */
743 INT
744 EXPORT
745 WSAIoctl(IN SOCKET s,
746 IN DWORD dwIoControlCode,
747 IN LPVOID lpvInBuffer,
748 IN DWORD cbInBuffer,
749 OUT LPVOID lpvOutBuffer,
750 IN DWORD cbOutBuffer,
751 OUT LPDWORD lpcbBytesReturned,
752 IN LPWSAOVERLAPPED lpOverlapped,
753 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
754 {
755 PCATALOG_ENTRY Provider;
756 INT Status;
757 INT Errno;
758
759 if (!WSAINITIALIZED)
760 {
761 WSASetLastError(WSANOTINITIALISED);
762 return SOCKET_ERROR;
763 }
764
765 if (!ReferenceProviderByHandle((HANDLE)s, &Provider))
766 {
767 WSASetLastError(WSAENOTSOCK);
768 return SOCKET_ERROR;
769 }
770
771 Status = Provider->ProcTable.lpWSPIoctl(s,
772 dwIoControlCode,
773 lpvInBuffer,
774 cbInBuffer,
775 lpvOutBuffer,
776 cbOutBuffer,
777 lpcbBytesReturned,
778 lpOverlapped,
779 lpCompletionRoutine,
780 NULL /* lpThreadId */,
781 &Errno);
782
783 DereferenceProviderByPointer(Provider);
784
785 if (Status == SOCKET_ERROR)
786 WSASetLastError(Errno);
787
788 return Status;
789 }
790
791 /*
792 * @implemented
793 */
794 INT
795 EXPORT
796 __WSAFDIsSet(SOCKET s, LPFD_SET set)
797 {
798 unsigned int i;
799
800 for ( i = 0; i < set->fd_count; i++ )
801 if ( set->fd_array[i] == s ) return TRUE;
802
803 return FALSE;
804 }
805
806 void free_winsock_thread_block(PWINSOCK_THREAD_BLOCK p)
807 {
808 if (p)
809 {
810 if (p->Hostent) { free_hostent(p->Hostent); p->Hostent = 0; }
811 if (p->Getservbyname){}
812 if (p->Getservbyport) {}
813 }
814 }
815
816 BOOL
817 WINAPI
818 DllMain(HANDLE hInstDll,
819 ULONG dwReason,
820 LPVOID lpReserved)
821 {
822 PWINSOCK_THREAD_BLOCK p;
823
824 WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll.\n"));
825
826 switch (dwReason)
827 {
828 case DLL_PROCESS_ATTACH:
829 {
830 GlobalHeap = GetProcessHeap();
831
832 g_hInstDll = hInstDll;
833
834 CreateCatalog();
835
836 InitProviderHandleTable();
837
838 UpcallTable.lpWPUCloseEvent = WPUCloseEvent;
839 UpcallTable.lpWPUCloseSocketHandle = WPUCloseSocketHandle;
840 UpcallTable.lpWPUCreateEvent = WPUCreateEvent;
841 UpcallTable.lpWPUCreateSocketHandle = WPUCreateSocketHandle;
842 UpcallTable.lpWPUFDIsSet = WPUFDIsSet;
843 UpcallTable.lpWPUGetProviderPath = WPUGetProviderPath;
844 UpcallTable.lpWPUModifyIFSHandle = WPUModifyIFSHandle;
845 UpcallTable.lpWPUPostMessage = PostMessageW;
846 UpcallTable.lpWPUQueryBlockingCallback = WPUQueryBlockingCallback;
847 UpcallTable.lpWPUQuerySocketHandleContext = WPUQuerySocketHandleContext;
848 UpcallTable.lpWPUQueueApc = WPUQueueApc;
849 UpcallTable.lpWPUResetEvent = WPUResetEvent;
850 UpcallTable.lpWPUSetEvent = WPUSetEvent;
851 UpcallTable.lpWPUOpenCurrentThread = WPUOpenCurrentThread;
852 UpcallTable.lpWPUCloseThread = WPUCloseThread;
853
854 /* Fall through to thread attachment handler */
855 }
856 case DLL_THREAD_ATTACH:
857 {
858 p = HeapAlloc(GlobalHeap, 0, sizeof(WINSOCK_THREAD_BLOCK));
859
860 WS_DbgPrint(MAX_TRACE, ("Thread block at 0x%X.\n", p));
861
862 if (!p) {
863 return FALSE;
864 }
865
866 p->Hostent = NULL;
867 p->LastErrorValue = NO_ERROR;
868 p->Getservbyname = NULL;
869 p->Getservbyport = NULL;
870
871 NtCurrentTeb()->WinSockData = p;
872 }
873 break;
874
875 case DLL_PROCESS_DETACH:
876 {
877 DestroyCatalog();
878
879 FreeProviderHandleTable();
880 }
881 break;
882
883 case DLL_THREAD_DETACH:
884 {
885 p = NtCurrentTeb()->WinSockData;
886
887 if (p)
888 HeapFree(GlobalHeap, 0, p);
889 }
890 break;
891 }
892
893 WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll. Leaving.\n"));
894
895 return TRUE;
896 }
897
898 /* EOF */