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