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;
38 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
41 return p->LastErrorValue;
43 /* FIXME: What error code should we use here? Can this even happen? */
44 return ERROR_BAD_ENVIRONMENT;
57 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
60 p->LastErrorValue = iError;
70 IN WORD wVersionRequested,
71 OUT LPWSADATA lpWSAData)
73 WS_DbgPrint(MAX_TRACE, ("WSAStartup of ws2_32.dll\n"));
75 lpWSAData->wVersion = wVersionRequested;
76 lpWSAData->wHighVersion = 2;
77 lstrcpyA(lpWSAData->szDescription, "WinSock 2.0");
78 lstrcpyA(lpWSAData->szSystemStatus, "Running");
79 lpWSAData->iMaxSockets = 0;
80 lpWSAData->iMaxUdpDg = 0;
81 lpWSAData->lpVendorInfo = NULL;
96 WS_DbgPrint(MAX_TRACE, ("WSACleanup of ws2_32.dll\n"));
98 if (!WSAINITIALIZED) {
99 WSASetLastError(WSANOTINITIALISED);
100 return WSANOTINITIALISED;
117 return WSASocketA(af, type, protocol, NULL, 0, 0);
130 IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
134 * FUNCTION: Creates a new socket
137 WSAPROTOCOL_INFOW ProtocolInfoW;
138 LPWSAPROTOCOL_INFOW p;
139 UNICODE_STRING StringU;
142 WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n",
143 af, type, protocol));
145 if (lpProtocolInfo) {
146 memcpy(&ProtocolInfoW,
148 sizeof(WSAPROTOCOL_INFOA) -
149 sizeof(CHAR) * (WSAPROTOCOL_LEN + 1));
150 RtlInitAnsiString(&StringA, (LPSTR)lpProtocolInfo->szProtocol);
151 RtlInitUnicodeString(&StringU, (LPWSTR)&ProtocolInfoW.szProtocol);
152 RtlAnsiStringToUnicodeString(&StringU, &StringA, FALSE);
158 return WSASocketW(af,
176 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
180 * FUNCTION: Creates a new socket descriptor
182 * af = Address family
184 * protocol = Protocol type
185 * lpProtocolInfo = Pointer to protocol information
187 * dwFlags = Socket flags
189 * Created socket descriptor, or INVALID_SOCKET if it could not be created
194 PCATALOG_ENTRY Provider;
195 WSAPROTOCOL_INFOW ProtocolInfo;
197 WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n",
198 af, type, protocol));
200 if (!WSAINITIALIZED) {
201 WSASetLastError(WSANOTINITIALISED);
202 return INVALID_SOCKET;
205 if (!lpProtocolInfo) {
206 lpProtocolInfo = &ProtocolInfo;
207 ZeroMemory(&ProtocolInfo, sizeof(WSAPROTOCOL_INFOW));
209 ProtocolInfo.iAddressFamily = af;
210 ProtocolInfo.iSocketType = type;
211 ProtocolInfo.iProtocol = protocol;
214 Provider = LocateProvider(lpProtocolInfo);
216 WSASetLastError(WSAEAFNOSUPPORT);
217 return INVALID_SOCKET;
220 Status = LoadProvider(Provider, lpProtocolInfo);
221 if (Status != NO_ERROR) {
222 WSASetLastError(Status);
223 return INVALID_SOCKET;
226 WS_DbgPrint(MAX_TRACE, ("Calling WSPSocket at (0x%X).\n",
227 Provider->ProcTable.lpWSPSocket));
229 assert(Provider->ProcTable.lpWSPSocket);
231 Socket = Provider->ProcTable.lpWSPSocket(
239 if (Status != NO_ERROR) {
240 WSASetLastError(Status);
241 return INVALID_SOCKET;
256 * FUNCTION: Closes a socket descriptor
258 * s = Socket descriptor
260 * 0, or SOCKET_ERROR if an error ocurred
263 PCATALOG_ENTRY Provider;
267 WS_DbgPrint(MAX_TRACE, ("s (0x%X).\n", s));
269 if (!WSAINITIALIZED) {
270 WSASetLastError(WSANOTINITIALISED);
274 if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
275 WSASetLastError(WSAENOTSOCK);
279 CloseProviderHandle((HANDLE)s);
281 DereferenceProviderByPointer(Provider);
283 Status = Provider->ProcTable.lpWSPCloseSocket(s, &Errno);
284 if (Status == SOCKET_ERROR)
285 WSASetLastError(Errno);
298 IN OUT LPFD_SET readfds,
299 IN OUT LPFD_SET writefds,
300 IN OUT LPFD_SET exceptfds,
301 IN CONST LPTIMEVAL timeout)
303 * FUNCTION: Returns status of one or more sockets
305 * nfds = Always ignored
306 * readfds = Pointer to socket set to be checked for readability (optional)
307 * writefds = Pointer to socket set to be checked for writability (optional)
308 * exceptfds = Pointer to socket set to be checked for errors (optional)
309 * timeout = Pointer to a TIMEVAL structure indicating maximum wait time
310 * (NULL means wait forever)
312 * Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred
315 PCATALOG_ENTRY Provider;
319 WS_DbgPrint(MAX_TRACE, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n",
320 readfds, writefds, exceptfds));
322 if (!WSAINITIALIZED) {
323 WSASetLastError(WSANOTINITIALISED);
327 /* FIXME: Sockets in FD_SETs should be sorted by their provider */
329 /* FIXME: For now, assume only one service provider */
330 if ((readfds != NULL) && (readfds->fd_count > 0)) {
331 if (!ReferenceProviderByHandle((HANDLE)readfds->fd_array[0], &Provider)) {
332 WSASetLastError(WSAENOTSOCK);
335 } else if ((writefds != NULL) && (writefds->fd_count > 0)) {
336 if (!ReferenceProviderByHandle((HANDLE)writefds->fd_array[0], &Provider)) {
337 WSASetLastError(WSAENOTSOCK);
340 } else if ((exceptfds != NULL) && (exceptfds->fd_count > 0)) {
341 if (!ReferenceProviderByHandle((HANDLE)exceptfds->fd_array[0], &Provider)) {
342 WSASetLastError(WSAENOTSOCK);
346 WSASetLastError(WSAEINVAL);
350 Count = Provider->ProcTable.lpWSPSelect(
351 nfds, readfds, writefds, exceptfds, timeout, &Errno);
353 WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider));
355 DereferenceProviderByPointer(Provider);
357 if (Errno != NO_ERROR) {
358 WSASetLastError(Errno);
373 IN CONST LPSOCKADDR name,
376 PCATALOG_ENTRY Provider;
380 if (!WSAINITIALIZED) {
381 WSASetLastError(WSANOTINITIALISED);
385 if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
386 WSASetLastError(WSAENOTSOCK);
390 Status = Provider->ProcTable.lpWSPBind(
391 s, name, namelen, &Errno);
393 DereferenceProviderByPointer(Provider);
395 if (Status == SOCKET_ERROR) {
396 WSASetLastError(Errno);
412 PCATALOG_ENTRY Provider;
416 if (!WSAINITIALIZED) {
417 WSASetLastError(WSANOTINITIALISED);
421 if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
422 WSASetLastError(WSAENOTSOCK);
426 Status = Provider->ProcTable.lpWSPListen(
429 DereferenceProviderByPointer(Provider);
431 if (Status == SOCKET_ERROR) {
432 WSASetLastError(Errno);
447 OUT INT FAR* addrlen)
449 return WSAAccept(s, addr, addrlen, NULL, 0);
461 IN OUT LPINT addrlen,
462 IN LPCONDITIONPROC lpfnCondition,
463 IN DWORD dwCallbackData)
465 PCATALOG_ENTRY Provider;
469 if (!WSAINITIALIZED) {
470 WSASetLastError(WSANOTINITIALISED);
474 if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
475 WSASetLastError(WSAENOTSOCK);
479 Socket = Provider->ProcTable.lpWSPAccept(
480 s, addr, addrlen, lpfnCondition, dwCallbackData, &Errno);
482 DereferenceProviderByPointer(Provider);
484 if (Socket == INVALID_SOCKET) {
485 WSASetLastError(Errno);
499 IN CONST LPSOCKADDR name,
502 return WSAConnect(s, name, namelen, NULL, NULL, NULL, NULL);
513 IN CONST LPSOCKADDR name,
515 IN LPWSABUF lpCallerData,
516 OUT LPWSABUF lpCalleeData,
520 PCATALOG_ENTRY Provider;
524 if (!WSAINITIALIZED) {
525 WSASetLastError(WSANOTINITIALISED);
529 if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
530 WSASetLastError(WSAENOTSOCK);
534 Status = Provider->ProcTable.lpWSPConnect(
535 s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, &Errno);
537 DereferenceProviderByPointer(Provider);
539 if (Status == SOCKET_ERROR) {
540 WSASetLastError(Errno);
549 DllMain(HANDLE hInstDll,
553 PWINSOCK_THREAD_BLOCK p;
555 WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll.\n"));
558 case DLL_PROCESS_ATTACH:
559 GlobalHeap = GetProcessHeap();
563 InitProviderHandleTable();
565 UpcallTable.lpWPUCloseEvent = WPUCloseEvent;
566 UpcallTable.lpWPUCloseSocketHandle = WPUCloseSocketHandle;
567 UpcallTable.lpWPUCreateEvent = WPUCreateEvent;
568 UpcallTable.lpWPUCreateSocketHandle = WPUCreateSocketHandle;
569 UpcallTable.lpWPUFDIsSet = WPUFDIsSet;
570 UpcallTable.lpWPUGetProviderPath = WPUGetProviderPath;
571 UpcallTable.lpWPUModifyIFSHandle = WPUModifyIFSHandle;
572 UpcallTable.lpWPUPostMessage = WPUPostMessage;
573 UpcallTable.lpWPUQueryBlockingCallback = WPUQueryBlockingCallback;
574 UpcallTable.lpWPUQuerySocketHandleContext = WPUQuerySocketHandleContext;
575 UpcallTable.lpWPUQueueApc = WPUQueueApc;
576 UpcallTable.lpWPUResetEvent = WPUResetEvent;
577 UpcallTable.lpWPUSetEvent = WPUSetEvent;
578 UpcallTable.lpWPUOpenCurrentThread = WPUOpenCurrentThread;
579 UpcallTable.lpWPUCloseThread = WPUCloseThread;
581 /* Fall through to thread attachment handler */
583 case DLL_THREAD_ATTACH:
584 p = HeapAlloc(GlobalHeap, 0, sizeof(WINSOCK_THREAD_BLOCK));
586 WS_DbgPrint(MAX_TRACE, ("Thread block at 0x%X.\n", p));
592 p->LastErrorValue = NO_ERROR;
593 p->Initialized = FALSE;
595 NtCurrentTeb()->WinSockData = p;
598 case DLL_PROCESS_DETACH:
599 p = NtCurrentTeb()->WinSockData;
602 HeapFree(GlobalHeap, 0, p);
606 FreeProviderHandleTable();
609 case DLL_THREAD_DETACH:
610 p = NtCurrentTeb()->WinSockData;
613 HeapFree(GlobalHeap, 0, p);
617 WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll. Leaving.\n"));