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

📄 dllmain.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:

/*
 * COPYRIGHT:   See COPYING in the top level directory
 * PROJECT:     ReactOS Ancillary Function Driver DLL
 * FILE:        misc/dllmain.c
 * PURPOSE:     DLL entry point
 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
 *				Alex Ionescu (alex@relsoft.net)
 * REVISIONS:
 *   CSH 01/09-2000 Created
 *	 Alex 16/07/2004 - Complete Rewrite
 */
#include <msafd.h>

#include <debug.h>

#ifdef DBG
//DWORD DebugTraceLevel = DEBUG_ULTRA;
DWORD DebugTraceLevel = 0;
#endif /* DBG */

HANDLE GlobalHeap;
WSPUPCALLTABLE Upcalls;
LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
ULONG SocketCount = 0;
PSOCKET_INFORMATION *Sockets = NULL;
LIST_ENTRY SockHelpersListHead = {NULL};
ULONG SockAsyncThreadRefCount;
HANDLE SockAsyncHelperAfdHandle;
HANDLE SockAsyncCompletionPort;
BOOLEAN SockAsyncSelectCalled;

SOCKET 
WSPAPI 
WSPSocket(
	int AddressFamily, 
	int SocketType, 
	int Protocol, 
	LPWSAPROTOCOL_INFOW lpProtocolInfo, 
	GROUP g, 
	DWORD dwFlags, 
	LPINT lpErrno)  
