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
15 /* See debug.h for debug/trace constants */
16 //DWORD DebugTraceLevel = MIN_TRACE;
17 //DWORD DebugTraceLevel = MAX_TRACE;
18 //DWORD DebugTraceLevel = DEBUG_ULTRA;
19 DWORD DebugTraceLevel
= 0;
24 BOOL WsaInitialized
= FALSE
; /* TRUE if WSAStartup() has been successfully called */
25 WSPUPCALLTABLE UpcallTable
;
35 return GetLastError();
44 WSASetLastError(IN INT iError
)
55 WSAStartup(IN WORD wVersionRequested
,
56 OUT LPWSADATA lpWSAData
)
60 WS_DbgPrint(MAX_TRACE
, ("WSAStartup of ws2_32.dll\n"));
63 return WSASYSNOTREADY
;
65 if (lpWSAData
== NULL
)
68 Low
= LOBYTE(wVersionRequested
);
69 High
= HIBYTE(wVersionRequested
);
73 WS_DbgPrint(MAX_TRACE
, ("Bad winsock version requested, %d,%d", Low
, High
));
74 return WSAVERNOTSUPPORTED
;
81 lpWSAData
->wVersion
= wVersionRequested
;
85 lpWSAData
->wVersion
= MAKEWORD(1, 1);
92 lpWSAData
->wVersion
= MAKEWORD(2, High
);
96 lpWSAData
->wVersion
= MAKEWORD(2, 2);
101 lpWSAData
->wVersion
= MAKEWORD(2, 2);
104 lpWSAData
->wVersion
= wVersionRequested
;
105 lpWSAData
->wHighVersion
= MAKEWORD(2,2);
106 lstrcpyA(lpWSAData
->szDescription
, "WinSock 2.2");
107 lstrcpyA(lpWSAData
->szSystemStatus
, "Running");
108 lpWSAData
->iMaxSockets
= 0;
109 lpWSAData
->iMaxUdpDg
= 0;
110 lpWSAData
->lpVendorInfo
= NULL
;
112 /*FIXME: increment internal counter */
127 WS_DbgPrint(MAX_TRACE
, ("WSACleanup of ws2_32.dll\n"));
131 WSASetLastError(WSANOTINITIALISED
);
132 return WSANOTINITIALISED
;
148 return WSASocketW(af
,
162 WSASocketA(IN INT af
,
165 IN LPWSAPROTOCOL_INFOA lpProtocolInfo
,
169 * FUNCTION: Creates a new socket
172 WSAPROTOCOL_INFOW ProtocolInfoW
;
173 LPWSAPROTOCOL_INFOW p
;
174 UNICODE_STRING StringU
;
177 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d).\n",
178 af
, type
, protocol
));
182 memcpy(&ProtocolInfoW
,
184 sizeof(WSAPROTOCOL_INFOA
) - sizeof(CHAR
) * (WSAPROTOCOL_LEN
+ 1));
185 RtlInitAnsiString(&StringA
, (LPSTR
)lpProtocolInfo
->szProtocol
);
186 RtlInitUnicodeString(&StringU
, (LPWSTR
)&ProtocolInfoW
.szProtocol
);
187 RtlAnsiStringToUnicodeString(&StringU
, &StringA
, FALSE
);
195 return WSASocketW(af
,
209 WSASocketW(IN INT af
,
212 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
216 * FUNCTION: Creates a new socket descriptor
218 * af = Address family
220 * protocol = Protocol type
221 * lpProtocolInfo = Pointer to protocol information
223 * dwFlags = Socket flags
225 * Created socket descriptor, or INVALID_SOCKET if it could not be created
230 PCATALOG_ENTRY Provider
;
231 WSAPROTOCOL_INFOW ProtocolInfo
;
233 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d).\n",
234 af
, type
, protocol
));
238 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d) = WSANOTINITIALISED.\n",
239 af
, type
, protocol
));
240 WSASetLastError(WSANOTINITIALISED
);
241 return INVALID_SOCKET
;
246 lpProtocolInfo
= &ProtocolInfo
;
247 ZeroMemory(&ProtocolInfo
, sizeof(WSAPROTOCOL_INFOW
));
249 ProtocolInfo
.iAddressFamily
= af
;
250 ProtocolInfo
.iSocketType
= type
;
251 ProtocolInfo
.iProtocol
= protocol
;
254 Provider
= LocateProvider(lpProtocolInfo
);
257 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d) = WSAEAFNOSUPPORT.\n",
258 af
, type
, protocol
));
259 WSASetLastError(WSAEAFNOSUPPORT
);
260 return INVALID_SOCKET
;
263 Status
= LoadProvider(Provider
, lpProtocolInfo
);
264 if (Status
!= NO_ERROR
)
266 WS_DbgPrint(MAX_TRACE
, ("af (%d) type (%d) protocol (%d) = %d.\n",
267 af
, type
, protocol
, Status
));
268 WSASetLastError(Status
);
269 return INVALID_SOCKET
;
272 WS_DbgPrint(MAX_TRACE
, ("Calling WSPSocket at (0x%X).\n",
273 Provider
->ProcTable
.lpWSPSocket
));
275 assert(Provider
->ProcTable
.lpWSPSocket
);
277 WS_DbgPrint(MAX_TRACE
,("About to call provider socket fn\n"));
279 Socket
= Provider
->ProcTable
.lpWSPSocket(af
,
287 WS_DbgPrint(MAX_TRACE
,("Socket: %x, Status: %x\n", Socket
, Status
));
289 if (Status
!= NO_ERROR
)
291 WSASetLastError(Status
);
292 return INVALID_SOCKET
;
295 WS_DbgPrint(MAX_TRACE
,("Status: %x\n", Status
));
306 closesocket(IN SOCKET s
)
308 * FUNCTION: Closes a socket descriptor
310 * s = Socket descriptor
312 * 0, or SOCKET_ERROR if an error ocurred
315 PCATALOG_ENTRY Provider
;
319 WS_DbgPrint(MAX_TRACE
, ("s (0x%X).\n", s
));
323 WSASetLastError(WSANOTINITIALISED
);
327 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
329 WSASetLastError(WSAENOTSOCK
);
333 CloseProviderHandle((HANDLE
)s
);
335 WS_DbgPrint(MAX_TRACE
,("DereferenceProviderByHandle\n"));
337 DereferenceProviderByPointer(Provider
);
339 WS_DbgPrint(MAX_TRACE
,("DereferenceProviderByHandle Done\n"));
341 Status
= Provider
->ProcTable
.lpWSPCloseSocket(s
, &Errno
);
343 WS_DbgPrint(MAX_TRACE
,("Provider Close Done\n"));
345 if (Status
== SOCKET_ERROR
)
346 WSASetLastError(Errno
);
348 WS_DbgPrint(MAX_TRACE
,("Returning success\n"));
360 IN OUT LPFD_SET readfds
,
361 IN OUT LPFD_SET writefds
,
362 IN OUT LPFD_SET exceptfds
,
363 IN CONST
struct timeval
*timeout
)
365 * FUNCTION: Returns status of one or more sockets
367 * nfds = Always ignored
368 * readfds = Pointer to socket set to be checked for readability (optional)
369 * writefds = Pointer to socket set to be checked for writability (optional)
370 * exceptfds = Pointer to socket set to be checked for errors (optional)
371 * timeout = Pointer to a TIMEVAL structure indicating maximum wait time
372 * (NULL means wait forever)
374 * Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred
377 PCATALOG_ENTRY Provider
= NULL
;
381 WS_DbgPrint(MAX_TRACE
, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n",
382 readfds
, writefds
, exceptfds
));
386 WSASetLastError(WSANOTINITIALISED
);
387 WS_DbgPrint(MID_TRACE
,("Not initialized\n"));
391 /* FIXME: Sockets in FD_SETs should be sorted by their provider */
393 /* FIXME: For now, assume only one service provider */
394 if ((readfds
!= NULL
) && (readfds
->fd_count
> 0))
396 if (!ReferenceProviderByHandle((HANDLE
)readfds
->fd_array
[0],
399 WSASetLastError(WSAENOTSOCK
);
400 WS_DbgPrint(MID_TRACE
,("No provider (read)\n"));
404 else if ((writefds
!= NULL
) && (writefds
->fd_count
> 0))
406 if (!ReferenceProviderByHandle((HANDLE
)writefds
->fd_array
[0],
409 WSASetLastError(WSAENOTSOCK
);
410 WS_DbgPrint(MID_TRACE
,("No provider (write)\n"));
414 else if ((exceptfds
!= NULL
) && (exceptfds
->fd_count
> 0))
416 if (!ReferenceProviderByHandle((HANDLE
)exceptfds
->fd_array
[0], &Provider
))
418 WSASetLastError(WSAENOTSOCK
);
419 WS_DbgPrint(MID_TRACE
,("No provider (err)\n"));
422 #if 0 /* XXX empty select is not an error */
426 WSASetLastError(WSAEINVAL
);
435 WS_DbgPrint(MID_TRACE
,("Select: used as timer\n"));
436 Sleep( timeout
->tv_sec
* 1000 + (timeout
->tv_usec
/ 1000) );
440 else if (Provider
->ProcTable
.lpWSPSelect
)
442 WS_DbgPrint(MID_TRACE
,("Calling WSPSelect:%x\n", Provider
->ProcTable
.lpWSPSelect
));
443 Count
= Provider
->ProcTable
.lpWSPSelect(nfds
,
450 WS_DbgPrint(MAX_TRACE
, ("[%x] Select: Count %d Errno %x\n",
451 Provider
, Count
, Errno
));
453 DereferenceProviderByPointer(Provider
);
455 if (Count
== SOCKET_ERROR
)
457 WSASetLastError(Errno
);
463 WSASetLastError(WSAEINVAL
);
477 IN CONST
struct sockaddr
*name
,
480 PCATALOG_ENTRY Provider
;
486 WSASetLastError(WSANOTINITIALISED
);
490 if (!ReferenceProviderByHandle((HANDLE
)s
,
493 WSASetLastError(WSAENOTSOCK
);
497 #if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
498 Status
= Provider
->ProcTable
.lpWSPBind(s
,
499 (CONST LPSOCKADDR
)name
,
503 Status
= Provider
->ProcTable
.lpWSPBind(s
,
507 #endif /* __W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5 */
509 DereferenceProviderByPointer(Provider
);
511 if (Status
== SOCKET_ERROR
)
512 WSASetLastError(Errno
);
526 PCATALOG_ENTRY Provider
;
532 WSASetLastError(WSANOTINITIALISED
);
536 if (!ReferenceProviderByHandle((HANDLE
)s
,
539 WSASetLastError(WSAENOTSOCK
);
543 Status
= Provider
->ProcTable
.lpWSPListen(s
,
547 DereferenceProviderByPointer(Provider
);
549 if (Status
== SOCKET_ERROR
)
550 WSASetLastError(Errno
);
563 OUT INT FAR
* addrlen
)
578 ioctlsocket(IN SOCKET s
,
580 IN OUT ULONG FAR
* argp
)
601 WSAAccept(IN SOCKET s
,
603 IN OUT LPINT addrlen
,
604 IN LPCONDITIONPROC lpfnCondition
,
605 IN DWORD_PTR dwCallbackData
)
607 PCATALOG_ENTRY Provider
;
613 WSASetLastError(WSANOTINITIALISED
);
617 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
619 WSASetLastError(WSAENOTSOCK
);
623 WS_DbgPrint(MAX_TRACE
,("Calling provider accept\n"));
625 Socket
= Provider
->ProcTable
.lpWSPAccept(s
,
632 WS_DbgPrint(MAX_TRACE
,("Calling provider accept -> Socket %x, Errno %x\n",
635 DereferenceProviderByPointer(Provider
);
637 if (Socket
== INVALID_SOCKET
)
638 WSASetLastError(Errno
);
640 if ( addr
&& addrlen
)
643 LPSOCKADDR_IN sa
= (LPSOCKADDR_IN
)addr
;
644 WS_DbgPrint(MAX_TRACE
,("Returned address: %d %s:%d (len %d)\n",
646 inet_ntoa(sa
->sin_addr
),
662 IN CONST
struct sockaddr
*name
,
680 WSAConnect(IN SOCKET s
,
681 IN CONST
struct sockaddr
*name
,
683 IN LPWSABUF lpCallerData
,
684 OUT LPWSABUF lpCalleeData
,
688 PCATALOG_ENTRY Provider
;
694 WSASetLastError(WSANOTINITIALISED
);
698 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
700 WSASetLastError(WSAENOTSOCK
);
704 #if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
705 Status
= Provider
->ProcTable
.lpWSPConnect(s
,
706 (CONST LPSOCKADDR
)name
,
714 Status
= Provider
->ProcTable
.lpWSPConnect(s
,
724 DereferenceProviderByPointer(Provider
);
726 if (Status
== SOCKET_ERROR
)
727 WSASetLastError(Errno
);
738 WSAIoctl(IN SOCKET s
,
739 IN DWORD dwIoControlCode
,
740 IN LPVOID lpvInBuffer
,
742 OUT LPVOID lpvOutBuffer
,
743 IN DWORD cbOutBuffer
,
744 OUT LPDWORD lpcbBytesReturned
,
745 IN LPWSAOVERLAPPED lpOverlapped
,
746 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
748 PCATALOG_ENTRY Provider
;
754 WSASetLastError(WSANOTINITIALISED
);
758 if (!ReferenceProviderByHandle((HANDLE
)s
, &Provider
))
760 WSASetLastError(WSAENOTSOCK
);
764 Status
= Provider
->ProcTable
.lpWSPIoctl(s
,
773 NULL
/* lpThreadId */,
776 DereferenceProviderByPointer(Provider
);
778 if (Status
== SOCKET_ERROR
)
779 WSASetLastError(Errno
);
789 __WSAFDIsSet(SOCKET s
, LPFD_SET set
)
793 for ( i
= 0; i
< set
->fd_count
; i
++ )
794 if ( set
->fd_array
[i
] == s
) return TRUE
;
799 void free_winsock_thread_block(PWINSOCK_THREAD_BLOCK p
)
803 if (p
->Hostent
) { free_hostent(p
->Hostent
); p
->Hostent
= 0; }
804 if (p
->Getservbyname
){}
805 if (p
->Getservbyport
) {}
811 DllMain(HANDLE hInstDll
,
815 PWINSOCK_THREAD_BLOCK p
;
817 WS_DbgPrint(MAX_TRACE
, ("DllMain of ws2_32.dll.\n"));
821 case DLL_PROCESS_ATTACH
:
823 GlobalHeap
= GetProcessHeap();
825 g_hInstDll
= hInstDll
;
829 InitProviderHandleTable();
831 UpcallTable
.lpWPUCloseEvent
= WPUCloseEvent
;
832 UpcallTable
.lpWPUCloseSocketHandle
= WPUCloseSocketHandle
;
833 UpcallTable
.lpWPUCreateEvent
= WPUCreateEvent
;
834 UpcallTable
.lpWPUCreateSocketHandle
= WPUCreateSocketHandle
;
835 UpcallTable
.lpWPUFDIsSet
= WPUFDIsSet
;
836 UpcallTable
.lpWPUGetProviderPath
= WPUGetProviderPath
;
837 UpcallTable
.lpWPUModifyIFSHandle
= WPUModifyIFSHandle
;
838 UpcallTable
.lpWPUPostMessage
= PostMessageW
;
839 UpcallTable
.lpWPUQueryBlockingCallback
= WPUQueryBlockingCallback
;
840 UpcallTable
.lpWPUQuerySocketHandleContext
= WPUQuerySocketHandleContext
;
841 UpcallTable
.lpWPUQueueApc
= WPUQueueApc
;
842 UpcallTable
.lpWPUResetEvent
= WPUResetEvent
;
843 UpcallTable
.lpWPUSetEvent
= WPUSetEvent
;
844 UpcallTable
.lpWPUOpenCurrentThread
= WPUOpenCurrentThread
;
845 UpcallTable
.lpWPUCloseThread
= WPUCloseThread
;
847 /* Fall through to thread attachment handler */
849 case DLL_THREAD_ATTACH
:
851 p
= HeapAlloc(GlobalHeap
, 0, sizeof(WINSOCK_THREAD_BLOCK
));
853 WS_DbgPrint(MAX_TRACE
, ("Thread block at 0x%X.\n", p
));
860 p
->LastErrorValue
= NO_ERROR
;
861 p
->Getservbyname
= NULL
;
862 p
->Getservbyport
= NULL
;
864 NtCurrentTeb()->WinSockData
= p
;
868 case DLL_PROCESS_DETACH
:
872 FreeProviderHandleTable();
876 case DLL_THREAD_DETACH
:
878 p
= NtCurrentTeb()->WinSockData
;
881 HeapFree(GlobalHeap
, 0, p
);
886 WS_DbgPrint(MAX_TRACE
, ("DllMain of ws2_32.dll. Leaving.\n"));