2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 DLL
4 * FILE: dll/win32/ws2_32/misc/dllmain.c
5 * PURPOSE: DLL entry point
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/09-2000 Created
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;
24 BOOL WsaInitialized
= FALSE
; /* TRUE if WSAStartup() has been successfully called */
25 WSPUPCALLTABLE UpcallTable
;
35 return GetLastError();
44 WSASetLastError(IN INT iError
)
55 WSAStartup(IN WORD wVersionRequested
,
56 OUT LPWSADATA lpWSAData
)
58 WORD VersionReturned
= 0;
59 DWORD ErrorCode
= ERROR_SUCCESS
;
61 WS_DbgPrint(MAX_TRACE
, ("WSAStartup of ws2_32.dll\n"));
64 return WSASYSNOTREADY
;
66 if (lpWSAData
== NULL
)
69 /* Check which version is being requested */
70 switch (LOBYTE(wVersionRequested
))
74 /* We don't support this unknown version */
75 ErrorCode
= WSAVERNOTSUPPORTED
;
79 /* We support only 1.0 and 1.1 */
80 if (HIBYTE(wVersionRequested
) == 0)
82 /* Caller wants 1.0, return it */
83 VersionReturned
= wVersionRequested
;
87 /* The only other version we support is 1.1 */
88 VersionReturned
= MAKEWORD(1, 1);
93 /* We support only 2.0, 2.1 and 2.2 */
94 if (HIBYTE(wVersionRequested
) <= 2)
96 /* Caller wants 2.0-2.2, return it */
97 VersionReturned
= MAKEWORD(2, HIBYTE(wVersionRequested
));
101 /* The highest version we support is 2.2 */
102 VersionReturned
= MAKEWORD(2, 2);
109 VersionReturned
= MAKEWORD(2, 2);;
113 /* Return the Version Requested, unless error */
114 lpWSAData
->wVersion
= VersionReturned
;
116 lpWSAData
->wHighVersion
= MAKEWORD(2,2);
117 lstrcpyA(lpWSAData
->szDescription
, "WinSock 2.0");
118 lstrcpyA(lpWSAData
->szSystemStatus
, "Running");
120 if (LOBYTE(wVersionRequested
) == 1)
122 lpWSAData
->iMaxSockets
= 32767;
123 lpWSAData
->iMaxUdpDg
= 65467;
127 lpWSAData
->iMaxSockets
= 0;
128 lpWSAData
->iMaxUdpDg
= 0;
131 /*FIXME: increment internal counter */
133 if (ErrorCode
== ERROR_SUCCESS
)
147 WS_DbgPrint(MAX_TRACE
, ("WSACleanup of ws2_32.dll\n"));
151 WSASetLastError(WSANOTINITIALISED
);
152 return WSANOTINITIALISED
;
168 return WSASocketW(af
,
182 WSASocketA(IN INT af
,
185 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
189 * FUNCTION: Creates a new socket
192 WSAPROTOCOL_INFOW ProtocolInfoW
;
193 LPWSAPROTOCOL_INFOW p
;
194 UNICODE_STRING StringU
;
197 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d).\n",
198 af
, type
, protocol
));
202 memcpy(&ProtocolInfoW
,
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
);
215 return WSASocketW(af
,
229 WSASocketW(IN INT af
,
232 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
236 * FUNCTION: Creates a new socket descriptor
238 * af = Address family
240 * protocol = Protocol type
241 * lpProtocolInfo = Pointer to protocol information
243 * dwFlags = Socket flags
245 * Created socket descriptor, or INVALID_SOCKET if it could not be created
250 PCATALOG_ENTRY Provider
;
251 WSAPROTOCOL_INFOW ProtocolInfo
;
253 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d).\n",
254 af
, type
, protocol
));
258 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d) = WSANOTINITIALISED.\n",
259 af
, type
, protocol
));
260 WSASetLastError(WSANOTINITIALISED
);
261 return INVALID_SOCKET
;
266 lpProtocolInfo
= &ProtocolInfo
;
267 ZeroMemory(&ProtocolInfo
, sizeof(WSAPROTOCOL_INFOW
));
269 ProtocolInfo
.iAddressFamily
= af
;
270 ProtocolInfo
.iSocketType
= type
;
271 ProtocolInfo
.iProtocol
= protocol
;
274 Provider
= LocateProvider(lpProtocolInfo
);
277 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d) = WSAEAFNOSUPPORT.\n",
278 af
, type
, protocol
));
279 WSASetLastError(WSAEAFNOSUPPORT
);
280 return INVALID_SOCKET
;
283 Status
= LoadProvider(Provider
, lpProtocolInfo
);
284 if (Status
!= NO_ERROR
)
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
;
292 WS_DbgPrint(MAX_TRACE
, ("Calling WSPSocket at (0x%X).\n",
293 Provider
->ProcTable
.lpWSPSocket
));
295 assert(Provider
->ProcTable
.lpWSPSocket
);
297 WS_DbgPrint(MAX_TRACE
,("About to call provider socket fn\n"));
299 Socket
= Provider
->ProcTable
.lpWSPSocket(af
,
307 WS_DbgPrint(MAX_TRACE
,("Socket: %x, Status: %x\n", Socket
, Status
));
309 if (Status
!= NO_ERROR
)
311 WSASetLastError(Status
);
312 return INVALID_SOCKET
;
315 WS_DbgPrint(MAX_TRACE
,("Status: %x\n", Status
));
326 closesocket(IN SOCKET s
)
328 * FUNCTION: Closes a socket descriptor
330 * s = Socket descriptor
332 * 0, or SOCKET_ERROR if an error ocurred
335 PCATALOG_ENTRY Provider
;
339 WS_DbgPrint(MAX_TRACE
, ("s (0x%X).\n", s
));
343 WSASetLastError(WSANOTINITIALISED
);
347 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
349 WSASetLastError(WSAENOTSOCK
);
353 CloseProviderHandle((HANDLE
)s
);
355 WS_DbgPrint(MAX_TRACE
,("DereferenceProviderByHandle\n"));
357 DereferenceProviderByPointer(Provider
);
359 WS_DbgPrint(MAX_TRACE
,("DereferenceProviderByHandle Done\n"));
361 Status
= Provider
->ProcTable
.lpWSPCloseSocket(s
, &Errno
);
363 WS_DbgPrint(MAX_TRACE
,("Provider Close Done\n"));
365 if (Status
== SOCKET_ERROR
)
366 WSASetLastError(Errno
);
368 WS_DbgPrint(MAX_TRACE
,("Returning success\n"));
380 IN OUT LPFD_SET readfds
,
381 IN OUT LPFD_SET writefds
,
382 IN OUT LPFD_SET exceptfds
,
383 IN CONST
struct timeval
*timeout
)
385 * FUNCTION: Returns status of one or more sockets
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)
394 * Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred
397 PCATALOG_ENTRY Provider
= NULL
;
401 WS_DbgPrint(MAX_TRACE
, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n",
402 readfds
, writefds
, exceptfds
));
406 WSASetLastError(WSANOTINITIALISED
);
407 WS_DbgPrint(MID_TRACE
,("Not initialized\n"));
411 /* FIXME: Sockets in FD_SETs should be sorted by their provider */
413 /* FIXME: For now, assume only one service provider */
414 if ((readfds
!= NULL
) && (readfds
->fd_count
> 0))
416 if (!ReferenceProviderByHandle((HANDLE
)readfds
->fd_array
[0],
419 WSASetLastError(WSAENOTSOCK
);
420 WS_DbgPrint(MID_TRACE
,("No provider (read)\n"));
424 else if ((writefds
!= NULL
) && (writefds
->fd_count
> 0))
426 if (!ReferenceProviderByHandle((HANDLE
)writefds
->fd_array
[0],
429 WSASetLastError(WSAENOTSOCK
);
430 WS_DbgPrint(MID_TRACE
,("No provider (write)\n"));
434 else if ((exceptfds
!= NULL
) && (exceptfds
->fd_count
> 0))
436 if (!ReferenceProviderByHandle((HANDLE
)exceptfds
->fd_array
[0], &Provider
))
438 WSASetLastError(WSAENOTSOCK
);
439 WS_DbgPrint(MID_TRACE
,("No provider (err)\n"));
442 #if 0 /* XXX empty select is not an error */
446 WSASetLastError(WSAEINVAL
);
455 WS_DbgPrint(MID_TRACE
,("Select: used as timer\n"));
456 Sleep( timeout
->tv_sec
* 1000 + (timeout
->tv_usec
/ 1000) );
460 else if (Provider
->ProcTable
.lpWSPSelect
)
462 WS_DbgPrint(MID_TRACE
,("Calling WSPSelect:%x\n", Provider
->ProcTable
.lpWSPSelect
));
463 Count
= Provider
->ProcTable
.lpWSPSelect(nfds
,
470 WS_DbgPrint(MAX_TRACE
, ("[%x] Select: Count %d Errno %x\n",
471 Provider
, Count
, Errno
));
473 DereferenceProviderByPointer(Provider
);
475 if (Count
== SOCKET_ERROR
)
477 WSASetLastError(Errno
);
483 WSASetLastError(WSAEINVAL
);
497 IN CONST
struct sockaddr
*name
,
500 PCATALOG_ENTRY Provider
;
506 WSASetLastError(WSANOTINITIALISED
);
510 if (!ReferenceProviderByHandle((HANDLE
)s
,
513 WSASetLastError(WSAENOTSOCK
);
517 #if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
518 Status
= Provider
->ProcTable
.lpWSPBind(s
,
519 (CONST LPSOCKADDR
)name
,
523 Status
= Provider
->ProcTable
.lpWSPBind(s
,
527 #endif /* __W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5 */
529 DereferenceProviderByPointer(Provider
);
531 if (Status
== SOCKET_ERROR
)
532 WSASetLastError(Errno
);
546 PCATALOG_ENTRY Provider
;
552 WSASetLastError(WSANOTINITIALISED
);
556 if (!ReferenceProviderByHandle((HANDLE
)s
,
559 WSASetLastError(WSAENOTSOCK
);
563 Status
= Provider
->ProcTable
.lpWSPListen(s
,
567 DereferenceProviderByPointer(Provider
);
569 if (Status
== SOCKET_ERROR
)
570 WSASetLastError(Errno
);
583 OUT INT FAR
* addrlen
)
598 ioctlsocket(IN SOCKET s
,
600 IN OUT ULONG FAR
* argp
)
621 WSAAccept(IN SOCKET s
,
623 IN OUT LPINT addrlen
,
624 IN LPCONDITIONPROC lpfnCondition
,
625 IN DWORD_PTR dwCallbackData
)
627 PCATALOG_ENTRY Provider
;
633 WSASetLastError(WSANOTINITIALISED
);
637 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
639 WSASetLastError(WSAENOTSOCK
);
643 WS_DbgPrint(MAX_TRACE
,("Calling provider accept\n"));
645 Socket
= Provider
->ProcTable
.lpWSPAccept(s
,
652 WS_DbgPrint(MAX_TRACE
,("Calling provider accept -> Socket %x, Errno %x\n",
655 DereferenceProviderByPointer(Provider
);
657 if (Socket
== INVALID_SOCKET
)
658 WSASetLastError(Errno
);
660 if ( addr
&& addrlen
)
663 LPSOCKADDR_IN sa
= (LPSOCKADDR_IN
)addr
;
664 WS_DbgPrint(MAX_TRACE
,("Returned address: %d %s:%d (len %d)\n",
666 inet_ntoa(sa
->sin_addr
),
682 IN CONST
struct sockaddr
*name
,
700 WSAConnect(IN SOCKET s
,
701 IN CONST
struct sockaddr
*name
,
703 IN LPWSABUF lpCallerData
,
704 OUT LPWSABUF lpCalleeData
,
708 PCATALOG_ENTRY Provider
;
714 WSASetLastError(WSANOTINITIALISED
);
718 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
720 WSASetLastError(WSAENOTSOCK
);
724 #if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
725 Status
= Provider
->ProcTable
.lpWSPConnect(s
,
726 (CONST LPSOCKADDR
)name
,
734 Status
= Provider
->ProcTable
.lpWSPConnect(s
,
744 DereferenceProviderByPointer(Provider
);
746 if (Status
== SOCKET_ERROR
)
747 WSASetLastError(Errno
);
758 WSAIoctl(IN SOCKET s
,
759 IN DWORD dwIoControlCode
,
760 IN LPVOID lpvInBuffer
,
762 OUT LPVOID lpvOutBuffer
,
763 IN DWORD cbOutBuffer
,
764 OUT LPDWORD lpcbBytesReturned
,
765 IN LPWSAOVERLAPPED lpOverlapped
,
766 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
768 PCATALOG_ENTRY Provider
;
774 WSASetLastError(WSANOTINITIALISED
);
778 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
780 WSASetLastError(WSAENOTSOCK
);
784 Status
= Provider
->ProcTable
.lpWSPIoctl(s
,
793 NULL
/* lpThreadId */,
796 DereferenceProviderByPointer(Provider
);
798 if (Status
== SOCKET_ERROR
)
799 WSASetLastError(Errno
);
809 __WSAFDIsSet(SOCKET s
, LPFD_SET set
)
813 for ( i
= 0; i
< set
->fd_count
; i
++ )
814 if ( set
->fd_array
[i
] == s
) return TRUE
;
819 void free_winsock_thread_block(PWINSOCK_THREAD_BLOCK p
)
823 if (p
->Hostent
) { free_hostent(p
->Hostent
); p
->Hostent
= 0; }
824 if (p
->Getservbyname
){}
825 if (p
->Getservbyport
) {}
831 DllMain(HANDLE hInstDll
,
835 PWINSOCK_THREAD_BLOCK p
;
837 WS_DbgPrint(MAX_TRACE
, ("DllMain of ws2_32.dll.\n"));
841 case DLL_PROCESS_ATTACH
:
843 GlobalHeap
= GetProcessHeap();
845 g_hInstDll
= hInstDll
;
849 InitProviderHandleTable();
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
;
867 /* Fall through to thread attachment handler */
869 case DLL_THREAD_ATTACH
:
871 p
= HeapAlloc(GlobalHeap
, 0, sizeof(WINSOCK_THREAD_BLOCK
));
873 WS_DbgPrint(MAX_TRACE
, ("Thread block at 0x%X.\n", p
));
880 p
->LastErrorValue
= NO_ERROR
;
881 p
->Getservbyname
= NULL
;
882 p
->Getservbyport
= NULL
;
884 NtCurrentTeb()->WinSockData
= p
;
888 case DLL_PROCESS_DETACH
:
892 FreeProviderHandleTable();
898 case DLL_THREAD_DETACH
:
900 p
= NtCurrentTeb()->WinSockData
;
903 HeapFree(GlobalHeap
, 0, p
);
908 WS_DbgPrint(MAX_TRACE
, ("DllMain of ws2_32.dll. Leaving.\n"));