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