Wow, WriteConfigurationFile() in rbuild never worked since it was added in r13496...
[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 <w32api.h>
12 #include <ws2_32.h>
13 #include <catalog.h>
14 #include <handle.h>
15 #include <upcall.h>
16
17 #ifdef 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 STDCALL 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 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
43
44 if (p)
45 {
46 return p->LastErrorValue;
47 }
48 else
49 {
50 /* FIXME: What error code should we use here? Can this even happen? */
51 return ERROR_BAD_ENVIRONMENT;
52 }
53 }
54
55
56 /*
57 * @implemented
58 */
59 VOID
60 EXPORT
61 WSASetLastError(IN INT iError)
62 {
63 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
64
65 if (p)
66 p->LastErrorValue = iError;
67 }
68
69
70 /*
71 * @implemented
72 */
73 INT
74 EXPORT
75 WSAStartup(IN WORD wVersionRequested,
76 OUT LPWSADATA lpWSAData)
77 {
78 BYTE Low, High;
79
80 WS_DbgPrint(MAX_TRACE, ("WSAStartup of ws2_32.dll\n"));
81
82 if (!g_hInstDll)
83 return WSASYSNOTREADY;
84
85 if (lpWSAData == NULL)
86 return WSAEFAULT;
87
88 Low = LOBYTE(wVersionRequested);
89 High = HIBYTE(wVersionRequested);
90
91 if (Low < 1)
92 {
93 WS_DbgPrint(MAX_TRACE, ("Bad winsock version requested, %d,%d", Low, High));
94 return WSAVERNOTSUPPORTED;
95 }
96
97 if (Low == 1)
98 {
99 if (High == 0)
100 {
101 lpWSAData->wVersion = wVersionRequested;
102 }
103 else
104 {
105 lpWSAData->wVersion = MAKEWORD(1, 1);
106 }
107 }
108 else if (Low == 2)
109 {
110 if (High <= 2)
111 {
112 lpWSAData->wVersion = MAKEWORD(2, High);
113 }
114 else
115 {
116 lpWSAData->wVersion = MAKEWORD(2, 2);
117 }
118 }
119 else
120 {
121 lpWSAData->wVersion = MAKEWORD(2, 2);
122 }
123
124 lpWSAData->wVersion = wVersionRequested;
125 lpWSAData->wHighVersion = MAKEWORD(2,2);
126 lstrcpyA(lpWSAData->szDescription, "WinSock 2.2");
127 lstrcpyA(lpWSAData->szSystemStatus, "Running");
128 lpWSAData->iMaxSockets = 0;
129 lpWSAData->iMaxUdpDg = 0;
130 lpWSAData->lpVendorInfo = NULL;
131
132 /*FIXME: increment internal counter */
133
134 WSASETINITIALIZED;
135
136 return NO_ERROR;
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 (Errno != NO_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 return WSAIoctl(s,
603 cmd,
604 argp,
605 sizeof(ULONG),
606 argp,
607 sizeof(ULONG),
608 argp,
609 0,
610 0);
611 }
612
613
614 /*
615 * @implemented
616 */
617 SOCKET
618 EXPORT
619 WSAAccept(IN SOCKET s,
620 OUT LPSOCKADDR addr,
621 IN OUT LPINT addrlen,
622 IN LPCONDITIONPROC lpfnCondition,
623 IN DWORD dwCallbackData)
624 {
625 PCATALOG_ENTRY Provider;
626 SOCKET Socket;
627 INT Errno;
628
629 if (!WSAINITIALIZED)
630 {
631 WSASetLastError(WSANOTINITIALISED);
632 return SOCKET_ERROR;
633 }
634
635 if (!ReferenceProviderByHandle((HANDLE)s, &Provider))
636 {
637 WSASetLastError(WSAENOTSOCK);
638 return SOCKET_ERROR;
639 }
640
641 WS_DbgPrint(MAX_TRACE,("Calling provider accept\n"));
642
643 Socket = Provider->ProcTable.lpWSPAccept(s,
644 addr,
645 addrlen,
646 lpfnCondition,
647 dwCallbackData,
648 &Errno);
649
650 WS_DbgPrint(MAX_TRACE,("Calling provider accept -> Socket %x, Errno %x\n",
651 Socket, Errno));
652
653 DereferenceProviderByPointer(Provider);
654
655 if (Socket == INVALID_SOCKET)
656 WSASetLastError(Errno);
657
658 if ( addr )
659 {
660 #ifdef DBG
661 LPSOCKADDR_IN sa = (LPSOCKADDR_IN)addr;
662 WS_DbgPrint(MAX_TRACE,("Returned address: %d %s:%d (len %d)\n",
663 sa->sin_family,
664 inet_ntoa(sa->sin_addr),
665 ntohs(sa->sin_port),
666 *addrlen));
667 #endif
668 }
669
670 return Socket;
671 }
672
673
674 /*
675 * @implemented
676 */
677 INT
678 EXPORT
679 connect(IN SOCKET s,
680 IN CONST struct sockaddr *name,
681 IN INT namelen)
682 {
683 return WSAConnect(s,
684 name,
685 namelen,
686 NULL,
687 NULL,
688 NULL,
689 NULL);
690 }
691
692
693 /*
694 * @implemented
695 */
696 INT
697 EXPORT
698 WSAConnect(IN SOCKET s,
699 IN CONST struct sockaddr *name,
700 IN INT namelen,
701 IN LPWSABUF lpCallerData,
702 OUT LPWSABUF lpCalleeData,
703 IN LPQOS lpSQOS,
704 IN LPQOS lpGQOS)
705 {
706 PCATALOG_ENTRY Provider;
707 INT Status;
708 INT Errno;
709
710 if (!WSAINITIALIZED)
711 {
712 WSASetLastError(WSANOTINITIALISED);
713 return SOCKET_ERROR;
714 }
715
716 if (!ReferenceProviderByHandle((HANDLE)s, &Provider))
717 {
718 WSASetLastError(WSAENOTSOCK);
719 return SOCKET_ERROR;
720 }
721
722 #if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
723 Status = Provider->ProcTable.lpWSPConnect(s,
724 (CONST LPSOCKADDR)name,
725 namelen,
726 lpCallerData,
727 lpCalleeData,
728 lpSQOS,
729 lpGQOS,
730 &Errno);
731 #else
732 Status = Provider->ProcTable.lpWSPConnect(s,
733 name,
734 namelen,
735 lpCallerData,
736 lpCalleeData,
737 lpSQOS,
738 lpGQOS,
739 &Errno);
740 #endif
741
742 DereferenceProviderByPointer(Provider);
743
744 if (Status == SOCKET_ERROR)
745 WSASetLastError(Errno);
746
747 return Status;
748 }
749
750
751 /*
752 * @implemented
753 */
754 INT
755 EXPORT
756 WSAIoctl(IN SOCKET s,
757 IN DWORD dwIoControlCode,
758 IN LPVOID lpvInBuffer,
759 IN DWORD cbInBuffer,
760 OUT LPVOID lpvOutBuffer,
761 IN DWORD cbOutBuffer,
762 OUT LPDWORD lpcbBytesReturned,
763 IN LPWSAOVERLAPPED lpOverlapped,
764 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
765 {
766 PCATALOG_ENTRY Provider;
767 INT Status;
768 INT Errno;
769
770 if (!WSAINITIALIZED)
771 {
772 WSASetLastError(WSANOTINITIALISED);
773 return SOCKET_ERROR;
774 }
775
776 if (!ReferenceProviderByHandle((HANDLE)s, &Provider))
777 {
778 WSASetLastError(WSAENOTSOCK);
779 return SOCKET_ERROR;
780 }
781
782 Status = Provider->ProcTable.lpWSPIoctl(s,
783 dwIoControlCode,
784 lpvInBuffer,
785 cbInBuffer,
786 lpvOutBuffer,
787 cbOutBuffer,
788 lpcbBytesReturned,
789 lpOverlapped,
790 lpCompletionRoutine,
791 NULL /* lpThreadId */,
792 &Errno);
793
794 DereferenceProviderByPointer(Provider);
795
796 if (Status == SOCKET_ERROR)
797 WSASetLastError(Errno);
798
799 return Status;
800 }
801
802 /*
803 * @implemented
804 */
805 INT
806 EXPORT
807 __WSAFDIsSet(SOCKET s, LPFD_SET set)
808 {
809 unsigned int i;
810
811 for ( i = 0; i < set->fd_count; i++ )
812 if ( set->fd_array[i] == s ) return TRUE;
813
814 return FALSE;
815 }
816
817 void free_winsock_thread_block(PWINSOCK_THREAD_BLOCK p)
818 {
819 if (p)
820 {
821 if (p->Hostent) { free_hostent(p->Hostent); p->Hostent = 0; }
822 if (p->Getservbyname){}
823 if (p->Getservbyport) {}
824 }
825 }
826
827 BOOL
828 STDCALL
829 DllMain(HANDLE hInstDll,
830 ULONG dwReason,
831 LPVOID lpReserved)
832 {
833 PWINSOCK_THREAD_BLOCK p;
834
835 WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll.\n"));
836
837 switch (dwReason)
838 {
839 case DLL_PROCESS_ATTACH:
840 {
841 GlobalHeap = GetProcessHeap();
842
843 g_hInstDll = hInstDll;
844
845 CreateCatalog();
846
847 InitProviderHandleTable();
848
849 UpcallTable.lpWPUCloseEvent = WPUCloseEvent;
850 UpcallTable.lpWPUCloseSocketHandle = WPUCloseSocketHandle;
851 UpcallTable.lpWPUCreateEvent = WPUCreateEvent;
852 UpcallTable.lpWPUCreateSocketHandle = WPUCreateSocketHandle;
853 UpcallTable.lpWPUFDIsSet = WPUFDIsSet;
854 UpcallTable.lpWPUGetProviderPath = WPUGetProviderPath;
855 UpcallTable.lpWPUModifyIFSHandle = WPUModifyIFSHandle;
856 UpcallTable.lpWPUPostMessage = PostMessageW;
857 UpcallTable.lpWPUQueryBlockingCallback = WPUQueryBlockingCallback;
858 UpcallTable.lpWPUQuerySocketHandleContext = WPUQuerySocketHandleContext;
859 UpcallTable.lpWPUQueueApc = WPUQueueApc;
860 UpcallTable.lpWPUResetEvent = WPUResetEvent;
861 UpcallTable.lpWPUSetEvent = WPUSetEvent;
862 UpcallTable.lpWPUOpenCurrentThread = WPUOpenCurrentThread;
863 UpcallTable.lpWPUCloseThread = WPUCloseThread;
864
865 /* Fall through to thread attachment handler */
866 }
867 case DLL_THREAD_ATTACH:
868 {
869 p = HeapAlloc(GlobalHeap, 0, sizeof(WINSOCK_THREAD_BLOCK));
870
871 WS_DbgPrint(MAX_TRACE, ("Thread block at 0x%X.\n", p));
872
873 if (!p) {
874 return FALSE;
875 }
876
877 p->Hostent = NULL;
878 p->LastErrorValue = NO_ERROR;
879 p->Getservbyname = NULL;
880 p->Getservbyport = NULL;
881
882 NtCurrentTeb()->WinSockData = p;
883 }
884 break;
885
886 case DLL_PROCESS_DETACH:
887 {
888 p = NtCurrentTeb()->WinSockData;
889
890 if (p)
891 HeapFree(GlobalHeap, 0, p);
892
893 DestroyCatalog();
894
895 FreeProviderHandleTable();
896 }
897 break;
898
899 case DLL_THREAD_DETACH:
900 {
901 p = NtCurrentTeb()->WinSockData;
902
903 if (p)
904 HeapFree(GlobalHeap, 0, p);
905 }
906 break;
907 }
908
909 WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll. Leaving.\n"));
910
911 return TRUE;
912 }
913
914 /* EOF */