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
19 /* See debug.h for debug/trace constants */
20 //DWORD DebugTraceLevel = MIN_TRACE;
21 //DWORD DebugTraceLevel = MAX_TRACE;
22 //DWORD DebugTraceLevel = DEBUG_ULTRA;
23 DWORD DebugTraceLevel
= 0;
26 /* To make the linker happy */
27 VOID WINAPI
KeBugCheck (ULONG BugCheckCode
) {}
31 BOOL WsaInitialized
= FALSE
; /* TRUE if WSAStartup() has been successfully called */
32 WSPUPCALLTABLE UpcallTable
;
42 return GetLastError();
51 WSASetLastError(IN INT iError
)
62 WSAStartup(IN WORD wVersionRequested
,
63 OUT LPWSADATA lpWSAData
)
67 WS_DbgPrint(MAX_TRACE
, ("WSAStartup of ws2_32.dll\n"));
70 return WSASYSNOTREADY
;
72 if (lpWSAData
== NULL
)
75 Low
= LOBYTE(wVersionRequested
);
76 High
= HIBYTE(wVersionRequested
);
80 WS_DbgPrint(MAX_TRACE
, ("Bad winsock version requested, %d,%d", Low
, High
));
81 return WSAVERNOTSUPPORTED
;
88 lpWSAData
->wVersion
= wVersionRequested
;
92 lpWSAData
->wVersion
= MAKEWORD(1, 1);
99 lpWSAData
->wVersion
= MAKEWORD(2, High
);
103 lpWSAData
->wVersion
= MAKEWORD(2, 2);
108 lpWSAData
->wVersion
= MAKEWORD(2, 2);
111 lpWSAData
->wVersion
= wVersionRequested
;
112 lpWSAData
->wHighVersion
= MAKEWORD(2,2);
113 lstrcpyA(lpWSAData
->szDescription
, "WinSock 2.2");
114 lstrcpyA(lpWSAData
->szSystemStatus
, "Running");
115 lpWSAData
->iMaxSockets
= 0;
116 lpWSAData
->iMaxUdpDg
= 0;
117 lpWSAData
->lpVendorInfo
= NULL
;
119 /*FIXME: increment internal counter */
134 WS_DbgPrint(MAX_TRACE
, ("WSACleanup of ws2_32.dll\n"));
138 WSASetLastError(WSANOTINITIALISED
);
139 return WSANOTINITIALISED
;
155 return WSASocketW(af
,
169 WSASocketA(IN INT af
,
172 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
176 * FUNCTION: Creates a new socket
179 WSAPROTOCOL_INFOW ProtocolInfoW
;
180 LPWSAPROTOCOL_INFOW p
;
181 UNICODE_STRING StringU
;
184 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d).\n",
185 af
, type
, protocol
));
189 memcpy(&ProtocolInfoW
,
191 sizeof(WSAPROTOCOL_INFOA
) - sizeof(CHAR
) * (WSAPROTOCOL_LEN
+ 1));
192 RtlInitAnsiString(&StringA
, (LPSTR
)lpProtocolInfo
->szProtocol
);
193 RtlInitUnicodeString(&StringU
, (LPWSTR
)&ProtocolInfoW
.szProtocol
);
194 RtlAnsiStringToUnicodeString(&StringU
, &StringA
, FALSE
);
202 return WSASocketW(af
,
216 WSASocketW(IN INT af
,
219 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
223 * FUNCTION: Creates a new socket descriptor
225 * af = Address family
227 * protocol = Protocol type
228 * lpProtocolInfo = Pointer to protocol information
230 * dwFlags = Socket flags
232 * Created socket descriptor, or INVALID_SOCKET if it could not be created
237 PCATALOG_ENTRY Provider
;
238 WSAPROTOCOL_INFOW ProtocolInfo
;
240 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d).\n",
241 af
, type
, protocol
));
245 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d) = WSANOTINITIALISED.\n",
246 af
, type
, protocol
));
247 WSASetLastError(WSANOTINITIALISED
);
248 return INVALID_SOCKET
;
253 lpProtocolInfo
= &ProtocolInfo
;
254 ZeroMemory(&ProtocolInfo
, sizeof(WSAPROTOCOL_INFOW
));
256 ProtocolInfo
.iAddressFamily
= af
;
257 ProtocolInfo
.iSocketType
= type
;
258 ProtocolInfo
.iProtocol
= protocol
;
261 Provider
= LocateProvider(lpProtocolInfo
);
264 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d) = WSAEAFNOSUPPORT.\n",
265 af
, type
, protocol
));
266 WSASetLastError(WSAEAFNOSUPPORT
);
267 return INVALID_SOCKET
;
270 Status
= LoadProvider(Provider
, lpProtocolInfo
);
271 if (Status
!= NO_ERROR
)
273 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d) = %d.\n",
274 af
, type
, protocol
, Status
));
275 WSASetLastError(Status
);
276 return INVALID_SOCKET
;
279 WS_DbgPrint(MAX_TRACE
, ("Calling WSPSocket at (0x%X).\n",
280 Provider
->ProcTable
.lpWSPSocket
));
282 assert(Provider
->ProcTable
.lpWSPSocket
);
284 WS_DbgPrint(MAX_TRACE
,("About to call provider socket fn\n"));
286 Socket
= Provider
->ProcTable
.lpWSPSocket(af
,
294 WS_DbgPrint(MAX_TRACE
,("Socket: %x, Status: %x\n", Socket
, Status
));
296 if (Status
!= NO_ERROR
)
298 WSASetLastError(Status
);
299 return INVALID_SOCKET
;
302 WS_DbgPrint(MAX_TRACE
,("Status: %x\n", Status
));
313 closesocket(IN SOCKET s
)
315 * FUNCTION: Closes a socket descriptor
317 * s = Socket descriptor
319 * 0, or SOCKET_ERROR if an error ocurred
322 PCATALOG_ENTRY Provider
;
326 WS_DbgPrint(MAX_TRACE
, ("s (0x%X).\n", s
));
330 WSASetLastError(WSANOTINITIALISED
);
334 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
336 WSASetLastError(WSAENOTSOCK
);
340 CloseProviderHandle((HANDLE
)s
);
342 WS_DbgPrint(MAX_TRACE
,("DereferenceProviderByHandle\n"));
344 DereferenceProviderByPointer(Provider
);
346 WS_DbgPrint(MAX_TRACE
,("DereferenceProviderByHandle Done\n"));
348 Status
= Provider
->ProcTable
.lpWSPCloseSocket(s
, &Errno
);
350 WS_DbgPrint(MAX_TRACE
,("Provider Close Done\n"));
352 if (Status
== SOCKET_ERROR
)
353 WSASetLastError(Errno
);
355 WS_DbgPrint(MAX_TRACE
,("Returning success\n"));
367 IN OUT LPFD_SET readfds
,
368 IN OUT LPFD_SET writefds
,
369 IN OUT LPFD_SET exceptfds
,
370 IN CONST
struct timeval
*timeout
)
372 * FUNCTION: Returns status of one or more sockets
374 * nfds = Always ignored
375 * readfds = Pointer to socket set to be checked for readability (optional)
376 * writefds = Pointer to socket set to be checked for writability (optional)
377 * exceptfds = Pointer to socket set to be checked for errors (optional)
378 * timeout = Pointer to a TIMEVAL structure indicating maximum wait time
379 * (NULL means wait forever)
381 * Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred
384 PCATALOG_ENTRY Provider
= NULL
;
388 WS_DbgPrint(MAX_TRACE
, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n",
389 readfds
, writefds
, exceptfds
));
393 WSASetLastError(WSANOTINITIALISED
);
394 WS_DbgPrint(MID_TRACE
,("Not initialized\n"));
398 /* FIXME: Sockets in FD_SETs should be sorted by their provider */
400 /* FIXME: For now, assume only one service provider */
401 if ((readfds
!= NULL
) && (readfds
->fd_count
> 0))
403 if (!ReferenceProviderByHandle((HANDLE
)readfds
->fd_array
[0],
406 WSASetLastError(WSAENOTSOCK
);
407 WS_DbgPrint(MID_TRACE
,("No provider (read)\n"));
411 else if ((writefds
!= NULL
) && (writefds
->fd_count
> 0))
413 if (!ReferenceProviderByHandle((HANDLE
)writefds
->fd_array
[0],
416 WSASetLastError(WSAENOTSOCK
);
417 WS_DbgPrint(MID_TRACE
,("No provider (write)\n"));
421 else if ((exceptfds
!= NULL
) && (exceptfds
->fd_count
> 0))
423 if (!ReferenceProviderByHandle((HANDLE
)exceptfds
->fd_array
[0], &Provider
))
425 WSASetLastError(WSAENOTSOCK
);
426 WS_DbgPrint(MID_TRACE
,("No provider (err)\n"));
429 #if 0 /* XXX empty select is not an error */
433 WSASetLastError(WSAEINVAL
);
442 WS_DbgPrint(MID_TRACE
,("Select: used as timer\n"));
443 Sleep( timeout
->tv_sec
* 1000 + (timeout
->tv_usec
/ 1000) );
447 else if (Provider
->ProcTable
.lpWSPSelect
)
449 WS_DbgPrint(MID_TRACE
,("Calling WSPSelect:%x\n", Provider
->ProcTable
.lpWSPSelect
));
450 Count
= Provider
->ProcTable
.lpWSPSelect(nfds
,
457 WS_DbgPrint(MAX_TRACE
, ("[%x] Select: Count %d Errno %x\n",
458 Provider
, Count
, Errno
));
460 DereferenceProviderByPointer(Provider
);
462 if (Errno
!= NO_ERROR
)
464 WSASetLastError(Errno
);
470 WSASetLastError(WSAEINVAL
);
484 IN CONST
struct sockaddr
*name
,
487 PCATALOG_ENTRY Provider
;
493 WSASetLastError(WSANOTINITIALISED
);
497 if (!ReferenceProviderByHandle((HANDLE
)s
,
500 WSASetLastError(WSAENOTSOCK
);
504 #if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
505 Status
= Provider
->ProcTable
.lpWSPBind(s
,
506 (CONST LPSOCKADDR
)name
,
510 Status
= Provider
->ProcTable
.lpWSPBind(s
,
514 #endif /* __W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5 */
516 DereferenceProviderByPointer(Provider
);
518 if (Status
== SOCKET_ERROR
)
519 WSASetLastError(Errno
);
533 PCATALOG_ENTRY Provider
;
539 WSASetLastError(WSANOTINITIALISED
);
543 if (!ReferenceProviderByHandle((HANDLE
)s
,
546 WSASetLastError(WSAENOTSOCK
);
550 Status
= Provider
->ProcTable
.lpWSPListen(s
,
554 DereferenceProviderByPointer(Provider
);
556 if (Status
== SOCKET_ERROR
)
557 WSASetLastError(Errno
);
570 OUT INT FAR
* addrlen
)
585 ioctlsocket(IN SOCKET s
,
587 IN OUT ULONG FAR
* argp
)
606 WSAAccept(IN SOCKET s
,
608 IN OUT LPINT addrlen
,
609 IN LPCONDITIONPROC lpfnCondition
,
610 IN DWORD dwCallbackData
)
612 PCATALOG_ENTRY Provider
;
618 WSASetLastError(WSANOTINITIALISED
);
622 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
624 WSASetLastError(WSAENOTSOCK
);
628 WS_DbgPrint(MAX_TRACE
,("Calling provider accept\n"));
630 Socket
= Provider
->ProcTable
.lpWSPAccept(s
,
637 WS_DbgPrint(MAX_TRACE
,("Calling provider accept -> Socket %x, Errno %x\n",
640 DereferenceProviderByPointer(Provider
);
642 if (Socket
== INVALID_SOCKET
)
643 WSASetLastError(Errno
);
648 LPSOCKADDR_IN sa
= (LPSOCKADDR_IN
)addr
;
649 WS_DbgPrint(MAX_TRACE
,("Returned address: %d %s:%d (len %d)\n",
651 inet_ntoa(sa
->sin_addr
),
667 IN CONST
struct sockaddr
*name
,
685 WSAConnect(IN SOCKET s
,
686 IN CONST
struct sockaddr
*name
,
688 IN LPWSABUF lpCallerData
,
689 OUT LPWSABUF lpCalleeData
,
693 PCATALOG_ENTRY Provider
;
699 WSASetLastError(WSANOTINITIALISED
);
703 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
705 WSASetLastError(WSAENOTSOCK
);
709 #if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
710 Status
= Provider
->ProcTable
.lpWSPConnect(s
,
711 (CONST LPSOCKADDR
)name
,
719 Status
= Provider
->ProcTable
.lpWSPConnect(s
,
729 DereferenceProviderByPointer(Provider
);
731 if (Status
== SOCKET_ERROR
)
732 WSASetLastError(Errno
);
743 WSAIoctl(IN SOCKET s
,
744 IN DWORD dwIoControlCode
,
745 IN LPVOID lpvInBuffer
,
747 OUT LPVOID lpvOutBuffer
,
748 IN DWORD cbOutBuffer
,
749 OUT LPDWORD lpcbBytesReturned
,
750 IN LPWSAOVERLAPPED lpOverlapped
,
751 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
753 PCATALOG_ENTRY Provider
;
759 WSASetLastError(WSANOTINITIALISED
);
763 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
765 WSASetLastError(WSAENOTSOCK
);
769 Status
= Provider
->ProcTable
.lpWSPIoctl(s
,
778 NULL
/* lpThreadId */,
781 DereferenceProviderByPointer(Provider
);
783 if (Status
== SOCKET_ERROR
)
784 WSASetLastError(Errno
);
794 __WSAFDIsSet(SOCKET s
, LPFD_SET set
)
798 for ( i
= 0; i
< set
->fd_count
; i
++ )
799 if ( set
->fd_array
[i
] == s
) return TRUE
;
804 void free_winsock_thread_block(PWINSOCK_THREAD_BLOCK p
)
808 if (p
->Hostent
) { free_hostent(p
->Hostent
); p
->Hostent
= 0; }
809 if (p
->Getservbyname
){}
810 if (p
->Getservbyport
) {}
816 DllMain(HANDLE hInstDll
,
820 PWINSOCK_THREAD_BLOCK p
;
822 WS_DbgPrint(MAX_TRACE
, ("DllMain of ws2_32.dll.\n"));
826 case DLL_PROCESS_ATTACH
:
828 GlobalHeap
= GetProcessHeap();
830 g_hInstDll
= hInstDll
;
834 InitProviderHandleTable();
836 UpcallTable
.lpWPUCloseEvent
= WPUCloseEvent
;
837 UpcallTable
.lpWPUCloseSocketHandle
= WPUCloseSocketHandle
;
838 UpcallTable
.lpWPUCreateEvent
= WPUCreateEvent
;
839 UpcallTable
.lpWPUCreateSocketHandle
= WPUCreateSocketHandle
;
840 UpcallTable
.lpWPUFDIsSet
= WPUFDIsSet
;
841 UpcallTable
.lpWPUGetProviderPath
= WPUGetProviderPath
;
842 UpcallTable
.lpWPUModifyIFSHandle
= WPUModifyIFSHandle
;
843 UpcallTable
.lpWPUPostMessage
= PostMessageW
;
844 UpcallTable
.lpWPUQueryBlockingCallback
= WPUQueryBlockingCallback
;
845 UpcallTable
.lpWPUQuerySocketHandleContext
= WPUQuerySocketHandleContext
;
846 UpcallTable
.lpWPUQueueApc
= WPUQueueApc
;
847 UpcallTable
.lpWPUResetEvent
= WPUResetEvent
;
848 UpcallTable
.lpWPUSetEvent
= WPUSetEvent
;
849 UpcallTable
.lpWPUOpenCurrentThread
= WPUOpenCurrentThread
;
850 UpcallTable
.lpWPUCloseThread
= WPUCloseThread
;
852 /* Fall through to thread attachment handler */
854 case DLL_THREAD_ATTACH
:
856 p
= HeapAlloc(GlobalHeap
, 0, sizeof(WINSOCK_THREAD_BLOCK
));
858 WS_DbgPrint(MAX_TRACE
, ("Thread block at 0x%X.\n", p
));
865 p
->LastErrorValue
= NO_ERROR
;
866 p
->Getservbyname
= NULL
;
867 p
->Getservbyport
= NULL
;
869 NtCurrentTeb()->WinSockData
= p
;
873 case DLL_PROCESS_DETACH
:
877 FreeProviderHandleTable();
881 case DLL_THREAD_DETACH
:
883 p
= NtCurrentTeb()->WinSockData
;
886 HeapFree(GlobalHeap
, 0, p
);
891 WS_DbgPrint(MAX_TRACE
, ("DllMain of ws2_32.dll. Leaving.\n"));