/*
 * FUNCTION: Creates a new socket
 * ARGUMENTS:
 *     af             = Address family
 *     type           = Socket type
 *     protocol       = Protocol type
 *     lpProtocolInfo = Pointer to protocol information
 *     g              = Reserved
 *     dwFlags        = Socket flags
 *     lpErrno        = Address of buffer for error information
 * RETURNS:
 *     Created socket, or INVALID_SOCKET if it could not be created
 */
{
	OBJECT_ATTRIBUTES			Object;
	IO_STATUS_BLOCK				IOSB;
	USHORT						SizeOfPacket;
	ULONG						SizeOfEA;
	PAFD_CREATE_PACKET			AfdPacket;
	HANDLE						Sock;
	PSOCKET_INFORMATION			Socket = NULL, PrevSocket = NULL;
    PFILE_FULL_EA_INFORMATION	EABuffer = NULL;
	PHELPER_DATA				HelperData;
	PVOID						HelperDLLContext;
	DWORD						HelperEvents;
	UNICODE_STRING				TransportName;
	UNICODE_STRING				DevName;
	LARGE_INTEGER				GroupData;
	INT                         Status;

	AFD_DbgPrint(MAX_TRACE, ("Creating Socket, getting TDI Name\n"));
	AFD_DbgPrint(MAX_TRACE, ("AddressFamily (%d)  SocketType (%d)  Protocol (%d).\n",
    AddressFamily, SocketType, Protocol));

	/* Get Helper Data and Transport */
	Status = SockGetTdiName (&AddressFamily,
	                         &SocketType,
	                         &Protocol,
	                         g,
	                         dwFlags,
	                         &TransportName,
	                         &HelperDLLContext,
	                         &HelperData,
	                         &HelperEvents);

	/* Check for error */
	if (Status != NO_ERROR) {
	    AFD_DbgPrint(MID_TRACE,("SockGetTdiName: Status %x\n", Status));
	    goto error;
	}

	/* AFD Device Name */
	RtlInitUnicodeString(&DevName, L"\\Device\\Afd\\Endpoint");

	/* Set Socket Data */
	Socket = HeapAlloc(GlobalHeap, 0, sizeof(*Socket));
	RtlZeroMemory(Socket, sizeof(*Socket));
	Socket->RefCount = 2;
	Socket->Handle = -1;
	Socket->SharedData.State = SocketOpen;
	Socket->SharedData.AddressFamily = AddressFamily;
	Socket->SharedData.SocketType = SocketType;
	Socket->SharedData.Protocol = Protocol;
	Socket->HelperContext = HelperDLLContext;
	Socket->HelperData = HelperData;
	Socket->HelperEvents = HelperEvents;
	Socket->LocalAddress = &Socket->WSLocalAddress;
	Socket->SharedData.SizeOfLocalAddress = HelperData->MaxWSAddressLength;
	Socket->RemoteAddress = &Socket->WSRemoteAddress;
	Socket->SharedData.SizeOfRemoteAddress = HelperData->MaxWSAddressLength;
	Socket->SharedData.UseDelayedAcceptance = HelperData->UseDelayedAcceptance;
	Socket->SharedData.CreateFlags = dwFlags;
	Socket->SharedData.CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
	Socket->SharedData.ServiceFlags1 = lpProtocolInfo->dwServiceFlags1;
	Socket->SharedData.ProviderFlags = lpProtocolInfo->dwProviderFlags;
	Socket->SharedData.GroupID = g;
	Socket->SharedData.GroupType = 0;
	Socket->SharedData.UseSAN = FALSE;
        Socket->SharedData.NonBlocking = FALSE; /* Sockets start blocking */
	Socket->SanData = NULL;

	/* Ask alex about this */
	if( Socket->SharedData.SocketType == SOCK_DGRAM ||
            Socket->SharedData.SocketType == SOCK_RAW ) {
            AFD_DbgPrint(MID_TRACE,("Connectionless socket\n"));
	    Socket->SharedData.ServiceFlags1 |= XP1_CONNECTIONLESS;
        }

	/* Packet Size */
	SizeOfPacket = TransportName.Length + sizeof(AFD_CREATE_PACKET) + sizeof(WCHAR);

	/* EA Size */
	SizeOfEA = SizeOfPacket + sizeof(FILE_FULL_EA_INFORMATION) + AFD_PACKET_COMMAND_LENGTH;

	/* Set up EA Buffer */
	EABuffer = HeapAlloc(GlobalHeap, 0, SizeOfEA);
        RtlZeroMemory(EABuffer, SizeOfEA);
	EABuffer->NextEntryOffset = 0;
	EABuffer->Flags = 0;
	EABuffer->EaNameLength = AFD_PACKET_COMMAND_LENGTH;
	RtlCopyMemory (EABuffer->EaName, 
					AfdCommand, 
					AFD_PACKET_COMMAND_LENGTH + 1);
	EABuffer->EaValueLength = SizeOfPacket;
	
	/* Set up AFD Packet */
	AfdPacket = (PAFD_CREATE_PACKET)(EABuffer->EaName + EABuffer->EaNameLength + 1);
	AfdPacket->SizeOfTransportName = TransportName.Length;
	RtlCopyMemory (AfdPacket->TransportName,
					TransportName.Buffer, 
					TransportName.Length + sizeof(WCHAR));
	AfdPacket->GroupID = g;

	/* Set up Endpoint Flags */
	if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS) != 0) {
		if ((SocketType != SOCK_DGRAM) && (SocketType != SOCK_RAW)) {
			goto error;			/* Only RAW or UDP can be Connectionless */
		}
		AfdPacket->EndpointFlags |= AFD_ENDPOINT_CONNECTIONLESS;
	}
	
	if ((Socket->SharedData.ServiceFlags1 & XP1_MESSAGE_ORIENTED) != 0) { 
		if (SocketType == SOCK_STREAM) {
			if ((Socket->SharedData.ServiceFlags1 & XP1_PSEUDO_STREAM) == 0) {
				goto error;		/* The Provider doesn't actually support Message Oriented Streams */
			}
		}
			AfdPacket->EndpointFlags |= AFD_ENDPOINT_MESSAGE_ORIENTED;
	}

	if (SocketType == SOCK_RAW) AfdPacket->EndpointFlags |= AFD_ENDPOINT_RAW;

	if (dwFlags & (WSA_FLAG_MULTIPOINT_C_ROOT | 
		WSA_FLAG_MULTIPOINT_C_LEAF | 
		WSA_FLAG_MULTIPOINT_D_ROOT | 
		WSA_FLAG_MULTIPOINT_D_LEAF)) {
		if ((Socket->SharedData.ServiceFlags1 & XP1_SUPPORT_MULTIPOINT) == 0) {
			goto error;			/* The Provider doesn't actually support Multipoint */
		}
		AfdPacket->EndpointFlags |= AFD_ENDPOINT_MULTIPOINT;
		if (dwFlags & WSA_FLAG_MULTIPOINT_C_ROOT) {
			if (((Socket->SharedData.ServiceFlags1 & XP1_MULTIPOINT_CONTROL_PLANE) == 0) 
				|| ((dwFlags & WSA_FLAG_MULTIPOINT_C_LEAF) != 0)) {
				goto error;		/* The Provider doesn't support Control Planes, or you already gave a leaf */
			}
			AfdPacket->EndpointFlags |= AFD_ENDPOINT_C_ROOT;
		}
		if (dwFlags & WSA_FLAG_MULTIPOINT_D_ROOT) {
			if (((Socket->SharedData.ServiceFlags1 & XP1_MULTIPOINT_DATA_PLANE) == 0) 
				|| ((dwFlags & WSA_FLAG_MULTIPOINT_D_LEAF) != 0)) {
				goto error;		/* The Provider doesn't support Data Planes, or you already gave a leaf */
			}
			AfdPacket->EndpointFlags |= AFD_ENDPOINT_D_ROOT;
		}
	}

    /* Set up Object Attributes */
    InitializeObjectAttributes (&Object,
								&DevName, 
								OBJ_CASE_INSENSITIVE | OBJ_INHERIT, 
								0, 
								0);

	/* Create the Socket as asynchronous. That means we have to block
	   ourselves after every call to NtDeviceIoControlFile. This is
	   because the kernel doesn't support overlapping synchronous I/O
	   requests (made from multiple threads) at this time (Sep 2005) */
	ZwCreateFile(&Sock,
			GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
			&Object,
			&IOSB,
			NULL,
			0,
			FILE_SHARE_READ | FILE_SHARE_WRITE,
			FILE_OPEN_IF,
			0,
			EABuffer,
			SizeOfEA);

	/* Save Handle */
	Socket->Handle = (SOCKET)Sock;

        /* XXX See if there's a structure we can reuse -- We need to do this
         * more properly. */
        PrevSocket = GetSocketStructure( (SOCKET)Sock );

        if( PrevSocket ) {
            RtlCopyMemory( PrevSocket, Socket, sizeof(*Socket) );
            RtlFreeHeap( GlobalHeap, 0, Socket );
            Socket = PrevSocket;
        }

	/* Save Group Info */
	if (g != 0) {
		GetSocketInformation(Socket, AFD_INFO_GROUP_ID_TYPE, 0, &GroupData);

		Socket->SharedData.GroupID = GroupData.u.LowPart;
		Socket->SharedData.GroupType = GroupData.u.HighPart;
	}

	/* Get Window Sizes and Save them */
	GetSocketInformation (Socket,
                              AFD_INFO_SEND_WINDOW_SIZE, 
                              &Socket->SharedData.SizeOfSendBuffer, 
                              NULL);
	GetSocketInformation (Socket, 
                              AFD_INFO_RECEIVE_WINDOW_SIZE, 
                              &Socket->SharedData.SizeOfRecvBuffer, 
                              NULL);

	/* Save in Process Sockets List */
	Sockets[SocketCount] = Socket;
	SocketCount ++;

	/* Create the Socket Context */
	CreateContext(Socket);

	/* Notify Winsock */
	Upcalls.lpWPUModifyIFSHandle(1, (SOCKET)Sock, lpErrno);

	/* Return Socket Handle */
	AFD_DbgPrint(MID_TRACE,("Success %x\n", Sock));
	return (SOCKET)Sock;

