2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 DLL
5 * PURPOSE: DLL entry point
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/09-2000 Created
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;
26 /* To make the linker happy */
27 VOID STDCALL
KeBugCheck (ULONG BugCheckCode
) {}
31 BOOL WsaInitialized
= FALSE
; /* TRUE if WSAStartup() has been successfully called */
32 WSPUPCALLTABLE UpcallTable
;
43 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
46 return p
->LastErrorValue
;
48 /* FIXME: What error code should we use here? Can this even happen? */
49 return ERROR_BAD_ENVIRONMENT
;
62 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
65 p
->LastErrorValue
= iError
;
75 IN WORD wVersionRequested
,
76 OUT LPWSADATA lpWSAData
)
78 WS_DbgPrint(MAX_TRACE
, ("WSAStartup of ws2_32.dll\n"));
80 lpWSAData
->wVersion
= wVersionRequested
;
81 lpWSAData
->wHighVersion
= 2;
82 lstrcpyA(lpWSAData
->szDescription
, "WinSock 2.0");
83 lstrcpyA(lpWSAData
->szSystemStatus
, "Running");
84 lpWSAData
->iMaxSockets
= 0;
85 lpWSAData
->iMaxUdpDg
= 0;
86 lpWSAData
->lpVendorInfo
= NULL
;
101 WS_DbgPrint(MAX_TRACE
, ("WSACleanup of ws2_32.dll\n"));
103 if (!WSAINITIALIZED
) {
104 WSASetLastError(WSANOTINITIALISED
);
105 return WSANOTINITIALISED
;
122 return WSASocketA(af
, type
, protocol
, NULL
, 0, 0);
135 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
139 * FUNCTION: Creates a new socket
142 WSAPROTOCOL_INFOW ProtocolInfoW
;
143 LPWSAPROTOCOL_INFOW p
;
144 UNICODE_STRING StringU
;
147 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d).\n",
148 af
, type
, protocol
));
150 if (lpProtocolInfo
) {
151 memcpy(&ProtocolInfoW
,
153 sizeof(WSAPROTOCOL_INFOA
) -
154 sizeof(CHAR
) * (WSAPROTOCOL_LEN
+ 1));
155 RtlInitAnsiString(&StringA
, (LPSTR
)lpProtocolInfo
->szProtocol
);
156 RtlInitUnicodeString(&StringU
, (LPWSTR
)&ProtocolInfoW
.szProtocol
);
157 RtlAnsiStringToUnicodeString(&StringU
, &StringA
, FALSE
);
163 return WSASocketW(af
,
181 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
185 * FUNCTION: Creates a new socket descriptor
187 * af = Address family
189 * protocol = Protocol type
190 * lpProtocolInfo = Pointer to protocol information
192 * dwFlags = Socket flags
194 * Created socket descriptor, or INVALID_SOCKET if it could not be created
199 PCATALOG_ENTRY Provider
;
200 WSAPROTOCOL_INFOW ProtocolInfo
;
202 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d).\n",
203 af
, type
, protocol
));
205 if (!WSAINITIALIZED
) {
206 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d) = WSANOTINITIALISED.\n",
207 af
, type
, protocol
));
208 WSASetLastError(WSANOTINITIALISED
);
209 return INVALID_SOCKET
;
212 if (!lpProtocolInfo
) {
213 lpProtocolInfo
= &ProtocolInfo
;
214 ZeroMemory(&ProtocolInfo
, sizeof(WSAPROTOCOL_INFOW
));
216 ProtocolInfo
.iAddressFamily
= af
;
217 ProtocolInfo
.iSocketType
= type
;
218 ProtocolInfo
.iProtocol
= protocol
;
221 Provider
= LocateProvider(lpProtocolInfo
);
223 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d) = WSAEAFNOSUPPORT.\n",
224 af
, type
, protocol
));
225 WSASetLastError(WSAEAFNOSUPPORT
);
226 return INVALID_SOCKET
;
229 Status
= LoadProvider(Provider
, lpProtocolInfo
);
230 if (Status
!= NO_ERROR
) {
231 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d) = %d.\n",
232 af
, type
, protocol
, Status
));
233 WSASetLastError(Status
);
234 return INVALID_SOCKET
;
237 WS_DbgPrint(MAX_TRACE
, ("Calling WSPSocket at (0x%X).\n",
238 Provider
->ProcTable
.lpWSPSocket
));
240 assert(Provider
->ProcTable
.lpWSPSocket
);
242 WS_DbgPrint(MAX_TRACE
,("About to call provider socket fn\n"));
244 Socket
= Provider
->ProcTable
.lpWSPSocket(
253 WS_DbgPrint(MAX_TRACE
,("Socket: %x, Status: %x\n", Socket
, Status
));
255 if (Status
!= NO_ERROR
) {
256 WSASetLastError(Status
);
257 return INVALID_SOCKET
;
260 WS_DbgPrint(MAX_TRACE
,("Status: %x\n", Status
));
274 * FUNCTION: Closes a socket descriptor
276 * s = Socket descriptor
278 * 0, or SOCKET_ERROR if an error ocurred
281 PCATALOG_ENTRY Provider
;
285 WS_DbgPrint(MAX_TRACE
, ("s (0x%X).\n", s
));
287 if (!WSAINITIALIZED
) {
288 WSASetLastError(WSANOTINITIALISED
);
292 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
)) {
293 WSASetLastError(WSAENOTSOCK
);
297 CloseProviderHandle((HANDLE
)s
);
299 WS_DbgPrint(MAX_TRACE
,("DereferenceProviderByHandle\n"));
301 DereferenceProviderByPointer(Provider
);
303 WS_DbgPrint(MAX_TRACE
,("DereferenceProviderByHandle Done\n"));
305 Status
= Provider
->ProcTable
.lpWSPCloseSocket(s
, &Errno
);
307 WS_DbgPrint(MAX_TRACE
,("Provider Close Done\n"));
309 if (Status
== SOCKET_ERROR
)
310 WSASetLastError(Errno
);
312 WS_DbgPrint(MAX_TRACE
,("Returning success\n"));
325 IN OUT LPFD_SET readfds
,
326 IN OUT LPFD_SET writefds
,
327 IN OUT LPFD_SET exceptfds
,
328 IN CONST
struct timeval
*timeout
)
330 * FUNCTION: Returns status of one or more sockets
332 * nfds = Always ignored
333 * readfds = Pointer to socket set to be checked for readability (optional)
334 * writefds = Pointer to socket set to be checked for writability (optional)
335 * exceptfds = Pointer to socket set to be checked for errors (optional)
336 * timeout = Pointer to a TIMEVAL structure indicating maximum wait time
337 * (NULL means wait forever)
339 * Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred
342 PCATALOG_ENTRY Provider
= NULL
;
346 WS_DbgPrint(MAX_TRACE
, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n",
347 readfds
, writefds
, exceptfds
));
349 if (!WSAINITIALIZED
) {
350 WSASetLastError(WSANOTINITIALISED
);
351 WS_DbgPrint(MID_TRACE
,("Not initialized\n"));
355 /* FIXME: Sockets in FD_SETs should be sorted by their provider */
357 /* FIXME: For now, assume only one service provider */
358 if ((readfds
!= NULL
) && (readfds
->fd_count
> 0)) {
359 if (!ReferenceProviderByHandle((HANDLE
)readfds
->fd_array
[0], &Provider
)) {
360 WSASetLastError(WSAENOTSOCK
);
361 WS_DbgPrint(MID_TRACE
,("No provider (read)\n"));
364 } else if ((writefds
!= NULL
) && (writefds
->fd_count
> 0)) {
365 if (!ReferenceProviderByHandle((HANDLE
)writefds
->fd_array
[0], &Provider
)) {
366 WSASetLastError(WSAENOTSOCK
);
367 WS_DbgPrint(MID_TRACE
,("No provider (write)\n"));
370 } else if ((exceptfds
!= NULL
) && (exceptfds
->fd_count
> 0)) {
371 if (!ReferenceProviderByHandle((HANDLE
)exceptfds
->fd_array
[0], &Provider
)) {
372 WSASetLastError(WSAENOTSOCK
);
373 WS_DbgPrint(MID_TRACE
,("No provider (err)\n"));
376 #if 0 /* XXX empty select is not an error */
378 WSASetLastError(WSAEINVAL
);
385 WS_DbgPrint(MID_TRACE
,("Select: used as timer\n"));
386 Sleep( timeout
->tv_sec
* 1000 + (timeout
->tv_usec
/ 1000) );
389 } else if (Provider
->ProcTable
.lpWSPSelect
) {
390 WS_DbgPrint(MID_TRACE
,("Calling WSPSelect:%x\n", Provider
->ProcTable
.lpWSPSelect
));
391 Count
= Provider
->ProcTable
.lpWSPSelect(
392 nfds
, readfds
, writefds
, exceptfds
, (LPTIMEVAL
)timeout
, &Errno
);
394 WS_DbgPrint(MAX_TRACE
, ("[%x] Select: Count %d Errno %x\n",
395 Provider
, Count
, Errno
));
397 DereferenceProviderByPointer(Provider
);
399 if (Errno
!= NO_ERROR
) {
400 WSASetLastError(Errno
);
404 WSASetLastError(WSAEINVAL
);
419 IN CONST
struct sockaddr
*name
,
422 PCATALOG_ENTRY Provider
;
426 if (!WSAINITIALIZED
) {
427 WSASetLastError(WSANOTINITIALISED
);
431 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
)) {
432 WSASetLastError(WSAENOTSOCK
);
436 #if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
437 Status
= Provider
->ProcTable
.lpWSPBind(
438 s
, (CONST LPSOCKADDR
) name
, namelen
, &Errno
);
440 Status
= Provider
->ProcTable
.lpWSPBind(
441 s
, name
, namelen
, &Errno
);
442 #endif /* __W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5 */
444 DereferenceProviderByPointer(Provider
);
446 if (Status
== SOCKET_ERROR
) {
447 WSASetLastError(Errno
);
463 PCATALOG_ENTRY Provider
;
467 if (!WSAINITIALIZED
) {
468 WSASetLastError(WSANOTINITIALISED
);
472 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
)) {
473 WSASetLastError(WSAENOTSOCK
);
477 Status
= Provider
->ProcTable
.lpWSPListen(
480 DereferenceProviderByPointer(Provider
);
482 if (Status
== SOCKET_ERROR
) {
483 WSASetLastError(Errno
);
498 OUT INT FAR
* addrlen
)
500 return WSAAccept(s
, addr
, addrlen
, NULL
, 0);
512 IN OUT ULONG FAR
* argp
)
514 return WSAIoctl(s
, cmd
, argp
, sizeof(ULONG
), argp
, sizeof(ULONG
), argp
, 0, 0);
526 IN OUT LPINT addrlen
,
527 IN LPCONDITIONPROC lpfnCondition
,
528 IN DWORD dwCallbackData
)
530 PCATALOG_ENTRY Provider
;
534 if (!WSAINITIALIZED
) {
535 WSASetLastError(WSANOTINITIALISED
);
539 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
)) {
540 WSASetLastError(WSAENOTSOCK
);
544 WS_DbgPrint(MAX_TRACE
,("Calling provider accept\n"));
546 Socket
= Provider
->ProcTable
.lpWSPAccept(
547 s
, addr
, addrlen
, lpfnCondition
, dwCallbackData
, &Errno
);
549 WS_DbgPrint(MAX_TRACE
,("Calling provider accept -> Socket %x, Errno %x\n",
552 DereferenceProviderByPointer(Provider
);
554 if (Socket
== INVALID_SOCKET
) {
555 WSASetLastError(Errno
);
560 LPSOCKADDR_IN sa
= (LPSOCKADDR_IN
)addr
;
561 WS_DbgPrint(MAX_TRACE
,("Returned address: %d %s:%d (len %d)\n",
563 inet_ntoa(sa
->sin_addr
),
580 IN CONST
struct sockaddr
*name
,
583 return WSAConnect(s
, name
, namelen
, NULL
, NULL
, NULL
, NULL
);
594 IN CONST
struct sockaddr
*name
,
596 IN LPWSABUF lpCallerData
,
597 OUT LPWSABUF lpCalleeData
,
601 PCATALOG_ENTRY Provider
;
605 if (!WSAINITIALIZED
) {
606 WSASetLastError(WSANOTINITIALISED
);
610 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
)) {
611 WSASetLastError(WSAENOTSOCK
);
615 #if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
616 Status
= Provider
->ProcTable
.lpWSPConnect(
617 s
, (CONST LPSOCKADDR
) name
, namelen
, lpCallerData
, lpCalleeData
, lpSQOS
, lpGQOS
, &Errno
);
619 Status
= Provider
->ProcTable
.lpWSPConnect(
620 s
, name
, namelen
, lpCallerData
, lpCalleeData
, lpSQOS
, lpGQOS
, &Errno
);
623 DereferenceProviderByPointer(Provider
);
625 if (Status
== SOCKET_ERROR
) {
626 WSASetLastError(Errno
);
640 IN DWORD dwIoControlCode
,
641 IN LPVOID lpvInBuffer
,
643 OUT LPVOID lpvOutBuffer
,
644 IN DWORD cbOutBuffer
,
645 OUT LPDWORD lpcbBytesReturned
,
646 IN LPWSAOVERLAPPED lpOverlapped
,
647 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
649 PCATALOG_ENTRY Provider
;
653 if (!WSAINITIALIZED
) {
654 WSASetLastError(WSANOTINITIALISED
);
658 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
)) {
659 WSASetLastError(WSAENOTSOCK
);
663 Status
= Provider
->ProcTable
.lpWSPIoctl(
664 s
, dwIoControlCode
, lpvInBuffer
, cbInBuffer
, lpvOutBuffer
,
665 cbOutBuffer
, lpcbBytesReturned
, lpOverlapped
, lpCompletionRoutine
,
666 NULL
/* lpThreadId */, &Errno
);
668 DereferenceProviderByPointer(Provider
);
670 if (Status
== SOCKET_ERROR
) {
671 WSASetLastError(Errno
);
682 __WSAFDIsSet(SOCKET s
, LPFD_SET set
)
686 for( i
= 0; i
< set
->fd_count
; i
++ )
687 if( set
->fd_array
[i
] == s
) return TRUE
;
692 void free_winsock_thread_block(PWINSOCK_THREAD_BLOCK p
) {
694 if(p
->Hostent
) { free_hostent(p
->Hostent
); p
->Hostent
= 0; }
695 if(p
->Getservbyname
){}
696 if(p
->Getservbyport
) {}
704 DllMain(HANDLE hInstDll
,
708 PWINSOCK_THREAD_BLOCK p
;
710 WS_DbgPrint(MAX_TRACE
, ("DllMain of ws2_32.dll.\n"));
713 case DLL_PROCESS_ATTACH
:
714 GlobalHeap
= GetProcessHeap();
718 InitProviderHandleTable();
720 UpcallTable
.lpWPUCloseEvent
= WPUCloseEvent
;
721 UpcallTable
.lpWPUCloseSocketHandle
= WPUCloseSocketHandle
;
722 UpcallTable
.lpWPUCreateEvent
= WPUCreateEvent
;
723 UpcallTable
.lpWPUCreateSocketHandle
= WPUCreateSocketHandle
;
724 UpcallTable
.lpWPUFDIsSet
= WPUFDIsSet
;
725 UpcallTable
.lpWPUGetProviderPath
= WPUGetProviderPath
;
726 UpcallTable
.lpWPUModifyIFSHandle
= WPUModifyIFSHandle
;
727 UpcallTable
.lpWPUPostMessage
= PostMessageW
;
728 UpcallTable
.lpWPUQueryBlockingCallback
= WPUQueryBlockingCallback
;
729 UpcallTable
.lpWPUQuerySocketHandleContext
= WPUQuerySocketHandleContext
;
730 UpcallTable
.lpWPUQueueApc
= WPUQueueApc
;
731 UpcallTable
.lpWPUResetEvent
= WPUResetEvent
;
732 UpcallTable
.lpWPUSetEvent
= WPUSetEvent
;
733 UpcallTable
.lpWPUOpenCurrentThread
= WPUOpenCurrentThread
;
734 UpcallTable
.lpWPUCloseThread
= WPUCloseThread
;
736 /* Fall through to thread attachment handler */
738 case DLL_THREAD_ATTACH
:
739 p
= HeapAlloc(GlobalHeap
, 0, sizeof(WINSOCK_THREAD_BLOCK
));
741 WS_DbgPrint(MAX_TRACE
, ("Thread block at 0x%X.\n", p
));
748 p
->LastErrorValue
= NO_ERROR
;
749 p
->Getservbyname
= NULL
;
750 p
->Getservbyport
= NULL
;
752 NtCurrentTeb()->WinSockData
= p
;
755 case DLL_PROCESS_DETACH
:
756 p
= NtCurrentTeb()->WinSockData
;
759 HeapFree(GlobalHeap
, 0, p
);
763 FreeProviderHandleTable();
766 case DLL_THREAD_DETACH
:
767 p
= NtCurrentTeb()->WinSockData
;
770 HeapFree(GlobalHeap
, 0, p
);
774 WS_DbgPrint(MAX_TRACE
, ("DllMain of ws2_32.dll. Leaving.\n"));