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

📄 dllmain.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* Send IOCTL */
	Status = NtDeviceIoControlFile( (HANDLE)Socket->Handle,
					SockEvent,
					NULL,
					NULL,
					&IOSB,
					IOCTL_AFD_GET_INFO,
					&InfoData,
					sizeof(InfoData),
					NULL,
					0);

	/* Wait for return */
	if (Status == STATUS_PENDING) {
		WaitForSingleObject(SockEvent, INFINITE);
	}

	NtClose( SockEvent );

	return 0;

}

PSOCKET_INFORMATION 
GetSocketStructure(
	SOCKET Handle)
{
	ULONG	i;

	for (i=0; i<SocketCount; i++) {
		if (Sockets[i]->Handle == Handle) {
			return Sockets[i];
		}
	}
	return 0;
}

int CreateContext(PSOCKET_INFORMATION Socket)
{
	IO_STATUS_BLOCK				IOSB;
	SOCKET_CONTEXT				ContextData;
	NTSTATUS				Status;
	HANDLE                                  SockEvent;

	Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE,
				NULL, 1, FALSE );

	if( !NT_SUCCESS(Status) ) return -1;

	/* Create Context */
	ContextData.SharedData = Socket->SharedData;
	ContextData.SizeOfHelperData = 0;
	RtlCopyMemory (&ContextData.LocalAddress, 
					Socket->LocalAddress, 
					Socket->SharedData.SizeOfLocalAddress);
	RtlCopyMemory (&ContextData.RemoteAddress, 
					Socket->RemoteAddress, 
					Socket->SharedData.SizeOfRemoteAddress);

	/* Send IOCTL */
	Status = NtDeviceIoControlFile( (HANDLE)Socket->Handle,
					SockEvent,
					NULL,
					NULL,
					&IOSB,
					IOCTL_AFD_SET_CONTEXT,
					&ContextData,
					sizeof(ContextData),
					NULL,
					0);

	/* Wait for Completition */
	if (Status == STATUS_PENDING) {
		WaitForSingleObject(SockEvent, INFINITE);
	}
	
	NtClose( SockEvent );

	return 0;
}

BOOLEAN SockCreateOrReferenceAsyncThread(VOID)
{
	HANDLE hAsyncThread;
	DWORD AsyncThreadId;
	HANDLE AsyncEvent;
	OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
	NTSTATUS Status;

	/* Check if the Thread Already Exists */
	if (SockAsyncThreadRefCount) {
		return TRUE;
	}
	
	/* Create the Completion Port */
	if (!SockAsyncCompletionPort) {
		Status = NtCreateIoCompletion(&SockAsyncCompletionPort,
					      IO_COMPLETION_ALL_ACCESS,
					      NULL,
					      2); // Allow 2 threads only
	
		/* Protect Handle */	
		HandleFlags.ProtectFromClose = TRUE;
		HandleFlags.Inherit = FALSE;
		Status = NtSetInformationObject(SockAsyncCompletionPort,
						ObjectHandleInformation,
						&HandleFlags,
						sizeof(HandleFlags));
	}
    
	/* Create the Async Event */
	Status = NtCreateEvent(&AsyncEvent,
			       EVENT_ALL_ACCESS,
			       NULL,
			       NotificationEvent,
			       FALSE);
    
	/* Create the Async Thread */
	hAsyncThread = CreateThread(NULL,
				    0,
				    (LPTHREAD_START_ROUTINE)SockAsyncThread,
				    NULL,
				    0,
				    &AsyncThreadId);

	/* Close the Handle */
	NtClose(hAsyncThread);

	/* Increase the Reference Count */
	SockAsyncThreadRefCount++;
	return TRUE;
}

int SockAsyncThread(PVOID ThreadParam)
{
	PVOID AsyncContext;
	PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine;
	IO_STATUS_BLOCK IOSB;
	NTSTATUS Status;
                          
	/* Make the Thread Higher Priority */
	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
	
	/* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
	do {
		Status =  NtRemoveIoCompletion (SockAsyncCompletionPort,
						(PVOID*)&AsyncCompletionRoutine,
						&AsyncContext,
						&IOSB,
						NULL);
						
		/* Call the Async Function */
		if (NT_SUCCESS(Status)) {
			(*AsyncCompletionRoutine)(AsyncContext, &IOSB);
		} else {
			/* It Failed, sleep for a second */
			Sleep(1000);
		}
	} while ((Status != STATUS_TIMEOUT));

    /* The Thread has Ended */
    return 0;
}

BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID)
{
	UNICODE_STRING AfdHelper;
	OBJECT_ATTRIBUTES ObjectAttributes;
	IO_STATUS_BLOCK IoSb;
	NTSTATUS Status;
	FILE_COMPLETION_INFORMATION CompletionInfo;
	OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;

	/* First, make sure we're not already intialized */
	if (SockAsyncHelperAfdHandle) {
		return TRUE;
	}

	/* Set up Handle Name and Object */
	RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" );
	InitializeObjectAttributes(&ObjectAttributes,
				   &AfdHelper,
				   OBJ_INHERIT | OBJ_CASE_INSENSITIVE,
				   NULL,
				   NULL);

	/* Open the Handle to AFD */
	Status = NtCreateFile(&SockAsyncHelperAfdHandle,
			      GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
			      &ObjectAttributes,
			      &IoSb,
			      NULL,
			      0,
			      FILE_SHARE_READ | FILE_SHARE_WRITE,
			      FILE_OPEN_IF,
			      0,
			      NULL,
			      0);

	/* 
	 * Now Set up the Completion Port Information 
	 * This means that whenever a Poll is finished, the routine will be executed
	 */
	CompletionInfo.Port = SockAsyncCompletionPort;
	CompletionInfo.Key = SockAsyncSelectCompletionRoutine;
	Status = NtSetInformationFile(SockAsyncHelperAfdHandle,
				      &IoSb,
				      &CompletionInfo,
				      sizeof(CompletionInfo),
				      FileCompletionInformation);
				      
				      
	/* Protect the Handle */
	HandleFlags.ProtectFromClose = TRUE;
	HandleFlags.Inherit = FALSE;
	Status = NtSetInformationObject(SockAsyncCompletionPort,
					ObjectHandleInformation,
					&HandleFlags,
					sizeof(HandleFlags));


	/* Set this variable to true so that Send/Recv/Accept will know wether to renable disabled events */
	SockAsyncSelectCalled = TRUE;
	return TRUE;
}

VOID SockAsyncSelectCompletionRoutine(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
{

	PASYNC_DATA AsyncData = Context;
	PSOCKET_INFORMATION Socket;
	ULONG x;
    
	/* Get the Socket */
	Socket = AsyncData->ParentSocket;
	
	/* Check if the Sequence  Number Changed behind our back */
	if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber ){
		return;
	}

	/* Check we were manually called b/c of a failure */
	if (!NT_SUCCESS(IoStatusBlock->Status)) {
		/* FIXME: Perform Upcall */
		return;
	}

	for (x = 1; x; x<<=1) {
		switch (AsyncData->AsyncSelectInfo.Handles[0].Events & x) {
			case AFD_EVENT_RECEIVE:
				if (0 != (Socket->SharedData.AsyncEvents & FD_READ) && 0 == (Socket->SharedData.AsyncDisabledEvents & FD_READ)) {
					/* Make the Notifcation */
					(Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
								   Socket->SharedData.wMsg,
								   Socket->Handle,
								   WSAMAKESELECTREPLY(FD_READ, 0));
					/* Disable this event until the next read(); */
					Socket->SharedData.AsyncDisabledEvents |= FD_READ;
				}
				break;
			
			case AFD_EVENT_OOB_RECEIVE:
				if (0 != (Socket->SharedData.AsyncEvents & FD_OOB) && 0 == (Socket->SharedData.AsyncDisabledEvents & FD_OOB)) {
					/* Make the Notifcation */
					(Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
								   Socket->SharedData.wMsg,
								   Socket->Handle,
								   WSAMAKESELECTREPLY(FD_OOB, 0));
					/* Disable this event until the next read(); */
					Socket->SharedData.AsyncDisabledEvents |= FD_OOB;
				}
				break;
		
			case AFD_EVENT_SEND:
				if (0 != (Socket->SharedData.AsyncEvents & FD_WRITE) && 0 == (Socket->SharedData.AsyncDisabledEvents & FD_WRITE)) {
					/* Make the Notifcation */
					(Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
								   Socket->SharedData.wMsg,
								   Socket->Handle,
								   WSAMAKESELECTREPLY(FD_WRITE, 0));
					/* Disable this event until the next write(); */
					Socket->SharedData.AsyncDisabledEvents |= FD_WRITE;
				}
				break;

            /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
			case AFD_EVENT_CONNECT:
				if (0 != (Socket->SharedData.AsyncEvents & FD_CONNECT) && 0 == (Socket->SharedData.AsyncDisabledEvents & FD_CONNECT)) {
					/* Make the Notifcation */
					(Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
								   Socket->SharedData.wMsg,
								   Socket->Handle,
								   WSAMAKESELECTREPLY(FD_CONNECT, 0));
					/* Disable this event forever; */
					Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT;
				}
				break;
				
			case AFD_EVENT_ACCEPT:
				if (0 != (Socket->SharedData.AsyncEvents & FD_ACCEPT) && 0 == (Socket->SharedData.AsyncDisabledEvents & FD_ACCEPT)) {
					/* Make the Notifcation */
					(Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
								   Socket->SharedData.wMsg,
								   Socket->Handle,
								   WSAMAKESELECTREPLY(FD_ACCEPT, 0));
					/* Disable this event until the next accept(); */
					Socket->SharedData.AsyncDisabledEvents |= FD_ACCEPT;
				}
				break;

			case AFD_EVENT_DISCONNECT:
			case AFD_EVENT_ABORT:
			case AFD_EVENT_CLOSE:
				if (0 != (Socket->SharedData.AsyncEvents & FD_CLOSE) && 0 == (Socket->SharedData.AsyncDisabledEvents & FD_CLOSE)) {
					/* Make the Notifcation */
					(Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
								   Socket->SharedData.wMsg,
								   Socket->Handle,
								   WSAMAKESELECTREPLY(FD_CLOSE, 0));
					/* Disable this event forever; */
					Socket->SharedData.AsyncDisabledEvents |= FD_CLOSE;
				}
				break;

			/* FIXME: Support QOS */
		}
	}
	
	/* Check if there are any events left for us to check */
	if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 ) {
		return;
	}

	/* Keep Polling */
	SockProcessAsyncSelect(Socket, AsyncData);
	return;
}