error:
	AFD_DbgPrint(MID_TRACE,("Ending %x\n", Status));

        if( lpErrno ) *lpErrno = Status;

	return INVALID_SOCKET;
}


DWORD MsafdReturnWithErrno( NTSTATUS Status, LPINT Errno, DWORD Received,
			    LPDWORD ReturnedBytes ) {
    if( ReturnedBytes ) *ReturnedBytes = 0; 
    if( Errno ) { 
        switch (Status) {
        case STATUS_CANT_WAIT: *Errno = WSAEWOULDBLOCK; break;
        case STATUS_TIMEOUT:
        case STATUS_SUCCESS: 
            /* Return Number of bytes Read */
            if( ReturnedBytes ) *ReturnedBytes = Received; break;
        case STATUS_END_OF_FILE: *Errno = WSAESHUTDOWN; *ReturnedBytes = 0; break;
        case STATUS_PENDING: *Errno = WSA_IO_PENDING; break;
        case STATUS_BUFFER_OVERFLOW: *Errno = WSAEMSGSIZE; break;
        default: {
            DbgPrint("MSAFD: Error %x is unknown\n", Status);
            *Errno = WSAEINVAL; break;
        } break;
        }
    }

    /* Success */
    return Status == STATUS_SUCCESS ? 0 : SOCKET_ERROR;
}


INT
WSPAPI
WSPCloseSocket(
  IN  SOCKET Handle,
  OUT	LPINT lpErrno)
