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 = DEBUG_ULTRA;
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;
102 return WSASocketA(af, type, protocol, NULL, 0, 0);
112 IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
116 * FUNCTION: Creates a new socket
119 WSAPROTOCOL_INFOW ProtocolInfoW;
120 LPWSAPROTOCOL_INFOW p;
121 UNICODE_STRING StringU;
124 WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n",
125 af, type, protocol));
127 if (lpProtocolInfo) {
128 memcpy(&ProtocolInfoW,
130 sizeof(WSAPROTOCOL_INFOA) -
131 sizeof(CHAR) * (WSAPROTOCOL_LEN + 1));
132 RtlInitAnsiString(&StringA, (LPSTR)lpProtocolInfo->szProtocol);
133 RtlInitUnicodeString(&StringU, (LPWSTR)&ProtocolInfoW.szProtocol);
134 RtlAnsiStringToUnicodeString(&StringU, &StringA, FALSE);
140 return WSASocketW(af,
155 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
159 * FUNCTION: Creates a new socket descriptor
161 * af = Address family
163 * protocol = Protocol type
164 * lpProtocolInfo = Pointer to protocol information
166 * dwFlags = Socket flags
168 * Created socket descriptor, or INVALID_SOCKET if it could not be created
173 PCATALOG_ENTRY Provider;
174 WSAPROTOCOL_INFOW ProtocolInfo;
176 WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n",
177 af, type, protocol));
179 if (!WSAINITIALIZED) {
180 WSASetLastError(WSANOTINITIALISED);
181 return INVALID_SOCKET;
184 if (!lpProtocolInfo) {
185 lpProtocolInfo = &ProtocolInfo;
186 ZeroMemory(&ProtocolInfo, sizeof(WSAPROTOCOL_INFOW));
188 ProtocolInfo.iAddressFamily = af;
189 ProtocolInfo.iSocketType = type;
190 ProtocolInfo.iProtocol = protocol;
193 Provider = LocateProvider(lpProtocolInfo);
195 WSASetLastError(WSAEAFNOSUPPORT);
196 return INVALID_SOCKET;
199 Status = LoadProvider(Provider, lpProtocolInfo);
200 if (Status != NO_ERROR) {
201 WSASetLastError(Status);
202 return INVALID_SOCKET;
205 WS_DbgPrint(MAX_TRACE, ("Calling WSPSocket at (0x%X).\n",
206 Provider->ProcTable.lpWSPSocket));
208 assert(Provider->ProcTable.lpWSPSocket);
210 Socket = Provider->ProcTable.lpWSPSocket(
218 if (Status != NO_ERROR) {
219 WSASetLastError(Status);
220 return INVALID_SOCKET;
232 * FUNCTION: Closes a socket descriptor
234 * s = Socket descriptor
236 * 0, or SOCKET_ERROR if an error ocurred
239 PCATALOG_ENTRY Provider;
243 WS_DbgPrint(MAX_TRACE, ("s (0x%X).\n", s));
245 if (!WSAINITIALIZED) {
246 WSASetLastError(WSANOTINITIALISED);
250 if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
251 WSASetLastError(WSAENOTSOCK);
255 CloseProviderHandle((HANDLE)s);
257 DereferenceProviderByPointer(Provider);
259 Status = Provider->ProcTable.lpWSPCloseSocket(s, &Errno);
260 if (Status == SOCKET_ERROR)
261 WSASetLastError(Errno);
271 IN OUT LPFD_SET readfds,
272 IN OUT LPFD_SET writefds,
273 IN OUT LPFD_SET exceptfds,
274 IN CONST LPTIMEVAL timeout)
276 * FUNCTION: Returns status of one or more sockets
278 * nfds = Always ignored
279 * readfds = Pointer to socket set to be checked for readability (optional)
280 * writefds = Pointer to socket set to be checked for writability (optional)
281 * exceptfds = Pointer to socket set to be checked for errors (optional)
282 * timeout = Pointer to a TIMEVAL structure indicating maximum wait time
283 * (NULL means wait forever)
285 * Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred
288 PCATALOG_ENTRY Provider;
292 WS_DbgPrint(MAX_TRACE, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n",
293 readfds, writefds, exceptfds));
295 if (!WSAINITIALIZED) {
296 WSASetLastError(WSANOTINITIALISED);
300 /* FIXME: Sockets in FD_SETs should be sorted by their provider */
302 /* FIXME: For now, assume only one service provider */
303 if ((readfds != NULL) && (readfds->fd_count > 0)) {
304 if (!ReferenceProviderByHandle((HANDLE)readfds->fd_array[0], &Provider)) {
305 WSASetLastError(WSAENOTSOCK);
308 } else if ((writefds != NULL) && (writefds->fd_count > 0)) {
309 if (!ReferenceProviderByHandle((HANDLE)writefds->fd_array[0], &Provider)) {
310 WSASetLastError(WSAENOTSOCK);
313 } else if ((exceptfds != NULL) && (exceptfds->fd_count > 0)) {
314 if (!ReferenceProviderByHandle((HANDLE)exceptfds->fd_array[0], &Provider)) {
315 WSASetLastError(WSAENOTSOCK);
319 WSASetLastError(WSAEINVAL);
323 Count = Provider->ProcTable.lpWSPSelect(
324 nfds, readfds, writefds, exceptfds, timeout, &Errno);
326 WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider));
328 DereferenceProviderByPointer(Provider);
330 if (Errno != NO_ERROR) {
331 WSASetLastError(Errno);
343 IN CONST LPSOCKADDR name,
346 PCATALOG_ENTRY Provider;
350 if (!WSAINITIALIZED) {
351 WSASetLastError(WSANOTINITIALISED);
355 if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
356 WSASetLastError(WSAENOTSOCK);
360 Status = Provider->ProcTable.lpWSPBind(
361 s, name, namelen, &Errno);
363 DereferenceProviderByPointer(Provider);
365 if (Status == SOCKET_ERROR) {
366 WSASetLastError(Errno);
379 PCATALOG_ENTRY Provider;
383 if (!WSAINITIALIZED) {
384 WSASetLastError(WSANOTINITIALISED);
388 if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
389 WSASetLastError(WSAENOTSOCK);
393 Status = Provider->ProcTable.lpWSPListen(
396 DereferenceProviderByPointer(Provider);
398 if (Status == SOCKET_ERROR) {
399 WSASetLastError(Errno);
411 OUT INT FAR* addrlen)
413 return WSAAccept(s, addr, addrlen, NULL, 0);
422 IN OUT LPINT addrlen,
423 IN LPCONDITIONPROC lpfnCondition,
424 IN DWORD dwCallbackData)
426 PCATALOG_ENTRY Provider;
430 if (!WSAINITIALIZED) {
431 WSASetLastError(WSANOTINITIALISED);
435 if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
436 WSASetLastError(WSAENOTSOCK);
440 Socket = Provider->ProcTable.lpWSPAccept(
441 s, addr, addrlen, lpfnCondition, dwCallbackData, &Errno);
443 DereferenceProviderByPointer(Provider);
445 if (Socket == INVALID_SOCKET) {
446 WSASetLastError(Errno);
457 IN CONST LPSOCKADDR name,
460 return WSAConnect(s, name, namelen, NULL, NULL, NULL, NULL);
468 IN CONST LPSOCKADDR name,
470 IN LPWSABUF lpCallerData,
471 OUT LPWSABUF lpCalleeData,
475 PCATALOG_ENTRY Provider;
479 if (!WSAINITIALIZED) {
480 WSASetLastError(WSANOTINITIALISED);
484 if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
485 WSASetLastError(WSAENOTSOCK);
489 Status = Provider->ProcTable.lpWSPConnect(
490 s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, &Errno);
492 DereferenceProviderByPointer(Provider);
494 if (Status == SOCKET_ERROR) {
495 WSASetLastError(Errno);
504 DllMain(HANDLE hInstDll,
508 PWINSOCK_THREAD_BLOCK p;
510 WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll.\n"));
513 case DLL_PROCESS_ATTACH:
514 GlobalHeap = GetProcessHeap();
518 InitProviderHandleTable();
520 UpcallTable.lpWPUCloseEvent = WPUCloseEvent;
521 UpcallTable.lpWPUCloseSocketHandle = WPUCloseSocketHandle;
522 UpcallTable.lpWPUCreateEvent = WPUCreateEvent;
523 UpcallTable.lpWPUCreateSocketHandle = WPUCreateSocketHandle;
524 UpcallTable.lpWPUFDIsSet = WPUFDIsSet;
525 UpcallTable.lpWPUGetProviderPath = WPUGetProviderPath;
526 UpcallTable.lpWPUModifyIFSHandle = WPUModifyIFSHandle;
527 UpcallTable.lpWPUPostMessage = WPUPostMessage;
528 UpcallTable.lpWPUQueryBlockingCallback = WPUQueryBlockingCallback;
529 UpcallTable.lpWPUQuerySocketHandleContext = WPUQuerySocketHandleContext;
530 UpcallTable.lpWPUQueueApc = WPUQueueApc;
531 UpcallTable.lpWPUResetEvent = WPUResetEvent;
532 UpcallTable.lpWPUSetEvent = WPUSetEvent;
533 UpcallTable.lpWPUOpenCurrentThread = WPUOpenCurrentThread;
534 UpcallTable.lpWPUCloseThread = WPUCloseThread;
536 /* Fall through to thread attachment handler */
538 case DLL_THREAD_ATTACH:
539 p = HeapAlloc(GlobalHeap, 0, sizeof(WINSOCK_THREAD_BLOCK));
541 WS_DbgPrint(MAX_TRACE, ("Thread block at 0x%X.\n", p));
547 p->LastErrorValue = NO_ERROR;
548 p->Initialized = FALSE;
550 NtCurrentTeb()->WinSockData = p;
553 case DLL_PROCESS_DETACH:
554 p = NtCurrentTeb()->WinSockData;
557 HeapFree(GlobalHeap, 0, p);
561 FreeProviderHandleTable();
564 case DLL_THREAD_DETACH:
565 p = NtCurrentTeb()->WinSockData;
568 HeapFree(GlobalHeap, 0, p);
572 WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll. Leaving.\n"));