dllmain.c

来自「一个类似windows」· C语言 代码 · 共 780 行 · 第 1/2 页

C
780
字号
/*
 * 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 <roscfg.h>
#include <w32api.h>
#include <ws2_32.h>
#include <catalog.h>
#include <handle.h>
#include <upcall.h>

#ifdef 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 */

/* To make the linker happy */
VOID STDCALL KeBugCheck (ULONG	BugCheckCode) {}


HANDLE GlobalHeap;
BOOL WsaInitialized = FALSE;	/* TRUE if WSAStartup() has been successfully called */
WSPUPCALLTABLE UpcallTable;


/*
 * @implemented
 */
INT
EXPORT
WSAGetLastError(VOID)
{
  
PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;

  if (p) {
    return p->LastErrorValue;
  } else {
    /* FIXME: What error code should we use here? Can this even happen? */
    return ERROR_BAD_ENVIRONMENT;
  }
}


/*
 * @implemented
 */
VOID
EXPORT
WSASetLastError(
    IN  INT iError)
{
  PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;

  if (p)
      p->LastErrorValue = iError;
}


/*
 * @implemented
 */
INT
EXPORT
WSAStartup(
    IN  WORD wVersionRequested,
    OUT LPWSADATA lpWSAData)
{
  WS_DbgPrint(MAX_TRACE, ("WSAStartup of ws2_32.dll\n"));

  lpWSAData->wVersion     = wVersionRequested;
  lpWSAData->wHighVersion = 2;
  lstrcpyA(lpWSAData->szDescription, "WinSock 2.0");
  lstrcpyA(lpWSAData->szSystemStatus, "Running");
  lpWSAData->iMaxSockets  = 0;
  lpWSAData->iMaxUdpDg    = 0;
  lpWSAData->lpVendorInfo = NULL;

  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 WSASocketA(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));

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?