reactos/dll/win32/ws2_32/misc/dllmain.c
Amine Khaldi 527f2f9057 [SHELL/EXPERIMENTS]
* Create a branch for some evul shell experiments.

svn path=/branches/shell-experiments/; revision=61927
2014-02-02 19:37:27 +00:00

892 lines
21 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS WinSock 2 DLL
* FILE: misc/dllmain.c
* PURPOSE: DLL entry point
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include "ws2_32.h"
#if DBG
/* See debug.h for debug/trace constants */
//DWORD DebugTraceLevel = MIN_TRACE;
//DWORD DebugTraceLevel = MAX_TRACE;
//DWORD DebugTraceLevel = DEBUG_ULTRA;
DWORD DebugTraceLevel = 0;
#endif /* DBG */
HINSTANCE g_hInstDll;
HANDLE GlobalHeap;
BOOL WsaInitialized = FALSE; /* TRUE if WSAStartup() has been successfully called */
WSPUPCALLTABLE UpcallTable;
/*
* @implemented
*/
INT
EXPORT
WSAGetLastError(VOID)
{
return GetLastError();
}
/*
* @implemented
*/
VOID
EXPORT
WSASetLastError(IN INT iError)
{
SetLastError(iError);
}
/*
* @implemented
*/
INT
EXPORT
WSAStartup(IN WORD wVersionRequested,
OUT LPWSADATA lpWSAData)
{
BYTE Low, High;
WS_DbgPrint(MAX_TRACE, ("WSAStartup of ws2_32.dll\n"));
if (!g_hInstDll)
return WSASYSNOTREADY;
if (lpWSAData == NULL)
return WSAEFAULT;
Low = LOBYTE(wVersionRequested);
High = HIBYTE(wVersionRequested);
if (Low < 1)
{
WS_DbgPrint(MAX_TRACE, ("Bad winsock version requested, %d,%d", Low, High));
return WSAVERNOTSUPPORTED;
}
if (Low == 1)
{
if (High == 0)
{
lpWSAData->wVersion = wVersionRequested;
}
else
{
lpWSAData->wVersion = MAKEWORD(1, 1);
}
}
else if (Low == 2)
{
if (High <= 2)
{
lpWSAData->wVersion = MAKEWORD(2, High);
}
else
{
lpWSAData->wVersion = MAKEWORD(2, 2);
}
}
else
{
lpWSAData->wVersion = MAKEWORD(2, 2);
}
lpWSAData->wVersion = wVersionRequested;
lpWSAData->wHighVersion = MAKEWORD(2,2);
lstrcpyA(lpWSAData->szDescription, "WinSock 2.2");
lstrcpyA(lpWSAData->szSystemStatus, "Running");
lpWSAData->iMaxSockets = 0;
lpWSAData->iMaxUdpDg = 0;
lpWSAData->lpVendorInfo = NULL;
/*FIXME: increment internal counter */
WSASETINITIALIZED;
return NO_ERROR;
}
/*
* @implemented
*/
INT
EXPORT
WSACleanup(VOID)
{
WS_DbgPrint(MAX_TRACE, ("WSACleanup of ws2_32.dll\n"));
if (!WSAINITIALIZED)
{
WSASetLastError(WSANOTINITIALISED);
return WSANOTINITIALISED;
}
return NO_ERROR;
}
/*
* @implemented
*/
SOCKET
EXPORT
socket(IN INT af,
IN INT type,
IN INT protocol)
{
return WSASocketW(af,
type,
protocol,
NULL,
0,
0);
}
/*
* @implemented
*/
SOCKET
EXPORT
WSASocketA(IN INT af,
IN INT type,
IN INT protocol,
IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
IN GROUP g,
IN DWORD dwFlags)
/*
* FUNCTION: Creates a new socket
*/
{
WSAPROTOCOL_INFOW ProtocolInfoW;
LPWSAPROTOCOL_INFOW p;
UNICODE_STRING StringU;
ANSI_STRING StringA;
WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n",
af, type, protocol));
if (lpProtocolInfo)
{
memcpy(&ProtocolInfoW,
lpProtocolInfo,
sizeof(WSAPROTOCOL_INFOA) - sizeof(CHAR) * (WSAPROTOCOL_LEN + 1));
RtlInitAnsiString(&StringA, (LPSTR)lpProtocolInfo->szProtocol);
RtlInitUnicodeString(&StringU, (LPWSTR)&ProtocolInfoW.szProtocol);
RtlAnsiStringToUnicodeString(&StringU, &StringA, FALSE);
p = &ProtocolInfoW;
}
else
{
p = NULL;
}
return WSASocketW(af,
type,
protocol,
p,
g,
dwFlags);
}
/*
* @implemented
*/
SOCKET
EXPORT
WSASocketW(IN INT af,
IN INT type,
IN INT protocol,
IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
IN GROUP g,
IN DWORD dwFlags)
/*
* FUNCTION: Creates a new socket descriptor
* ARGUMENTS:
* af = Address family
* type = Socket type
* protocol = Protocol type
* lpProtocolInfo = Pointer to protocol information
* g = Reserved
* dwFlags = Socket flags
* RETURNS:
* Created socket descriptor, or INVALID_SOCKET if it could not be created
*/
{
INT Status;
SOCKET Socket;
PCATALOG_ENTRY Provider;
WSAPROTOCOL_INFOW ProtocolInfo;
WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n",
af, type, protocol));
if (!WSAINITIALIZED)
{
WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d) = WSANOTINITIALISED.\n",
af, type, protocol));
WSASetLastError(WSANOTINITIALISED);
return INVALID_SOCKET;
}
if (!lpProtocolInfo)
{
lpProtocolInfo = &ProtocolInfo;
ZeroMemory(&ProtocolInfo, sizeof(WSAPROTOCOL_INFOW));
ProtocolInfo.iAddressFamily = af;
ProtocolInfo.iSocketType = type;
ProtocolInfo.iProtocol = protocol;
}
Provider = LocateProvider(lpProtocolInfo);
if (!Provider)
{
WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d) = WSAEAFNOSUPPORT.\n",
af, type, protocol));
WSASetLastError(WSAEAFNOSUPPORT);
return INVALID_SOCKET;
}
Status = LoadProvider(Provider, lpProtocolInfo);
if (Status != NO_ERROR)
{
WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d) = %d.\n",
af, type, protocol, Status));
WSASetLastError(Status);
return INVALID_SOCKET;
}
WS_DbgPrint(MAX_TRACE, ("Calling WSPSocket at (0x%X).\n",
Provider->ProcTable.lpWSPSocket));
assert(Provider->ProcTable.lpWSPSocket);
WS_DbgPrint(MAX_TRACE,("About to call provider socket fn\n"));
Socket = Provider->ProcTable.lpWSPSocket(af,
type,
protocol,
lpProtocolInfo,
g,
dwFlags,
&Status);
WS_DbgPrint(MAX_TRACE,("Socket: %x, Status: %x\n", Socket, Status));
if (Status != NO_ERROR)
{
WSASetLastError(Status);
return INVALID_SOCKET;
}
WS_DbgPrint(MAX_TRACE,("Status: %x\n", Status));
return Socket;
}
/*
* @implemented
*/
INT
EXPORT
closesocket(IN SOCKET s)
/*
* FUNCTION: Closes a socket descriptor
* ARGUMENTS:
* s = Socket descriptor
* RETURNS:
* 0, or SOCKET_ERROR if an error ocurred
*/
{
PCATALOG_ENTRY Provider;
INT Status;
INT Errno;
WS_DbgPrint(MAX_TRACE, ("s (0x%X).\n", s));
if (!WSAINITIALIZED)
{
WSASetLastError(WSANOTINITIALISED);
return SOCKET_ERROR;
}
if (!ReferenceProviderByHandle((HANDLE)s, &Provider))
{
WSASetLastError(WSAENOTSOCK);
return SOCKET_ERROR;
}
CloseProviderHandle((HANDLE)s);
WS_DbgPrint(MAX_TRACE,("DereferenceProviderByHandle\n"));
DereferenceProviderByPointer(Provider);
WS_DbgPrint(MAX_TRACE,("DereferenceProviderByHandle Done\n"));
Status = Provider->ProcTable.lpWSPCloseSocket(s, &Errno);
WS_DbgPrint(MAX_TRACE,("Provider Close Done\n"));
if (Status == SOCKET_ERROR)
WSASetLastError(Errno);
WS_DbgPrint(MAX_TRACE,("Returning success\n"));
return 0;
}
/*
* @implemented
*/
INT
EXPORT
select(IN INT nfds,
IN OUT LPFD_SET readfds,
IN OUT LPFD_SET writefds,
IN OUT LPFD_SET exceptfds,
IN CONST struct timeval *timeout)
/*
* FUNCTION: Returns status of one or more sockets
* ARGUMENTS:
* nfds = Always ignored
* readfds = Pointer to socket set to be checked for readability (optional)
* writefds = Pointer to socket set to be checked for writability (optional)
* exceptfds = Pointer to socket set to be checked for errors (optional)
* timeout = Pointer to a TIMEVAL structure indicating maximum wait time
* (NULL means wait forever)
* RETURNS:
* Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred
*/
{
PCATALOG_ENTRY Provider = NULL;
INT Count;
INT Errno;
WS_DbgPrint(MAX_TRACE, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n",
readfds, writefds, exceptfds));
if (!WSAINITIALIZED)
{
WSASetLastError(WSANOTINITIALISED);
WS_DbgPrint(MID_TRACE,("Not initialized\n"));
return SOCKET_ERROR;
}
/* FIXME: Sockets in FD_SETs should be sorted by their provider */
/* FIXME: For now, assume only one service provider */
if ((readfds != NULL) && (readfds->fd_count > 0))
{
if (!ReferenceProviderByHandle((HANDLE)readfds->fd_array[0],
&Provider))
{
WSASetLastError(WSAENOTSOCK);
WS_DbgPrint(MID_TRACE,("No provider (read)\n"));
return SOCKET_ERROR;
}
}
else if ((writefds != NULL) && (writefds->fd_count > 0))
{
if (!ReferenceProviderByHandle((HANDLE)writefds->fd_array[0],
&Provider))
{
WSASetLastError(WSAENOTSOCK);
WS_DbgPrint(MID_TRACE,("No provider (write)\n"));
return SOCKET_ERROR;
}
}
else if ((exceptfds != NULL) && (exceptfds->fd_count > 0))
{
if (!ReferenceProviderByHandle((HANDLE)exceptfds->fd_array[0], &Provider))
{
WSASetLastError(WSAENOTSOCK);
WS_DbgPrint(MID_TRACE,("No provider (err)\n"));
return SOCKET_ERROR;
}
#if 0 /* XXX empty select is not an error */
}
else
{
WSASetLastError(WSAEINVAL);
return SOCKET_ERROR;
#endif
}
if ( !Provider )
{
if ( timeout )
{
WS_DbgPrint(MID_TRACE,("Select: used as timer\n"));
Sleep( timeout->tv_sec * 1000 + (timeout->tv_usec / 1000) );
}
return 0;
}
else if (Provider->ProcTable.lpWSPSelect)
{
WS_DbgPrint(MID_TRACE,("Calling WSPSelect:%x\n", Provider->ProcTable.lpWSPSelect));
Count = Provider->ProcTable.lpWSPSelect(nfds,
readfds,
writefds,
exceptfds,
(LPTIMEVAL)timeout,
&Errno);
WS_DbgPrint(MAX_TRACE, ("[%x] Select: Count %d Errno %x\n",
Provider, Count, Errno));
DereferenceProviderByPointer(Provider);
if (Count == SOCKET_ERROR)
{
WSASetLastError(Errno);
return SOCKET_ERROR;
}
}
else
{
WSASetLastError(WSAEINVAL);
return SOCKET_ERROR;
}
return Count;
}
/*
* @implemented
*/
INT
EXPORT
bind(IN SOCKET s,
IN CONST struct sockaddr *name,
IN INT namelen)
{
PCATALOG_ENTRY Provider;
INT Status;
INT Errno;
if (!WSAINITIALIZED)
{
WSASetLastError(WSANOTINITIALISED);
return SOCKET_ERROR;
}
if (!ReferenceProviderByHandle((HANDLE)s,
&Provider))
{
WSASetLastError(WSAENOTSOCK);
return SOCKET_ERROR;
}
#if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
Status = Provider->ProcTable.lpWSPBind(s,
(CONST LPSOCKADDR)name,
namelen,
&Errno);
#else
Status = Provider->ProcTable.lpWSPBind(s,
name,
namelen,
&Errno);
#endif /* __W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5 */
DereferenceProviderByPointer(Provider);
if (Status == SOCKET_ERROR)
WSASetLastError(Errno);
return Status;
}
/*
* @implemented
*/
INT
EXPORT
listen(IN SOCKET s,
IN INT backlog)
{
PCATALOG_ENTRY Provider;
INT Status;
INT Errno;
if (!WSAINITIALIZED)
{
WSASetLastError(WSANOTINITIALISED);
return SOCKET_ERROR;
}
if (!ReferenceProviderByHandle((HANDLE)s,
&Provider))
{
WSASetLastError(WSAENOTSOCK);
return SOCKET_ERROR;
}
Status = Provider->ProcTable.lpWSPListen(s,
backlog,
&Errno);
DereferenceProviderByPointer(Provider);
if (Status == SOCKET_ERROR)
WSASetLastError(Errno);
return Status;
}
/*
* @implemented
*/
SOCKET
EXPORT
accept(IN SOCKET s,
OUT LPSOCKADDR addr,
OUT INT FAR* addrlen)
{
return WSAAccept(s,
addr,
addrlen,
NULL,
0);
}
/*
* @implemented
*/
INT
EXPORT
ioctlsocket(IN SOCKET s,
IN LONG cmd,
IN OUT ULONG FAR* argp)
{
ULONG tmp;
return WSAIoctl(s,
cmd,
argp,
sizeof(ULONG),
argp,
sizeof(ULONG),
&tmp,
0,
0);
}
/*
* @implemented
*/
SOCKET
EXPORT
WSAAccept(IN SOCKET s,
OUT LPSOCKADDR addr,
IN OUT LPINT addrlen,
IN LPCONDITIONPROC lpfnCondition,
IN DWORD_PTR dwCallbackData)
{
PCATALOG_ENTRY Provider;
SOCKET Socket;
INT Errno;
if (!WSAINITIALIZED)
{
WSASetLastError(WSANOTINITIALISED);
return SOCKET_ERROR;
}
if (!ReferenceProviderByHandle((HANDLE)s, &Provider))
{
WSASetLastError(WSAENOTSOCK);
return SOCKET_ERROR;
}
WS_DbgPrint(MAX_TRACE,("Calling provider accept\n"));
Socket = Provider->ProcTable.lpWSPAccept(s,
addr,
addrlen,
lpfnCondition,
dwCallbackData,
&Errno);
WS_DbgPrint(MAX_TRACE,("Calling provider accept -> Socket %x, Errno %x\n",
Socket, Errno));
DereferenceProviderByPointer(Provider);
if (Socket == INVALID_SOCKET)
WSASetLastError(Errno);
if ( addr && addrlen )
{
#if DBG
LPSOCKADDR_IN sa = (LPSOCKADDR_IN)addr;
WS_DbgPrint(MAX_TRACE,("Returned address: %d %s:%d (len %d)\n",
sa->sin_family,
inet_ntoa(sa->sin_addr),
ntohs(sa->sin_port),
*addrlen));
#endif
}
return Socket;
}
/*
* @implemented
*/
INT
EXPORT
connect(IN SOCKET s,
IN CONST struct sockaddr *name,
IN INT namelen)
{
return WSAConnect(s,
name,
namelen,
NULL,
NULL,
NULL,
NULL);
}
/*
* @implemented
*/
INT
EXPORT
WSAConnect(IN SOCKET s,
IN CONST struct sockaddr *name,
IN INT namelen,
IN LPWSABUF lpCallerData,
OUT LPWSABUF lpCalleeData,
IN LPQOS lpSQOS,
IN LPQOS lpGQOS)
{
PCATALOG_ENTRY Provider;
INT Status;
INT Errno;
if (!WSAINITIALIZED)
{
WSASetLastError(WSANOTINITIALISED);
return SOCKET_ERROR;
}
if (!ReferenceProviderByHandle((HANDLE)s, &Provider))
{
WSASetLastError(WSAENOTSOCK);
return SOCKET_ERROR;
}
#if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
Status = Provider->ProcTable.lpWSPConnect(s,
(CONST LPSOCKADDR)name,
namelen,
lpCallerData,
lpCalleeData,
lpSQOS,
lpGQOS,
&Errno);
#else
Status = Provider->ProcTable.lpWSPConnect(s,
name,
namelen,
lpCallerData,
lpCalleeData,
lpSQOS,
lpGQOS,
&Errno);
#endif
DereferenceProviderByPointer(Provider);
if (Status == SOCKET_ERROR)
WSASetLastError(Errno);
return Status;
}
/*
* @implemented
*/
INT
EXPORT
WSAIoctl(IN SOCKET s,
IN DWORD dwIoControlCode,
IN LPVOID lpvInBuffer,
IN DWORD cbInBuffer,
OUT LPVOID lpvOutBuffer,
IN DWORD cbOutBuffer,
OUT LPDWORD lpcbBytesReturned,
IN LPWSAOVERLAPPED lpOverlapped,
IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
PCATALOG_ENTRY Provider;
INT Status;
INT Errno;
if (!WSAINITIALIZED)
{
WSASetLastError(WSANOTINITIALISED);
return SOCKET_ERROR;
}
if (!ReferenceProviderByHandle((HANDLE)s, &Provider))
{
WSASetLastError(WSAENOTSOCK);
return SOCKET_ERROR;
}
Status = Provider->ProcTable.lpWSPIoctl(s,
dwIoControlCode,
lpvInBuffer,
cbInBuffer,
lpvOutBuffer,
cbOutBuffer,
lpcbBytesReturned,
lpOverlapped,
lpCompletionRoutine,
NULL /* lpThreadId */,
&Errno);
DereferenceProviderByPointer(Provider);
if (Status == SOCKET_ERROR)
WSASetLastError(Errno);
return Status;
}
/*
* @implemented
*/
INT
EXPORT
__WSAFDIsSet(SOCKET s, LPFD_SET set)
{
unsigned int i;
for ( i = 0; i < set->fd_count; i++ )
if ( set->fd_array[i] == s ) return TRUE;
return FALSE;
}
void free_winsock_thread_block(PWINSOCK_THREAD_BLOCK p)
{
if (p)
{
if (p->Hostent) { free_hostent(p->Hostent); p->Hostent = 0; }
if (p->Getservbyname){}
if (p->Getservbyport) {}
}
}
BOOL
WINAPI
DllMain(HANDLE hInstDll,
ULONG dwReason,
LPVOID lpReserved)
{
PWINSOCK_THREAD_BLOCK p;
WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll.\n"));
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
GlobalHeap = GetProcessHeap();
g_hInstDll = hInstDll;
CreateCatalog();
InitProviderHandleTable();
UpcallTable.lpWPUCloseEvent = WPUCloseEvent;
UpcallTable.lpWPUCloseSocketHandle = WPUCloseSocketHandle;
UpcallTable.lpWPUCreateEvent = WPUCreateEvent;
UpcallTable.lpWPUCreateSocketHandle = WPUCreateSocketHandle;
UpcallTable.lpWPUFDIsSet = WPUFDIsSet;
UpcallTable.lpWPUGetProviderPath = WPUGetProviderPath;
UpcallTable.lpWPUModifyIFSHandle = WPUModifyIFSHandle;
UpcallTable.lpWPUPostMessage = PostMessageW;
UpcallTable.lpWPUQueryBlockingCallback = WPUQueryBlockingCallback;
UpcallTable.lpWPUQuerySocketHandleContext = WPUQuerySocketHandleContext;
UpcallTable.lpWPUQueueApc = WPUQueueApc;
UpcallTable.lpWPUResetEvent = WPUResetEvent;
UpcallTable.lpWPUSetEvent = WPUSetEvent;
UpcallTable.lpWPUOpenCurrentThread = WPUOpenCurrentThread;
UpcallTable.lpWPUCloseThread = WPUCloseThread;
/* Fall through to thread attachment handler */
}
case DLL_THREAD_ATTACH:
{
p = HeapAlloc(GlobalHeap, 0, sizeof(WINSOCK_THREAD_BLOCK));
WS_DbgPrint(MAX_TRACE, ("Thread block at 0x%X.\n", p));
if (!p) {
return FALSE;
}
p->Hostent = NULL;
p->LastErrorValue = NO_ERROR;
p->Getservbyname = NULL;
p->Getservbyport = NULL;
NtCurrentTeb()->WinSockData = p;
}
break;
case DLL_PROCESS_DETACH:
{
DestroyCatalog();
FreeProviderHandleTable();
}
break;
case DLL_THREAD_DETACH:
{
p = NtCurrentTeb()->WinSockData;
if (p)
HeapFree(GlobalHeap, 0, p);
}
break;
}
WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll. Leaving.\n"));
return TRUE;
}
/* EOF */