⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dllmain.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * 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) {}

HINSTANCE g_hInstDll;
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)
{
    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 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) );
        }

⌨️ 快捷键说明

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