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
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;
22 /* To make the linker happy */
23 VOID WINAPI
KeBugCheck (ULONG BugCheckCode
) {}
27 BOOL WsaInitialized
= FALSE
; /* TRUE if WSAStartup() has been successfully called */
28 WSPUPCALLTABLE UpcallTable
;
38 return GetLastError();
47 WSASetLastError(IN INT iError
)
58 WSAStartup(IN WORD wVersionRequested
,
59 OUT LPWSADATA lpWSAData
)
63 WS_DbgPrint(MAX_TRACE
, ("WSAStartup of ws2_32.dll\n"));
66 return WSASYSNOTREADY
;
68 if (lpWSAData
== NULL
)
71 Low
= LOBYTE(wVersionRequested
);
72 High
= HIBYTE(wVersionRequested
);
76 WS_DbgPrint(MAX_TRACE
, ("Bad winsock version requested, %d,%d", Low
, High
));
77 return WSAVERNOTSUPPORTED
;
84 lpWSAData
->wVersion
= wVersionRequested
;
88 lpWSAData
->wVersion
= MAKEWORD(1, 1);
95 lpWSAData
->wVersion
= MAKEWORD(2, High
);
99 lpWSAData
->wVersion
= MAKEWORD(2, 2);
104 lpWSAData
->wVersion
= MAKEWORD(2, 2);
107 lpWSAData
->wVersion
= wVersionRequested
;
108 lpWSAData
->wHighVersion
= MAKEWORD(2,2);
109 lstrcpyA(lpWSAData
->szDescription
, "WinSock 2.2");
110 lstrcpyA(lpWSAData
->szSystemStatus
, "Running");
111 lpWSAData
->iMaxSockets
= 0;
112 lpWSAData
->iMaxUdpDg
= 0;
113 lpWSAData
->lpVendorInfo
= NULL
;
115 /*FIXME: increment internal counter */
130 WS_DbgPrint(MAX_TRACE
, ("WSACleanup of ws2_32.dll\n"));
134 WSASetLastError(WSANOTINITIALISED
);
135 return WSANOTINITIALISED
;
151 return WSASocketW(af
,
165 WSASocketA(IN INT af
,
168 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
172 * FUNCTION: Creates a new socket
175 WSAPROTOCOL_INFOW ProtocolInfoW
;
176 LPWSAPROTOCOL_INFOW p
;
177 UNICODE_STRING StringU
;
180 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d).\n",
181 af
, type
, protocol
));
185 memcpy(&ProtocolInfoW
,
187 sizeof(WSAPROTOCOL_INFOA
) - sizeof(CHAR
) * (WSAPROTOCOL_LEN
+ 1));
188 RtlInitAnsiString(&StringA
, (LPSTR
)lpProtocolInfo
->szProtocol
);
189 RtlInitUnicodeString(&StringU
, (LPWSTR
)&ProtocolInfoW
.szProtocol
);
190 RtlAnsiStringToUnicodeString(&StringU
, &StringA
, FALSE
);
198 return WSASocketW(af
,
212 WSASocketW(IN INT af
,
215 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
219 * FUNCTION: Creates a new socket descriptor
221 * af = Address family
223 * protocol = Protocol type
224 * lpProtocolInfo = Pointer to protocol information
226 * dwFlags = Socket flags
228 * Created socket descriptor, or INVALID_SOCKET if it could not be created
233 PCATALOG_ENTRY Provider
;
234 WSAPROTOCOL_INFOW ProtocolInfo
;
236 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d).\n",
237 af
, type
, protocol
));
241 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d) = WSANOTINITIALISED.\n",
242 af
, type
, protocol
));
243 WSASetLastError(WSANOTINITIALISED
);
244 return INVALID_SOCKET
;
249 lpProtocolInfo
= &ProtocolInfo
;
250 ZeroMemory(&ProtocolInfo
, sizeof(WSAPROTOCOL_INFOW
));
252 ProtocolInfo
.iAddressFamily
= af
;
253 ProtocolInfo
.iSocketType
= type
;
254 ProtocolInfo
.iProtocol
= protocol
;
257 Provider
= LocateProvider(lpProtocolInfo
);
260 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d) = WSAEAFNOSUPPORT.\n",
261 af
, type
, protocol
));
262 WSASetLastError(WSAEAFNOSUPPORT
);
263 return INVALID_SOCKET
;
266 Status
= LoadProvider(Provider
, lpProtocolInfo
);
267 if (Status
!= NO_ERROR
)
269 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d) = %d.\n",
270 af
, type
, protocol
, Status
));
271 WSASetLastError(Status
);
272 return INVALID_SOCKET
;
275 WS_DbgPrint(MAX_TRACE
, ("Calling WSPSocket at (0x%X).\n",
276 Provider
->ProcTable
.lpWSPSocket
));
278 assert(Provider
->ProcTable
.lpWSPSocket
);
280 WS_DbgPrint(MAX_TRACE
,("About to call provider socket fn\n"));
282 Socket
= Provider
->ProcTable
.lpWSPSocket(af
,
290 WS_DbgPrint(MAX_TRACE
,("Socket: %x, Status: %x\n", Socket
, Status
));
292 if (Status
!= NO_ERROR
)
294 WSASetLastError(Status
);
295 return INVALID_SOCKET
;
298 WS_DbgPrint(MAX_TRACE
,("Status: %x\n", Status
));
309 closesocket(IN SOCKET s
)
311 * FUNCTION: Closes a socket descriptor
313 * s = Socket descriptor
315 * 0, or SOCKET_ERROR if an error ocurred
318 PCATALOG_ENTRY Provider
;
322 WS_DbgPrint(MAX_TRACE
, ("s (0x%X).\n", s
));
326 WSASetLastError(WSANOTINITIALISED
);
330 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
332 WSASetLastError(WSAENOTSOCK
);
336 CloseProviderHandle((HANDLE
)s
);
338 WS_DbgPrint(MAX_TRACE
,("DereferenceProviderByHandle\n"));
340 DereferenceProviderByPointer(Provider
);
342 WS_DbgPrint(MAX_TRACE
,("DereferenceProviderByHandle Done\n"));
344 Status
= Provider
->ProcTable
.lpWSPCloseSocket(s
, &Errno
);
346 WS_DbgPrint(MAX_TRACE
,("Provider Close Done\n"));
348 if (Status
== SOCKET_ERROR
)
349 WSASetLastError(Errno
);
351 WS_DbgPrint(MAX_TRACE
,("Returning success\n"));
363 IN OUT LPFD_SET readfds
,
364 IN OUT LPFD_SET writefds
,
365 IN OUT LPFD_SET exceptfds
,
366 IN CONST
struct timeval
*timeout
)
368 * FUNCTION: Returns status of one or more sockets
370 * nfds = Always ignored
371 * readfds = Pointer to socket set to be checked for readability (optional)
372 * writefds = Pointer to socket set to be checked for writability (optional)
373 * exceptfds = Pointer to socket set to be checked for errors (optional)
374 * timeout = Pointer to a TIMEVAL structure indicating maximum wait time
375 * (NULL means wait forever)
377 * Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred
380 PCATALOG_ENTRY Provider
= NULL
;
384 WS_DbgPrint(MAX_TRACE
, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n",
385 readfds
, writefds
, exceptfds
));
389 WSASetLastError(WSANOTINITIALISED
);
390 WS_DbgPrint(MID_TRACE
,("Not initialized\n"));
394 /* FIXME: Sockets in FD_SETs should be sorted by their provider */
396 /* FIXME: For now, assume only one service provider */
397 if ((readfds
!= NULL
) && (readfds
->fd_count
> 0))
399 if (!ReferenceProviderByHandle((HANDLE
)readfds
->fd_array
[0],
402 WSASetLastError(WSAENOTSOCK
);
403 WS_DbgPrint(MID_TRACE
,("No provider (read)\n"));
407 else if ((writefds
!= NULL
) && (writefds
->fd_count
> 0))
409 if (!ReferenceProviderByHandle((HANDLE
)writefds
->fd_array
[0],
412 WSASetLastError(WSAENOTSOCK
);
413 WS_DbgPrint(MID_TRACE
,("No provider (write)\n"));
417 else if ((exceptfds
!= NULL
) && (exceptfds
->fd_count
> 0))
419 if (!ReferenceProviderByHandle((HANDLE
)exceptfds
->fd_array
[0], &Provider
))
421 WSASetLastError(WSAENOTSOCK
);
422 WS_DbgPrint(MID_TRACE
,("No provider (err)\n"));
425 #if 0 /* XXX empty select is not an error */
429 WSASetLastError(WSAEINVAL
);
438 WS_DbgPrint(MID_TRACE
,("Select: used as timer\n"));
439 Sleep( timeout
->tv_sec
* 1000 + (timeout
->tv_usec
/ 1000) );
443 else if (Provider
->ProcTable
.lpWSPSelect
)
445 WS_DbgPrint(MID_TRACE
,("Calling WSPSelect:%x\n", Provider
->ProcTable
.lpWSPSelect
));
446 Count
= Provider
->ProcTable
.lpWSPSelect(nfds
,
453 WS_DbgPrint(MAX_TRACE
, ("[%x] Select: Count %d Errno %x\n",
454 Provider
, Count
, Errno
));
456 DereferenceProviderByPointer(Provider
);
458 if (Count
== SOCKET_ERROR
)
460 WSASetLastError(Errno
);
466 WSASetLastError(WSAEINVAL
);
480 IN CONST
struct sockaddr
*name
,
483 PCATALOG_ENTRY Provider
;
489 WSASetLastError(WSANOTINITIALISED
);
493 if (!ReferenceProviderByHandle((HANDLE
)s
,
496 WSASetLastError(WSAENOTSOCK
);
500 #if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
501 Status
= Provider
->ProcTable
.lpWSPBind(s
,
502 (CONST LPSOCKADDR
)name
,
506 Status
= Provider
->ProcTable
.lpWSPBind(s
,
510 #endif /* __W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5 */
512 DereferenceProviderByPointer(Provider
);
514 if (Status
== SOCKET_ERROR
)
515 WSASetLastError(Errno
);
529 PCATALOG_ENTRY Provider
;
535 WSASetLastError(WSANOTINITIALISED
);
539 if (!ReferenceProviderByHandle((HANDLE
)s
,
542 WSASetLastError(WSAENOTSOCK
);
546 Status
= Provider
->ProcTable
.lpWSPListen(s
,
550 DereferenceProviderByPointer(Provider
);
552 if (Status
== SOCKET_ERROR
)
553 WSASetLastError(Errno
);
566 OUT INT FAR
* addrlen
)
581 ioctlsocket(IN SOCKET s
,
583 IN OUT ULONG FAR
* argp
)
604 WSAAccept(IN SOCKET s
,
606 IN OUT LPINT addrlen
,
607 IN LPCONDITIONPROC lpfnCondition
,
608 IN DWORD_PTR dwCallbackData
)
610 PCATALOG_ENTRY Provider
;
616 WSASetLastError(WSANOTINITIALISED
);
620 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
622 WSASetLastError(WSAENOTSOCK
);
626 WS_DbgPrint(MAX_TRACE
,("Calling provider accept\n"));
628 Socket
= Provider
->ProcTable
.lpWSPAccept(s
,
635 WS_DbgPrint(MAX_TRACE
,("Calling provider accept -> Socket %x, Errno %x\n",
638 DereferenceProviderByPointer(Provider
);
640 if (Socket
== INVALID_SOCKET
)
641 WSASetLastError(Errno
);
643 if ( addr
&& addrlen
)
646 LPSOCKADDR_IN sa
= (LPSOCKADDR_IN
)addr
;
647 WS_DbgPrint(MAX_TRACE
,("Returned address: %d %s:%d (len %d)\n",
649 inet_ntoa(sa
->sin_addr
),
665 IN CONST
struct sockaddr
*name
,
683 WSAConnect(IN SOCKET s
,
684 IN CONST
struct sockaddr
*name
,
686 IN LPWSABUF lpCallerData
,
687 OUT LPWSABUF lpCalleeData
,
691 PCATALOG_ENTRY Provider
;
697 WSASetLastError(WSANOTINITIALISED
);
701 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
703 WSASetLastError(WSAENOTSOCK
);
707 #if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
708 Status
= Provider
->ProcTable
.lpWSPConnect(s
,
709 (CONST LPSOCKADDR
)name
,
717 Status
= Provider
->ProcTable
.lpWSPConnect(s
,
727 DereferenceProviderByPointer(Provider
);
729 if (Status
== SOCKET_ERROR
)
730 WSASetLastError(Errno
);
741 WSAIoctl(IN SOCKET s
,
742 IN DWORD dwIoControlCode
,
743 IN LPVOID lpvInBuffer
,
745 OUT LPVOID lpvOutBuffer
,
746 IN DWORD cbOutBuffer
,
747 OUT LPDWORD lpcbBytesReturned
,
748 IN LPWSAOVERLAPPED lpOverlapped
,
749 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
751 PCATALOG_ENTRY Provider
;
757 WSASetLastError(WSANOTINITIALISED
);
761 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
763 WSASetLastError(WSAENOTSOCK
);
767 Status
= Provider
->ProcTable
.lpWSPIoctl(s
,
776 NULL
/* lpThreadId */,
779 DereferenceProviderByPointer(Provider
);
781 if (Status
== SOCKET_ERROR
)
782 WSASetLastError(Errno
);
792 __WSAFDIsSet(SOCKET s
, LPFD_SET set
)
796 for ( i
= 0; i
< set
->fd_count
; i
++ )
797 if ( set
->fd_array
[i
] == s
) return TRUE
;
802 void free_winsock_thread_block(PWINSOCK_THREAD_BLOCK p
)
806 if (p
->Hostent
) { free_hostent(p
->Hostent
); p
->Hostent
= 0; }
807 if (p
->Getservbyname
){}
808 if (p
->Getservbyport
) {}
814 DllMain(HANDLE hInstDll
,
818 PWINSOCK_THREAD_BLOCK p
;
820 WS_DbgPrint(MAX_TRACE
, ("DllMain of ws2_32.dll.\n"));
824 case DLL_PROCESS_ATTACH
:
826 GlobalHeap
= GetProcessHeap();
828 g_hInstDll
= hInstDll
;
832 InitProviderHandleTable();
834 UpcallTable
.lpWPUCloseEvent
= WPUCloseEvent
;
835 UpcallTable
.lpWPUCloseSocketHandle
= WPUCloseSocketHandle
;
836 UpcallTable
.lpWPUCreateEvent
= WPUCreateEvent
;
837 UpcallTable
.lpWPUCreateSocketHandle
= WPUCreateSocketHandle
;
838 UpcallTable
.lpWPUFDIsSet
= WPUFDIsSet
;
839 UpcallTable
.lpWPUGetProviderPath
= WPUGetProviderPath
;
840 UpcallTable
.lpWPUModifyIFSHandle
= WPUModifyIFSHandle
;
841 UpcallTable
.lpWPUPostMessage
= PostMessageW
;
842 UpcallTable
.lpWPUQueryBlockingCallback
= WPUQueryBlockingCallback
;
843 UpcallTable
.lpWPUQuerySocketHandleContext
= WPUQuerySocketHandleContext
;
844 UpcallTable
.lpWPUQueueApc
= WPUQueueApc
;
845 UpcallTable
.lpWPUResetEvent
= WPUResetEvent
;
846 UpcallTable
.lpWPUSetEvent
= WPUSetEvent
;
847 UpcallTable
.lpWPUOpenCurrentThread
= WPUOpenCurrentThread
;
848 UpcallTable
.lpWPUCloseThread
= WPUCloseThread
;
850 /* Fall through to thread attachment handler */
852 case DLL_THREAD_ATTACH
:
854 p
= HeapAlloc(GlobalHeap
, 0, sizeof(WINSOCK_THREAD_BLOCK
));
856 WS_DbgPrint(MAX_TRACE
, ("Thread block at 0x%X.\n", p
));
863 p
->LastErrorValue
= NO_ERROR
;
864 p
->Getservbyname
= NULL
;
865 p
->Getservbyport
= NULL
;
867 NtCurrentTeb()->WinSockData
= p
;
871 case DLL_PROCESS_DETACH
:
875 FreeProviderHandleTable();
879 case DLL_THREAD_DETACH
:
881 p
= NtCurrentTeb()->WinSockData
;
884 HeapFree(GlobalHeap
, 0, p
);
889 WS_DbgPrint(MAX_TRACE
, ("DllMain of ws2_32.dll. Leaving.\n"));