/*
 * FUNCTION: Closes an open socket
 * ARGUMENTS:
 *     s       = Socket descriptor
 *     lpErrno = Address of buffer for error information
 * RETURNS:
 *     NO_ERROR, or SOCKET_ERROR if the socket could not be closed
 */
{
    IO_STATUS_BLOCK IoStatusBlock;
    PSOCKET_INFORMATION Socket = NULL;
    NTSTATUS Status;
    HANDLE SockEvent;
    AFD_DISCONNECT_INFO DisconnectInfo;
    SOCKET_STATE OldState;

    /* Create the Wait Event */
    Status = NtCreateEvent(&SockEvent,
                           GENERIC_READ | GENERIC_WRITE,
                           NULL,
                           1,
                           FALSE);    

    if(!NT_SUCCESS(Status)) return SOCKET_ERROR;

    /* Get the Socket Structure associate to this Socket*/
    Socket = GetSocketStructure(Handle);

    /* If a Close is already in Process, give up */
    if (Socket->SharedData.State == SocketClosed) {
        *lpErrno = WSAENOTSOCK;
        return SOCKET_ERROR;
    }

    /* Set the state to close */
    OldState = Socket->SharedData.State;
    Socket->SharedData.State = SocketClosed;
    
    /* If SO_LINGER is ON and the Socket is connected, we need to disconnect */
    /* FIXME: Should we do this on Datagram Sockets too? */
    if ((OldState == SocketConnected) && (Socket->SharedData.LingerData.l_onoff)) {
        ULONG LingerWait;
        ULONG SendsInProgress;
        ULONG SleepWait;
        
        /* We need to respect the timeout */
        SleepWait = 100;
        LingerWait = Socket->SharedData.LingerData.l_linger * 1000;
        
        /* Loop until no more sends are pending, within the timeout */
        while (LingerWait) {
            
            /* Find out how many Sends are in Progress */
            if (GetSocketInformation(Socket, 
                                     AFD_INFO_SENDS_IN_PROGRESS,
                                     &SendsInProgress,
                                     NULL)) {
                /* Bail out if anything but NO_ERROR */
                LingerWait = 0;
                break;
            }

            /* Bail out if no more sends are pending */
            if (!SendsInProgress) break;
            
            /* 
             * We have to execute a sleep, so it's kind of like
             * a block. If the socket is Nonblock, we cannot
             * go on since asyncronous operation is expected
             * and we cannot offer it
             */
            if (Socket->SharedData.NonBlocking) {
                Socket->SharedData.State = OldState;
                *lpErrno = WSAEWOULDBLOCK;
                return SOCKET_ERROR;
            }
            
            /* Now we can sleep, and decrement the linger wait */
            /* 
             * FIXME: It seems Windows does some funky acceleration
             * since the waiting seems to be longer and longer. I
             * don't think this improves performance so much, so we
             * wait a fixed time instead.
             */
            Sleep(SleepWait);
            LingerWait -= SleepWait;
        }
        
        /*
         * We have reached the timeout or sends are over.
         * Disconnect if the timeout has been reached. 
         */
        if (LingerWait <= 0) {
        
            DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0);
            DisconnectInfo.DisconnectType = AFD_DISCONNECT_ABORT;
            
            /* Send IOCTL */
            Status = NtDeviceIoControlFile((HANDLE)Handle,
                                           SockEvent,
                                           NULL,
                                           NULL,
                                           &IoStatusBlock,
                                           IOCTL_AFD_DISCONNECT,
                                           &DisconnectInfo,
                                           sizeof(DisconnectInfo),
                                           NULL,
                                           0);
        
            /* Wait for return */
            if (Status == STATUS_PENDING) {
                WaitForSingleObject(SockEvent, INFINITE);
            }         
        }
    }
    
    /* FIXME: We should notify the Helper DLL of WSH_NOTIFY_CLOSE */
    
    /* Cleanup Time! */
    Socket->HelperContext = NULL;
    Socket->SharedData.AsyncDisabledEvents = -1;
    NtClose(Socket->TdiAddressHandle);
    Socket->TdiAddressHandle = NULL;
    NtClose(Socket->TdiConnectionHandle);
    Socket->TdiConnectionHandle = NULL;

    /* Close the handle */
    NtClose((HANDLE)Handle);

    return NO_ERROR;
}

INT
WSPAPI
WSPBind(
	SOCKET Handle, 
	const struct sockaddr *SocketAddress, 
	int SocketAddressLength, 
	LPINT lpErrno)
/*
 * FUNCTION: Associates a local address with a socket
 * ARGUMENTS:
 *     s       = Socket descriptor
 *     name    = Pointer to local address
 *     namelen = Length of name

⌨️ 快捷键说明

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