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;
293 WS_DbgPrint(MAX_TRACE, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n",
294 readfds, writefds, exceptfds));
296 if (!WSAINITIALIZED) {
297 WSASetLastError(WSANOTINITIALISED);
301 /* FIXME: Sockets in FD_SETs should be sorted by their provider */
303 /* FIXME: For now, assume only one service provider */
304 if ((readfds != NULL) && (readfds->fd_count > 0)) {
305 if (!ReferenceProviderByHandle((HANDLE)readfds->fd_array[0], &Provider)) {
306 WSASetLastError(WSAENOTSOCK);
309 } else if ((writefds != NULL) && (writefds->fd_count > 0)) {
310 if (!ReferenceProviderByHandle((HANDLE)writefds->fd_array[0], &Provider)) {
311 WSASetLastError(WSAENOTSOCK);
314 } else if ((exceptfds != NULL) && (exceptfds->fd_count > 0)) {
315 if (!ReferenceProviderByHandle((HANDLE)exceptfds->fd_array[0], &Provider)) {
316 WSASetLastError(WSAENOTSOCK);
320 WSASetLastError(WSAEINVAL);
324 Count = Provider->ProcTable.lpWSPSelect(
325 nfds, readfds, writefds, exceptfds, timeout, &Errno);
327 WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider));
329 DereferenceProviderByPointer(Provider);
331 if (Errno != NO_ERROR) {
332 WSASetLastError(Errno);
344 IN CONST LPSOCKADDR name,
347 PCATALOG_ENTRY Provider;
351 if (!WSAINITIALIZED) {
352 WSASetLastError(WSANOTINITIALISED);
356 if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
357 WSASetLastError(WSAENOTSOCK);
361 Status = Provider->ProcTable.lpWSPBind(
362 s, name, namelen, &Errno);
364 DereferenceProviderByPointer(Provider);
366 if (Status == SOCKET_ERROR) {
367 WSASetLastError(Errno);
380 PCATALOG_ENTRY Provider;
384 if (!WSAINITIALIZED) {
385 WSASetLastError(WSANOTINITIALISED);
389 if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
390 WSASetLastError(WSAENOTSOCK);
394 Status = Provider->ProcTable.lpWSPListen(
397 DereferenceProviderByPointer(Provider);
399 if (Status == SOCKET_ERROR) {
400 WSASetLastError(Errno);
412 OUT INT FAR* addrlen)
414 return WSAAccept(s, addr, addrlen, NULL, 0);
423 IN OUT LPINT addrlen,
424 IN LPCONDITIONPROC lpfnCondition,
425 IN DWORD dwCallbackData)
427 PCATALOG_ENTRY Provider;
431 if (!WSAINITIALIZED) {
432 WSASetLastError(WSANOTINITIALISED);
436 if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
437 WSASetLastError(WSAENOTSOCK);
441 Socket = Provider->ProcTable.lpWSPAccept(
442 s, addr, addrlen, lpfnCondition, dwCallbackData, &Errno);
444 DereferenceProviderByPointer(Provider);
446 if (Socket == INVALID_SOCKET) {
447 WSASetLastError(Errno);
458 IN CONST LPSOCKADDR name,
461 return WSAConnect(s, name, namelen, NULL, NULL, NULL, NULL);
469 IN CONST LPSOCKADDR name,
471 IN LPWSABUF lpCallerData,
472 OUT LPWSABUF lpCalleeData,
476 PCATALOG_ENTRY Provider;
480 if (!WSAINITIALIZED) {
481 WSASetLastError(WSANOTINITIALISED);
485 if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) {
486 WSASetLastError(WSAENOTSOCK);
490 Status = Provider->ProcTable.lpWSPConnect(
491 s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, &Errno);
493 DereferenceProviderByPointer(Provider);
495 if (Status == SOCKET_ERROR) {
496 WSASetLastError(Errno);
505 DllMain(HANDLE hInstDll,
509 PWINSOCK_THREAD_BLOCK p;
511 WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll.\n"));
514 case DLL_PROCESS_ATTACH:
515 GlobalHeap = GetProcessHeap();
519 InitProviderHandleTable();
521 UpcallTable.lpWPUCloseEvent = WPUCloseEvent;
522 UpcallTable.lpWPUCloseSocketHandle = WPUCloseSocketHandle;
523 UpcallTable.lpWPUCreateEvent = WPUCreateEvent;
524 UpcallTable.lpWPUCreateSocketHandle = WPUCreateSocketHandle;
525 UpcallTable.lpWPUFDIsSet = WPUFDIsSet;
526 UpcallTable.lpWPUGetProviderPath = WPUGetProviderPath;
527 UpcallTable.lpWPUModifyIFSHandle = WPUModifyIFSHandle;
528 UpcallTable.lpWPUPostMessage = WPUPostMessage;
529 UpcallTable.lpWPUQueryBlockingCallback = WPUQueryBlockingCallback;
530 UpcallTable.lpWPUQuerySocketHandleContext = WPUQuerySocketHandleContext;
531 UpcallTable.lpWPUQueueApc = WPUQueueApc;
532 UpcallTable.lpWPUResetEvent = WPUResetEvent;
533 UpcallTable.lpWPUSetEvent = WPUSetEvent;
534 UpcallTable.lpWPUOpenCurrentThread = WPUOpenCurrentThread;
535 UpcallTable.lpWPUCloseThread = WPUCloseThread;
537 /* Fall through to thread attachment handler */
539 case DLL_THREAD_ATTACH:
540 p = HeapAlloc(GlobalHeap, 0, sizeof(WINSOCK_THREAD_BLOCK));
542 WS_DbgPrint(MAX_TRACE, ("Thread block at 0x%X.\n", p));
548 p->LastErrorValue = NO_ERROR;
549 p->Initialized = FALSE;
551 NtCurrentTeb()->WinSockData = p;
554 case DLL_PROCESS_DETACH:
555 p = NtCurrentTeb()->WinSockData;
558 HeapFree(GlobalHeap, 0, p);
562 FreeProviderHandleTable();
565 case DLL_THREAD_DETACH:
566 p = NtCurrentTeb()->WinSockData;
569 HeapFree(GlobalHeap, 0, p);
573 WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll. Leaving.\n"));