VOID SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, PASYNC_DATA AsyncData)
{

	ULONG lNetworkEvents;
	NTSTATUS Status;

	/* Set up the Async Data Event Info */
	AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF;
	AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF;
	AsyncData->AsyncSelectInfo.HandleCount = 1;
	AsyncData->AsyncSelectInfo.Exclusive = TRUE;
	AsyncData->AsyncSelectInfo.Handles[0].Handle = Socket->Handle;
	AsyncData->AsyncSelectInfo.Handles[0].Events = 0;

	/* Remove unwanted events */
	lNetworkEvents = Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents);

	/* Set Events to wait for */
	if (lNetworkEvents & FD_READ) {
		AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE;
	}

	if (lNetworkEvents & FD_WRITE) {
		AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND;
	}

	if (lNetworkEvents & FD_OOB) {
	        AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE;
	}

	if (lNetworkEvents & FD_ACCEPT) {
		AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT;
	}

     /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
	if (lNetworkEvents & FD_CONNECT) {
		AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL;
	}

	if (lNetworkEvents & FD_CLOSE) {
		AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT;
	}

	if (lNetworkEvents & FD_QOS) {
		AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS;
	}

	if (lNetworkEvents & FD_GROUP_QOS) {
		AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS;
	}
	
	/* Send IOCTL */
	Status = NtDeviceIoControlFile (SockAsyncHelperAfdHandle,
					NULL,
					NULL,
					AsyncData,
					&AsyncData->IoStatusBlock,
					IOCTL_AFD_SELECT,
					&AsyncData->AsyncSelectInfo,
					sizeof(AsyncData->AsyncSelectInfo),
					&AsyncData->AsyncSelectInfo,
					sizeof(AsyncData->AsyncSelectInfo));

	/* I/O Manager Won't call the completion routine, let's do it manually */
	if (NT_SUCCESS(Status)) {
		return;
	} else {
		AsyncData->IoStatusBlock.Status = Status;
		SockAsyncSelectCompletionRoutine(AsyncData, &AsyncData->IoStatusBlock);
	}
}

VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
{
	PASYNC_DATA AsyncData = Context;
	BOOL FreeContext = TRUE;
	PSOCKET_INFORMATION Socket;

	/* Get the Socket */	
	Socket = AsyncData->ParentSocket;

	/* If someone closed it, stop the function */
	if (Socket->SharedData.State != SocketClosed) {
		/* Check if the Sequence Number changed by now, in which case quit */
		if (AsyncData->SequenceNumber == Socket->SharedData.SequenceNumber) {
			/* Do the actuall select, if needed */
			if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents))) {
				SockProcessAsyncSelect(Socket, AsyncData);
				FreeContext = FALSE;
			}
		}
	}
	
	/* Free the Context */
	if (FreeContext) {
		HeapFree(GetProcessHeap(), 0, AsyncData);
	}

	return;
}

VOID
SockReenableAsyncSelectEvent (
    IN PSOCKET_INFORMATION Socket,
    IN ULONG Event
    )
{
    PASYNC_DAT

⌨️ 快捷键说明

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