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
20 /* See debug.h for debug/trace constants */
21 //DWORD DebugTraceLevel = MIN_TRACE;
22 //DWORD DebugTraceLevel = MAX_TRACE;
23 //DWORD DebugTraceLevel = DEBUG_ULTRA;
24 DWORD DebugTraceLevel
= 0;
27 /* To make the linker happy */
28 VOID STDCALL
KeBugCheck (ULONG BugCheckCode
) {}
32 BOOL WsaInitialized
= FALSE
; /* TRUE if WSAStartup() has been successfully called */
33 WSPUPCALLTABLE UpcallTable
;
43 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
47 return p
->LastErrorValue
;
51 /* FIXME: What error code should we use here? Can this even happen? */
52 return ERROR_BAD_ENVIRONMENT
;
62 WSASetLastError(IN INT iError
)
64 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
67 p
->LastErrorValue
= iError
;
76 WSAStartup(IN WORD wVersionRequested
,
77 OUT LPWSADATA lpWSAData
)
81 WS_DbgPrint(MAX_TRACE
, ("WSAStartup of ws2_32.dll\n"));
84 return WSASYSNOTREADY
;
86 if (lpWSAData
== NULL
)
89 Low
= LOBYTE(wVersionRequested
);
90 High
= HIBYTE(wVersionRequested
);
94 WS_DbgPrint(MAX_TRACE
, ("Bad winsock version requested, %d,%d", Low
, High
));
95 return WSAVERNOTSUPPORTED
;
102 lpWSAData
->wVersion
= wVersionRequested
;
106 lpWSAData
->wVersion
= MAKEWORD(1, 1);
113 lpWSAData
->wVersion
= MAKEWORD(2, High
);
117 lpWSAData
->wVersion
= MAKEWORD(2, 2);
122 lpWSAData
->wVersion
= MAKEWORD(2, 2);
125 lpWSAData
->wVersion
= wVersionRequested
;
126 lpWSAData
->wHighVersion
= MAKEWORD(2,2);
127 lstrcpyA(lpWSAData
->szDescription
, "WinSock 2.2");
128 lstrcpyA(lpWSAData
->szSystemStatus
, "Running");
129 lpWSAData
->iMaxSockets
= 0;
130 lpWSAData
->iMaxUdpDg
= 0;
131 lpWSAData
->lpVendorInfo
= NULL
;
133 /*FIXME: increment internal counter */
148 WS_DbgPrint(MAX_TRACE
, ("WSACleanup of ws2_32.dll\n"));
152 WSASetLastError(WSANOTINITIALISED
);
153 return WSANOTINITIALISED
;
169 return WSASocketA(af
,
183 WSASocketA(IN INT af
,
186 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
190 * FUNCTION: Creates a new socket
193 WSAPROTOCOL_INFOW ProtocolInfoW
;
194 LPWSAPROTOCOL_INFOW p
;
195 UNICODE_STRING StringU
;
198 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d).\n",
199 af
, type
, protocol
));
203 memcpy(&ProtocolInfoW
,
205 sizeof(WSAPROTOCOL_INFOA
) - sizeof(CHAR
) * (WSAPROTOCOL_LEN
+ 1));
206 RtlInitAnsiString(&StringA
, (LPSTR
)lpProtocolInfo
->szProtocol
);
207 RtlInitUnicodeString(&StringU
, (LPWSTR
)&ProtocolInfoW
.szProtocol
);
208 RtlAnsiStringToUnicodeString(&StringU
, &StringA
, FALSE
);
216 return WSASocketW(af
,
230 WSASocketW(IN INT af
,
233 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
237 * FUNCTION: Creates a new socket descriptor
239 * af = Address family
241 * protocol = Protocol type
242 * lpProtocolInfo = Pointer to protocol information
244 * dwFlags = Socket flags
246 * Created socket descriptor, or INVALID_SOCKET if it could not be created
251 PCATALOG_ENTRY Provider
;
252 WSAPROTOCOL_INFOW ProtocolInfo
;
254 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d).\n",
255 af
, type
, protocol
));
259 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d) = WSANOTINITIALISED.\n",
260 af
, type
, protocol
));
261 WSASetLastError(WSANOTINITIALISED
);
262 return INVALID_SOCKET
;
267 lpProtocolInfo
= &ProtocolInfo
;
268 ZeroMemory(&ProtocolInfo
, sizeof(WSAPROTOCOL_INFOW
));
270 ProtocolInfo
.iAddressFamily
= af
;
271 ProtocolInfo
.iSocketType
= type
;
272 ProtocolInfo
.iProtocol
= protocol
;
275 Provider
= LocateProvider(lpProtocolInfo
);
278 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d) = WSAEAFNOSUPPORT.\n",
279 af
, type
, protocol
));
280 WSASetLastError(WSAEAFNOSUPPORT
);
281 return INVALID_SOCKET
;
284 Status
= LoadProvider(Provider
, lpProtocolInfo
);
285 if (Status
!= NO_ERROR
)
287 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d) = %d.\n",
288 af
, type
, protocol
, Status
));
289 WSASetLastError(Status
);
290 return INVALID_SOCKET
;
293 WS_DbgPrint(MAX_TRACE
, ("Calling WSPSocket at (0x%X).\n",
294 Provider
->ProcTable
.lpWSPSocket
));
296 assert(Provider
->ProcTable
.lpWSPSocket
);
298 WS_DbgPrint(MAX_TRACE
,("About to call provider socket fn\n"));
300 Socket
= Provider
->ProcTable
.lpWSPSocket(af
,
308 WS_DbgPrint(MAX_TRACE
,("Socket: %x, Status: %x\n", Socket
, Status
));
310 if (Status
!= NO_ERROR
)
312 WSASetLastError(Status
);
313 return INVALID_SOCKET
;
316 WS_DbgPrint(MAX_TRACE
,("Status: %x\n", Status
));
327 closesocket(IN SOCKET s
)
329 * FUNCTION: Closes a socket descriptor
331 * s = Socket descriptor
333 * 0, or SOCKET_ERROR if an error ocurred
336 PCATALOG_ENTRY Provider
;
340 WS_DbgPrint(MAX_TRACE
, ("s (0x%X).\n", s
));
344 WSASetLastError(WSANOTINITIALISED
);
348 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
350 WSASetLastError(WSAENOTSOCK
);
354 CloseProviderHandle((HANDLE
)s
);
356 WS_DbgPrint(MAX_TRACE
,("DereferenceProviderByHandle\n"));
358 DereferenceProviderByPointer(Provider
);
360 WS_DbgPrint(MAX_TRACE
,("DereferenceProviderByHandle Done\n"));
362 Status
= Provider
->ProcTable
.lpWSPCloseSocket(s
, &Errno
);
364 WS_DbgPrint(MAX_TRACE
,("Provider Close Done\n"));
366 if (Status
== SOCKET_ERROR
)
367 WSASetLastError(Errno
);
369 WS_DbgPrint(MAX_TRACE
,("Returning success\n"));
381 IN OUT LPFD_SET readfds
,
382 IN OUT LPFD_SET writefds
,
383 IN OUT LPFD_SET exceptfds
,
384 IN CONST
struct timeval
*timeout
)
386 * FUNCTION: Returns status of one or more sockets
388 * nfds = Always ignored
389 * readfds = Pointer to socket set to be checked for readability (optional)
390 * writefds = Pointer to socket set to be checked for writability (optional)
391 * exceptfds = Pointer to socket set to be checked for errors (optional)
392 * timeout = Pointer to a TIMEVAL structure indicating maximum wait time
393 * (NULL means wait forever)
395 * Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred
398 PCATALOG_ENTRY Provider
= NULL
;
402 WS_DbgPrint(MAX_TRACE
, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n",
403 readfds
, writefds
, exceptfds
));
407 WSASetLastError(WSANOTINITIALISED
);
408 WS_DbgPrint(MID_TRACE
,("Not initialized\n"));
412 /* FIXME: Sockets in FD_SETs should be sorted by their provider */
414 /* FIXME: For now, assume only one service provider */
415 if ((readfds
!= NULL
) && (readfds
->fd_count
> 0))
417 if (!ReferenceProviderByHandle((HANDLE
)readfds
->fd_array
[0],
420 WSASetLastError(WSAENOTSOCK
);
421 WS_DbgPrint(MID_TRACE
,("No provider (read)\n"));
425 else if ((writefds
!= NULL
) && (writefds
->fd_count
> 0))
427 if (!ReferenceProviderByHandle((HANDLE
)writefds
->fd_array
[0],
430 WSASetLastError(WSAENOTSOCK
);
431 WS_DbgPrint(MID_TRACE
,("No provider (write)\n"));
435 else if ((exceptfds
!= NULL
) && (exceptfds
->fd_count
> 0))
437 if (!ReferenceProviderByHandle((HANDLE
)exceptfds
->fd_array
[0], &Provider
))
439 WSASetLastError(WSAENOTSOCK
);
440 WS_DbgPrint(MID_TRACE
,("No provider (err)\n"));
443 #if 0 /* XXX empty select is not an error */
447 WSASetLastError(WSAEINVAL
);
456 WS_DbgPrint(MID_TRACE
,("Select: used as timer\n"));
457 Sleep( timeout
->tv_sec
* 1000 + (timeout
->tv_usec
/ 1000) );
461 else if (Provider
->ProcTable
.lpWSPSelect
)
463 WS_DbgPrint(MID_TRACE
,("Calling WSPSelect:%x\n", Provider
->ProcTable
.lpWSPSelect
));
464 Count
= Provider
->ProcTable
.lpWSPSelect(nfds
,
471 WS_DbgPrint(MAX_TRACE
, ("[%x] Select: Count %d Errno %x\n",
472 Provider
, Count
, Errno
));
474 DereferenceProviderByPointer(Provider
);
476 if (Errno
!= NO_ERROR
)
478 WSASetLastError(Errno
);
484 WSASetLastError(WSAEINVAL
);
498 IN CONST
struct sockaddr
*name
,
501 PCATALOG_ENTRY Provider
;
507 WSASetLastError(WSANOTINITIALISED
);
511 if (!ReferenceProviderByHandle((HANDLE
)s
,
514 WSASetLastError(WSAENOTSOCK
);
518 #if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
519 Status
= Provider
->ProcTable
.lpWSPBind(s
,
520 (CONST LPSOCKADDR
)name
,
524 Status
= Provider
->ProcTable
.lpWSPBind(s
,
528 #endif /* __W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5 */
530 DereferenceProviderByPointer(Provider
);
532 if (Status
== SOCKET_ERROR
)
533 WSASetLastError(Errno
);
547 PCATALOG_ENTRY Provider
;
553 WSASetLastError(WSANOTINITIALISED
);
557 if (!ReferenceProviderByHandle((HANDLE
)s
,
560 WSASetLastError(WSAENOTSOCK
);
564 Status
= Provider
->ProcTable
.lpWSPListen(s
,
568 DereferenceProviderByPointer(Provider
);
570 if (Status
== SOCKET_ERROR
)
571 WSASetLastError(Errno
);
584 OUT INT FAR
* addrlen
)
599 ioctlsocket(IN SOCKET s
,
601 IN OUT ULONG FAR
* argp
)
620 WSAAccept(IN SOCKET s
,
622 IN OUT LPINT addrlen
,
623 IN LPCONDITIONPROC lpfnCondition
,
624 IN DWORD dwCallbackData
)
626 PCATALOG_ENTRY Provider
;
632 WSASetLastError(WSANOTINITIALISED
);
636 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
638 WSASetLastError(WSAENOTSOCK
);
642 WS_DbgPrint(MAX_TRACE
,("Calling provider accept\n"));
644 Socket
= Provider
->ProcTable
.lpWSPAccept(s
,
651 WS_DbgPrint(MAX_TRACE
,("Calling provider accept -> Socket %x, Errno %x\n",
654 DereferenceProviderByPointer(Provider
);
656 if (Socket
== INVALID_SOCKET
)
657 WSASetLastError(Errno
);
662 LPSOCKADDR_IN sa
= (LPSOCKADDR_IN
)addr
;
663 WS_DbgPrint(MAX_TRACE
,("Returned address: %d %s:%d (len %d)\n",
665 inet_ntoa(sa
->sin_addr
),
681 IN CONST
struct sockaddr
*name
,
699 WSAConnect(IN SOCKET s
,
700 IN CONST
struct sockaddr
*name
,
702 IN LPWSABUF lpCallerData
,
703 OUT LPWSABUF lpCalleeData
,
707 PCATALOG_ENTRY Provider
;
713 WSASetLastError(WSANOTINITIALISED
);
717 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
719 WSASetLastError(WSAENOTSOCK
);
723 #if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
724 Status
= Provider
->ProcTable
.lpWSPConnect(s
,
725 (CONST LPSOCKADDR
)name
,
733 Status
= Provider
->ProcTable
.lpWSPConnect(s
,
743 DereferenceProviderByPointer(Provider
);
745 if (Status
== SOCKET_ERROR
)
746 WSASetLastError(Errno
);
757 WSAIoctl(IN SOCKET s
,
758 IN DWORD dwIoControlCode
,
759 IN LPVOID lpvInBuffer
,
761 OUT LPVOID lpvOutBuffer
,
762 IN DWORD cbOutBuffer
,
763 OUT LPDWORD lpcbBytesReturned
,
764 IN LPWSAOVERLAPPED lpOverlapped
,
765 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
767 PCATALOG_ENTRY Provider
;
773 WSASetLastError(WSANOTINITIALISED
);
777 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
779 WSASetLastError(WSAENOTSOCK
);
783 Status
= Provider
->ProcTable
.lpWSPIoctl(s
,
792 NULL
/* lpThreadId */,
795 DereferenceProviderByPointer(Provider
);
797 if (Status
== SOCKET_ERROR
)
798 WSASetLastError(Errno
);
808 __WSAFDIsSet(SOCKET s
, LPFD_SET set
)
812 for ( i
= 0; i
< set
->fd_count
; i
++ )
813 if ( set
->fd_array
[i
] == s
) return TRUE
;
818 void free_winsock_thread_block(PWINSOCK_THREAD_BLOCK p
)
822 if (p
->Hostent
) { free_hostent(p
->Hostent
); p
->Hostent
= 0; }
823 if (p
->Getservbyname
){}
824 if (p
->Getservbyport
) {}
830 DllMain(HANDLE hInstDll
,
834 PWINSOCK_THREAD_BLOCK p
;
836 WS_DbgPrint(MAX_TRACE
, ("DllMain of ws2_32.dll.\n"));
840 case DLL_PROCESS_ATTACH
:
842 GlobalHeap
= GetProcessHeap();
844 g_hInstDll
= hInstDll
;
848 InitProviderHandleTable();
850 UpcallTable
.lpWPUCloseEvent
= WPUCloseEvent
;
851 UpcallTable
.lpWPUCloseSocketHandle
= WPUCloseSocketHandle
;
852 UpcallTable
.lpWPUCreateEvent
= WPUCreateEvent
;
853 UpcallTable
.lpWPUCreateSocketHandle
= WPUCreateSocketHandle
;
854 UpcallTable
.lpWPUFDIsSet
= WPUFDIsSet
;
855 UpcallTable
.lpWPUGetProviderPath
= WPUGetProviderPath
;
856 UpcallTable
.lpWPUModifyIFSHandle
= WPUModifyIFSHandle
;
857 UpcallTable
.lpWPUPostMessage
= PostMessageW
;
858 UpcallTable
.lpWPUQueryBlockingCallback
= WPUQueryBlockingCallback
;
859 UpcallTable
.lpWPUQuerySocketHandleContext
= WPUQuerySocketHandleContext
;
860 UpcallTable
.lpWPUQueueApc
= WPUQueueApc
;
861 UpcallTable
.lpWPUResetEvent
= WPUResetEvent
;
862 UpcallTable
.lpWPUSetEvent
= WPUSetEvent
;
863 UpcallTable
.lpWPUOpenCurrentThread
= WPUOpenCurrentThread
;
864 UpcallTable
.lpWPUCloseThread
= WPUCloseThread
;
866 /* Fall through to thread attachment handler */
868 case DLL_THREAD_ATTACH
:
870 p
= HeapAlloc(GlobalHeap
, 0, sizeof(WINSOCK_THREAD_BLOCK
));
872 WS_DbgPrint(MAX_TRACE
, ("Thread block at 0x%X.\n", p
));
879 p
->LastErrorValue
= NO_ERROR
;
880 p
->Getservbyname
= NULL
;
881 p
->Getservbyport
= NULL
;
883 NtCurrentTeb()->WinSockData
= p
;
887 case DLL_PROCESS_DETACH
:
889 p
= NtCurrentTeb()->WinSockData
;
892 HeapFree(GlobalHeap
, 0, p
);
896 FreeProviderHandleTable();
900 case DLL_THREAD_DETACH
:
902 p
= NtCurrentTeb()->WinSockData
;
905 HeapFree(GlobalHeap
, 0, p
);
910 WS_DbgPrint(MAX_TRACE
, ("DllMain of ws2_32.dll. Leaving.\n"));