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
17 /* See debug.h for debug/trace constants */
18 DWORD DebugTraceLevel
= MIN_TRACE
;
19 //DWORD DebugTraceLevel = MAX_TRACE;
23 /* To make the linker happy */
24 VOID STDCALL
KeBugCheck (ULONG BugCheckCode
) {}
28 WSPUPCALLTABLE UpcallTable
;
35 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
38 return p
->LastErrorValue
;
40 /* FIXME: What error code should we use here? Can this even happen? */
41 return ERROR_BAD_ENVIRONMENT
;
51 PWINSOCK_THREAD_BLOCK p
= NtCurrentTeb()->WinSockData
;
54 p
->LastErrorValue
= iError
;
61 IN WORD wVersionRequested
,
62 OUT LPWSADATA lpWSAData
)
64 WS_DbgPrint(MAX_TRACE
, ("WSAStartup of ws2_32.dll\n"));
66 lpWSAData
->wVersion
= wVersionRequested
;
67 lpWSAData
->wHighVersion
= 2;
68 lstrcpyA(lpWSAData
->szDescription
, "WinSock 2.0");
69 lstrcpyA(lpWSAData
->szSystemStatus
, "Running");
70 lpWSAData
->iMaxSockets
= 0;
71 lpWSAData
->iMaxUdpDg
= 0;
72 lpWSAData
->lpVendorInfo
= NULL
;
84 WS_DbgPrint(MAX_TRACE
, ("WSACleanup of ws2_32.dll\n"));
86 if (!WSAINITIALIZED
) {
87 WSASetLastError(WSANOTINITIALISED
);
88 return WSANOTINITIALISED
;
101 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
105 * FUNCTION: Creates a new socket
108 WSAPROTOCOL_INFOW ProtocolInfoW
;
109 LPWSAPROTOCOL_INFOW p
;
110 UNICODE_STRING StringU
;
113 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d).\n",
114 af
, type
, protocol
));
116 if (lpProtocolInfo
) {
117 memcpy(&ProtocolInfoW
,
119 sizeof(WSAPROTOCOL_INFOA
) -
120 sizeof(CHAR
) * (WSAPROTOCOL_LEN
+ 1));
121 RtlInitAnsiString(&StringA
, (LPSTR
)lpProtocolInfo
->szProtocol
);
122 RtlInitUnicodeString(&StringU
, (LPWSTR
)&ProtocolInfoW
.szProtocol
);
123 RtlAnsiStringToUnicodeString(&StringU
, &StringA
, FALSE
);
129 return WSASocketW(af
,
144 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
148 * FUNCTION: Creates a new socket descriptor
150 * af = Address family
152 * protocol = Protocol type
153 * lpProtocolInfo = Pointer to protocol information
155 * dwFlags = Socket flags
157 * Created socket descriptor, or INVALID_SOCKET if it could not be created
162 PCATALOG_ENTRY Provider
;
163 WSAPROTOCOL_INFOW ProtocolInfo
;
165 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d).\n",
166 af
, type
, protocol
));
168 if (!WSAINITIALIZED
) {
169 WSASetLastError(WSANOTINITIALISED
);
170 return INVALID_SOCKET
;
173 if (!lpProtocolInfo
) {
174 lpProtocolInfo
= &ProtocolInfo
;
175 ZeroMemory(&ProtocolInfo
, sizeof(WSAPROTOCOL_INFOW
));
177 ProtocolInfo
.iAddressFamily
= af
;
178 ProtocolInfo
.iSocketType
= type
;
179 ProtocolInfo
.iProtocol
= protocol
;
182 Provider
= LocateProvider(lpProtocolInfo
);
184 WSASetLastError(WSAEAFNOSUPPORT
);
185 return INVALID_SOCKET
;
188 Status
= LoadProvider(Provider
, lpProtocolInfo
);
189 if (Status
!= NO_ERROR
) {
190 WSASetLastError(Status
);
191 return INVALID_SOCKET
;
194 WS_DbgPrint(MAX_TRACE
, ("Calling WSPSocket at (0x%X).\n",
195 Provider
->ProcTable
.lpWSPSocket
));
197 assert(Provider
->ProcTable
.lpWSPSocket
);
199 Socket
= Provider
->ProcTable
.lpWSPSocket(
207 if (Status
!= NO_ERROR
) {
208 WSASetLastError(Status
);
209 return INVALID_SOCKET
;
221 * FUNCTION: Closes a socket descriptor
223 * s = Socket descriptor
225 * 0, or SOCKET_ERROR if an error ocurred
228 PCATALOG_ENTRY Provider
;
232 WS_DbgPrint(MAX_TRACE
, ("s (0x%X).\n", s
));
234 if (!WSAINITIALIZED
) {
235 WSASetLastError(WSANOTINITIALISED
);
239 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
)) {
240 WSASetLastError(WSAENOTSOCK
);
244 CloseProviderHandle((HANDLE
)s
);
246 DereferenceProviderByPointer(Provider
);
248 Code
= Provider
->ProcTable
.lpWSPCloseSocket(s
, &Errno
);
249 if (Code
== SOCKET_ERROR
)
250 WSASetLastError(Errno
);
260 IN OUT LPFD_SET readfds
,
261 IN OUT LPFD_SET writefds
,
262 IN OUT LPFD_SET exceptfds
,
263 IN CONST LPTIMEVAL timeout
)
265 * FUNCTION: Returns status of one or more sockets
267 * nfds = Always ignored
268 * readfds = Pointer to socket set to be checked for readability (optional)
269 * writefds = Pointer to socket set to be checked for writability (optional)
270 * exceptfds = Pointer to socket set to be checked for errors (optional)
271 * timeout = Pointer to a TIMEVAL structure indicating maximum wait time
272 * (NULL means wait forever)
274 * Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred
277 PCATALOG_ENTRY Provider
;
282 WS_DbgPrint(MAX_TRACE
, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n",
283 readfds
, writefds
, exceptfds
));
285 if (!WSAINITIALIZED
) {
286 WSASetLastError(WSANOTINITIALISED
);
290 /* FIXME: Sockets in FD_SETs should be sorted by their provider */
292 /* FIXME: For now, assume only one service provider */
293 if ((readfds
!= NULL
) && (readfds
->fd_count
> 0)) {
294 if (!ReferenceProviderByHandle((HANDLE
)readfds
->fd_array
[0], &Provider
)) {
295 WSASetLastError(WSAENOTSOCK
);
298 } else if ((writefds
!= NULL
) && (writefds
->fd_count
> 0)) {
299 if (!ReferenceProviderByHandle((HANDLE
)writefds
->fd_array
[0], &Provider
)) {
300 WSASetLastError(WSAENOTSOCK
);
303 } else if ((exceptfds
!= NULL
) && (exceptfds
->fd_count
> 0)) {
304 if (!ReferenceProviderByHandle((HANDLE
)exceptfds
->fd_array
[0], &Provider
)) {
305 WSASetLastError(WSAENOTSOCK
);
309 WSASetLastError(WSAEINVAL
);
313 Count
= Provider
->ProcTable
.lpWSPSelect(
314 nfds
, readfds
, writefds
, exceptfds
, timeout
, &Errno
);
316 WS_DbgPrint(MAX_TRACE
, ("Provider (0x%X).\n", Provider
));
318 DereferenceProviderByPointer(Provider
);
320 WSASetLastError(Errno
);
322 if (Errno
!= NO_ERROR
)
331 DllMain(HANDLE hInstDll
,
335 PWINSOCK_THREAD_BLOCK p
;
337 WS_DbgPrint(MAX_TRACE
, ("DllMain of ws2_32.dll.\n"));
340 case DLL_PROCESS_ATTACH
:
341 GlobalHeap
= GetProcessHeap();
345 InitProviderHandleTable();
347 UpcallTable
.lpWPUCloseEvent
= WPUCloseEvent
;
348 UpcallTable
.lpWPUCloseSocketHandle
= WPUCloseSocketHandle
;
349 UpcallTable
.lpWPUCreateEvent
= WPUCreateEvent
;
350 UpcallTable
.lpWPUCreateSocketHandle
= WPUCreateSocketHandle
;
351 UpcallTable
.lpWPUFDIsSet
= WPUFDIsSet
;
352 UpcallTable
.lpWPUGetProviderPath
= WPUGetProviderPath
;
353 UpcallTable
.lpWPUModifyIFSHandle
= WPUModifyIFSHandle
;
354 UpcallTable
.lpWPUPostMessage
= WPUPostMessage
;
355 UpcallTable
.lpWPUQueryBlockingCallback
= WPUQueryBlockingCallback
;
356 UpcallTable
.lpWPUQuerySocketHandleContext
= WPUQuerySocketHandleContext
;
357 UpcallTable
.lpWPUQueueApc
= WPUQueueApc
;
358 UpcallTable
.lpWPUResetEvent
= WPUResetEvent
;
359 UpcallTable
.lpWPUSetEvent
= WPUSetEvent
;
360 UpcallTable
.lpWPUOpenCurrentThread
= WPUOpenCurrentThread
;
361 UpcallTable
.lpWPUCloseThread
= WPUCloseThread
;
363 /* Fall through to thread attachment handler */
365 case DLL_THREAD_ATTACH
:
366 p
= HeapAlloc(GlobalHeap
, 0, sizeof(WINSOCK_THREAD_BLOCK
));
368 WS_DbgPrint(MAX_TRACE
, ("Thread block at 0x%X.\n", p
));
374 p
->LastErrorValue
= NO_ERROR
;
375 p
->Initialized
= FALSE
;
377 NtCurrentTeb()->WinSockData
= p
;
380 case DLL_PROCESS_DETACH
:
381 p
= NtCurrentTeb()->WinSockData
;
384 HeapFree(GlobalHeap
, 0, p
);
388 FreeProviderHandleTable();
391 case DLL_THREAD_DETACH
:
392 p
= NtCurrentTeb()->WinSockData
;
395 HeapFree(GlobalHeap
, 0, p
);