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