Ejemplo n.º 1
0
VOID
PrimaryAgentThreadProc(
	IN 	PPRIMARY	Primary
	)
{
	BOOLEAN			primaryAgentThreadExit = FALSE;
	ULONG			listenSocketIndex;
	PKWAIT_BLOCK	waitBlocks;

	SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
				("PrimaryAgentThreadProc: Start\n"));

	Primary->Agent.Flags |= PRIMARY_AGENT_INITIALIZING;
	
	//
	// Allocate wait block
	//
	 waitBlocks = ExAllocatePool(NonPagedPool, sizeof(KWAIT_BLOCK) * MAXIMUM_WAIT_OBJECTS);
	 if(waitBlocks == NULL) {
		 ASSERT(LFS_REQUIRED);
		 PsTerminateSystemThread(STATUS_INSUFFICIENT_RESOURCES);
	 }

	for(listenSocketIndex=0; listenSocketIndex<MAX_SOCKETLPX_INTERFACE; listenSocketIndex++)
		KeInitializeEvent(
					&Primary->Agent.ListenSocket[listenSocketIndex].TdiListenContext.CompletionEvent, 
					NotificationEvent, 
					FALSE
					);

	BindListenSockets(
		Primary
		);

	Primary->Agent.Flags |= PRIMARY_AGENT_START;
				
	KeSetEvent(&Primary->Agent.ReadyEvent, IO_DISK_INCREMENT, FALSE);


	while(primaryAgentThreadExit == FALSE)
	{
		PKEVENT				events[MAXIMUM_WAIT_OBJECTS];
		LONG				eventCnt;

		ULONG				i;

		LARGE_INTEGER		timeOut;
		NTSTATUS			ntStatus;
		PLIST_ENTRY			primaryAgentRequestEntry;


		ASSERT(MAX_SOCKETLPX_INTERFACE + 1 <= MAXIMUM_WAIT_OBJECTS);

		eventCnt = 0;
		events[eventCnt++] = &Primary->Agent.RequestEvent;

		if(!BooleanFlagOn(Primary->Agent.Flags, PRIMARY_AGENT_SHUTDOWN))
		{
			for(i=0; i<MAX_SOCKETLPX_INTERFACE; i++)
			{
				if(Primary->Agent.ListenSocket[i].TdiListenContext.Irp &&
					Primary->Agent.ListenSocket[i].Active)
				{
					events[eventCnt++] = &Primary->Agent.ListenSocket[i].TdiListenContext.CompletionEvent;
				}
				else
				{
					// events[eventCnt++] = NULL; // I wanna set NULL, But It's not Work
					events[eventCnt++] = &Primary->Agent.ListenSocket[i].TdiListenContext.CompletionEvent;
				}
			}

			ASSERT(eventCnt == MAX_SOCKETLPX_INTERFACE + 1);
		}

		timeOut.QuadPart = - 5 * HZ;
		ntStatus = KeWaitForMultipleObjects(
					eventCnt,
					events,
					WaitAny,
					Executive,
					KernelMode,
					TRUE,
					&timeOut,
					waitBlocks
				);

		if(ntStatus == STATUS_TIMEOUT) 
		{
			continue;
		}

		SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE,
			("PrimaryAgentThreadProc: NTSTATUS:%lu\n", ntStatus));
		

		if(!NT_SUCCESS(ntStatus) || ntStatus >= eventCnt)
		{
			ASSERT(LFS_UNEXPECTED);
			SetFlag(Primary->Agent.Flags, PRIMARY_AGENT_ERROR);

			primaryAgentThreadExit = TRUE;

			continue;
		}

		KeClearEvent(events[ntStatus]);

		if(0 == ntStatus)
		{
			SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE,
					("PrimaryAgentThreadProc: RequestEvent received\n"));

			while(primaryAgentRequestEntry = 
					ExInterlockedRemoveHeadList(
							&Primary->Agent.RequestQueue,
							&Primary->Agent.RequestQSpinLock
							)
				) 
			{
				PPRIMARY_AGENT_REQUEST		primaryAgentRequest;

				primaryAgentRequest = CONTAINING_RECORD(
										primaryAgentRequestEntry,
										PRIMARY_AGENT_REQUEST,
										ListEntry
										);
	
				switch(primaryAgentRequest->RequestType) 
				{

				case PRIMARY_AGENT_REQ_DISCONNECT:
				{
					CloseListenSockets(
						Primary,
						FALSE
						);
				
					break;
				}

				case PRIMARY_AGENT_REQ_SHUTDOWN:
				{
					CloseListenSockets(
						Primary,
						TRUE
						);				
					SetFlag(Primary->Agent.Flags, PRIMARY_AGENT_SHUTDOWN);
					break;
				}

				case PRIMARY_AGENT_REQ_DOWN:

					primaryAgentThreadExit = TRUE;
					break;

				//
				//	added to adapt network card changes.
				//
				case PRIMARY_AGENT_REQ_NIC_DISABLED:
				
					SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
						("PrimaryAgentThreadProc: PRIMARY_AGENT_REQ_NIC_DISABLED\n"));
					PrimaryAgentNICDisabled(Primary, &primaryAgentRequest->AddressList);
				
					break;

				case PRIMARY_AGENT_REQ_NIC_ENABLED:
				
					SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE,
						("PrimaryAgentThreadProc: PRIMARY_AGENT_REQ_NIC_ENABLED\n"));
					PrimaryAgentNICEnabled(Primary, &primaryAgentRequest->AddressList);
				
					break;

				default:
		
					ASSERT(LFS_BUG);
					SetFlag(Primary->Agent.Flags, PRIMARY_AGENT_ERROR);

					break;
				}

				if(primaryAgentRequest->Synchronous == TRUE)
						KeSetEvent(&primaryAgentRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE);
				else
					DereferencePrimaryAgentRequest(
						primaryAgentRequest
						);
			}

			continue;	
		}

		ASSERT(1 <= ntStatus && ntStatus < eventCnt); // LpxEvent 
		
		if(	1 <= ntStatus &&
			ntStatus <= MAX_SOCKETLPX_INTERFACE
			) // Connected 
		{
			NTSTATUS		tdiStatus;
			HANDLE			listenFileHandle;
			PFILE_OBJECT	listenFileObject;
			HANDLE			connFileHandle;
			PFILE_OBJECT	connFileObject;
			PPRIMARY_LISTEN_SOCKET	listenSocket;
			LPX_ADDRESS		remoteAddress;

			listenSocket = &Primary->Agent.ListenSocket[ntStatus-1];

			//
			//	retreive a connection file and remote address.
			//
			connFileHandle = listenSocket->ListenFileHandle;
			connFileObject = listenSocket->ListenFileObject;
			RtlCopyMemory(&remoteAddress, &listenSocket->TdiListenContext.RemoteAddress, sizeof(LPX_ADDRESS));

			listenSocket->TdiListenContext.Irp = NULL;
			listenSocket->ListenFileHandle = NULL;
			listenSocket->ListenFileObject = NULL;
			KeClearEvent(&listenSocket->TdiListenContext.CompletionEvent);

			if(!listenSocket->Active) 
			{
				SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
						("ListenSocket is not active. Maybe a NIC disabled.\n"));
				continue;

			} 
			else if(listenSocket->TdiListenContext.Status != STATUS_SUCCESS) 
			{
				LpxTdiCloseAddress (
					listenSocket->AddressFileHandle, 
					listenSocket->AddressFileObject
					);

				listenSocket->Active = FALSE;
				Primary->Agent.ActiveListenSocketCount --;

				SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
						("Listen IRP #%d failed.\n", ntStatus));
				continue;
			}

			SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
					("PrimaryAgentThreadProc: Connect from %02X:%02X:%02X:%02X:%02X:%02X 0x%4X\n",
						listenSocket->TdiListenContext.RemoteAddress.Node[0], listenSocket->TdiListenContext.RemoteAddress.Node[1],
						listenSocket->TdiListenContext.RemoteAddress.Node[2], listenSocket->TdiListenContext.RemoteAddress.Node[3],
						listenSocket->TdiListenContext.RemoteAddress.Node[4], listenSocket->TdiListenContext.RemoteAddress.Node[5],
						NTOHS(listenSocket->TdiListenContext.RemoteAddress.Port)
						));

			//
			//	Make a new listen connection first of all to get another connection.
			//	It must be earlier than start a session that takes long time.
			//	Primary cannot accept a connection before it creates a new listen object.
			//
			tdiStatus = MakeConnectionObject(
							listenSocket->AddressFileHandle,
							listenSocket->AddressFileObject,
							&listenFileHandle,
							&listenFileObject
							);

			if(!NT_SUCCESS(tdiStatus)) 
			{
				ASSERT(LPX_BUG);
				LpxTdiCloseAddress (
					listenSocket->AddressFileHandle, 
					listenSocket->AddressFileObject
					);

				listenSocket->Active = FALSE;
				Primary->Agent.ActiveListenSocketCount --;
	
				goto start_session;
			}

			listenSocket->ListenFileHandle = listenFileHandle;
			listenSocket->ListenFileObject = listenFileObject;

			listenSocket->Flags	= TDI_QUERY_ACCEPT;
			tdiStatus = LpxTdiListenWithCompletionEvent(
							listenSocket->ListenFileObject,
							&listenSocket->TdiListenContext,
							&listenSocket->Flags
							);

			if(!NT_SUCCESS(tdiStatus)) 
			{
				ASSERT(LPX_BUG);
				LpxTdiDisassociateAddress(listenFileObject);
				LpxTdiCloseConnection(listenFileHandle, listenFileObject);
				LpxTdiCloseAddress (
					listenSocket->AddressFileHandle, 
					listenSocket->AddressFileObject
					);
				listenSocket->Active = FALSE;
				Primary->Agent.ActiveListenSocketCount --;
	
			}

start_session:
			//
			//	start a session.
			//
			Primary_AcceptConnection(Primary, connFileHandle, connFileObject, ntStatus-1, &remoteAddress);
			
			continue;
		}
	}

	for(listenSocketIndex=0; listenSocketIndex<MAX_SOCKETLPX_INTERFACE; listenSocketIndex++)
		KeClearEvent(&Primary->Agent.ListenSocket[listenSocketIndex].TdiListenContext.CompletionEvent);

	//
	// Free wait blocks
	//

	ExFreePool(waitBlocks);

	SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
				("PrimaryAgentThreadProc: PsTerminateSystemThread\n"));
	
	Primary->Agent.Flags |= PRIMARY_AGENT_TERMINATED;

	PsTerminateSystemThread(STATUS_SUCCESS);
}
Ejemplo n.º 2
0
VOID
Primary_Close (
	IN PPRIMARY	Primary
	)
{
	ULONG		listenSocketIndex;
	

	SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
		("Primary_Close: Entered primary = %p\n", Primary));

	for(listenSocketIndex=0; listenSocketIndex<MAX_SOCKETLPX_INTERFACE; listenSocketIndex++)
	{
	    PLIST_ENTRY	primarySessionListEntry;
		BOOLEAN		found   = FALSE;


		if(Primary->Agent.ListenSocket[listenSocketIndex].Active != TRUE)
			continue;
		
		while(primarySessionListEntry = 
				ExInterlockedRemoveHeadList(
						&Primary->PrimarySessionQueue[listenSocketIndex],
						&Primary->PrimarySessionQSpinLock[listenSocketIndex]
						)
			) 
		{
			PPRIMARY_SESSION primarySession;
		 
			primarySession = CONTAINING_RECORD (primarySessionListEntry, PRIMARY_SESSION, ListEntry);
			InitializeListHead(primarySessionListEntry);
			PrimarySession_Close(primarySession);
		}
	}

	if(Primary->Agent.ThreadHandle == NULL)
	{
		ASSERT(LFS_BUG);
		Primary_Dereference(Primary);

		return;
	}

	ASSERT(Primary->Agent.ThreadObject != NULL);

	if(Primary->Agent.Flags & PRIMARY_AGENT_TERMINATED)
	{
		ObDereferenceObject(Primary->Agent.ThreadObject);

		Primary->Agent.ThreadHandle = NULL;
		Primary->Agent.ThreadObject = NULL;

	} else
	{
		PPRIMARY_AGENT_REQUEST		primaryAgentRequest;
		NTSTATUS					ntStatus;
		LARGE_INTEGER				timeOut;
	
		
		primaryAgentRequest = AllocPrimaryAgentRequest(FALSE);
		primaryAgentRequest->RequestType = PRIMARY_AGENT_REQ_DISCONNECT;

		QueueingPrimaryAgentRequest(
			Primary,
			primaryAgentRequest
			);

		primaryAgentRequest = AllocPrimaryAgentRequest (FALSE);
		primaryAgentRequest->RequestType = PRIMARY_AGENT_REQ_DOWN;

		QueueingPrimaryAgentRequest(
			Primary,
			primaryAgentRequest
			);

		timeOut.QuadPart = - LFS_TIME_OUT;		// 10 sec
		ntStatus = KeWaitForSingleObject(
						Primary->Agent.ThreadObject,
						Executive,
						KernelMode,
						FALSE,
						&timeOut
						);

		ASSERT(ntStatus == STATUS_SUCCESS);

		if(ntStatus == STATUS_SUCCESS) 
		{
		    SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
							("Primary_Close: thread stoped\n"));

			ObDereferenceObject(Primary->Agent.ThreadObject);

			Primary->Agent.ThreadHandle = NULL;
			Primary->Agent.ThreadObject = NULL;
		
		} else
		{
			ASSERT(LFS_BUG);
			return;
		}
	}

	Primary_Dereference(Primary);

	return;
}
Ejemplo n.º 3
0
//前面说到为每一个磁盘设备对象生成了一个系统线程,用来处理Irp
VOID
FileDiskThread (
    IN PVOID Context
    )
{
    PDEVICE_OBJECT      device_object;
    PDEVICE_EXTENSION   device_extension;
    PLIST_ENTRY         request;
    PIRP                irp;
    PIO_STACK_LOCATION  io_stack;
    PUCHAR              system_buffer;
    PUCHAR              buffer;

    ASSERT(Context != NULL);

    device_object = (PDEVICE_OBJECT) Context;

    device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension;

    KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);

    for (;;)
    {
        KeWaitForSingleObject(
            &device_extension->request_event,
            Executive,
            KernelMode,
            FALSE,
            NULL
            );

        if (device_extension->terminate_thread)
        {
            PsTerminateSystemThread(STATUS_SUCCESS);
        }

        while (request = ExInterlockedRemoveHeadList(
            &device_extension->list_head,
            &device_extension->list_lock
            ))
        {
            irp = CONTAINING_RECORD(request, IRP, Tail.Overlay.ListEntry);

            io_stack = IoGetCurrentIrpStackLocation(irp);

            switch (io_stack->MajorFunction)
            {
            case IRP_MJ_READ:
                system_buffer = (PUCHAR) MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority);
                if (system_buffer == NULL)
                {
                    irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
                    irp->IoStatus.Information = 0;
                    break;
                }
                buffer = (PUCHAR) ExAllocatePool(PagedPool, io_stack->Parameters.Read.Length);
                if (buffer == NULL)
                {
                    irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
                    irp->IoStatus.Information = 0;
                    break;
                }
                ZwReadFile(
                    device_extension->file_handle,
                    NULL,
                    NULL,
                    NULL,
                    &irp->IoStatus,
                    buffer,
                    io_stack->Parameters.Read.Length,
                    &io_stack->Parameters.Read.ByteOffset,
                    NULL
                    );
                RtlCopyMemory(system_buffer, buffer, io_stack->Parameters.Read.Length);
                ExFreePool(buffer);
                break;

            case IRP_MJ_WRITE:
                if ((io_stack->Parameters.Write.ByteOffset.QuadPart +
                     io_stack->Parameters.Write.Length) >
                     device_extension->file_size.QuadPart)
                {
                    irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
                    irp->IoStatus.Information = 0;
                }
                ZwWriteFile(
                    device_extension->file_handle,
                    NULL,
                    NULL,
                    NULL,
                    &irp->IoStatus,
                    MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority),
                    io_stack->Parameters.Write.Length,
                    &io_stack->Parameters.Write.ByteOffset,
                    NULL
                    );
                break;

            case IRP_MJ_DEVICE_CONTROL:
                switch (io_stack->Parameters.DeviceIoControl.IoControlCode)
                {
                case IOCTL_FILE_DISK_OPEN_FILE:

                    SeImpersonateClient(device_extension->security_client_context, NULL);

                    irp->IoStatus.Status = FileDiskOpenFile(device_object, irp);

                    PsRevertToSelf();

                    break;

                case IOCTL_FILE_DISK_CLOSE_FILE:
                    irp->IoStatus.Status = FileDiskCloseFile(device_object, irp);
                    break;

                default:
                    irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
                }
                break;

            default:
                irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
            }

            IoCompleteRequest(
                irp,
                (CCHAR) (NT_SUCCESS(irp->IoStatus.Status) ?
                IO_DISK_INCREMENT : IO_NO_INCREMENT)
                );
        }
    }
}
Ejemplo n.º 4
0
VOID
RedirDataGramSvrThreadProc (
	PLFSDGRAMSVR_CTX	SvrCtx
	) 
{
	BOOLEAN				bret;
	NTSTATUS			status;
	LFSDG_Socket		ServerDatagramSocket;
	PKEVENT				Evts[3];
	PLIST_ENTRY			listEntry;
	PLFSDG_PKT			pkt;

	SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, 
				   ("[LFS] RedirDataGramSvrThreadProc: Initializing Redirection Datagram server...\n") );

	// Open server datagram port

	status = LfsOpenDGSocket( &ServerDatagramSocket, DEFAULT_DATAGRAM_SVRPORT );

	if (status == STATUS_SUCCESS) {

		// register Datagram handler

		status = LfsRegisterDatagramRecvHandler( &ServerDatagramSocket,
												 LfsSvrDatagramRecvHandler,
												 SvrCtx );
	}

	Evts[0] = &SvrCtx->ShutdownEvent;
	Evts[1] = &SvrCtx->DatagramRecvEvent;
	Evts[2] = &SvrCtx->NetworkEvent;

	SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, 
					("[LFS] RedirDataGramSvrThreadProc: Redirection Datagram server started...\n") );

	// Main loop...

	while(1) {
	
		status = KeWaitForMultipleObjects( 3,
										   Evts,
										   WaitAny,
										   Executive,
										   KernelMode,
										   TRUE,
										   NULL,
										   NULL );

		SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, 
					   ("[LFS] RedirDataGramSvrThreadProc: NTSTATUS:%lu\n", status) );

		if (status == 0) {

			SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, 
						   ("[LFS] RedirDataGramSvrThreadProc: ShutDown event received. NTSTATUS:%lu\n", status) );

			break;
		
		} else if (status == 1) {
			
			//	Datagram received.
			
			KeClearEvent( &SvrCtx->DatagramRecvEvent );

			SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, 
						   ("[LFS] RedirDataGramSvrThreadProc: DatagramRecv event received. NTSTATUS:%lu\n", status) );
		
		} else if (status == 2) {
			
			// Renew server datagram port
			
			SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, 
						   ("[LFS] RedirDataGramSvrThreadProc: Networking event received. NTSTATUS:%lu\n", status) );

			KeClearEvent( &SvrCtx->NetworkEvent );

			LfsCloseDGSocket( &ServerDatagramSocket );

			status = LfsOpenDGSocket( &ServerDatagramSocket, DEFAULT_DATAGRAM_SVRPORT );
			
			if (status == STATUS_SUCCESS) {
				
				// register Datagram handler
				
				status = LfsRegisterDatagramRecvHandler( &ServerDatagramSocket,
														 LfsSvrDatagramRecvHandler,
														 SvrCtx );
			}

			continue;

		} else {
			
			SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, 
						   ("[LFS] RedirDataGramSvrThreadProc: KeWaitForMultipleObjects() failed. NTSTATUS:%lu\n", status) );
			break;
		}

		//	get packets to the dispatch routine.

		while (1) {

			listEntry = ExInterlockedRemoveHeadList( &SvrCtx->RecvDGPktQueue,
													 &SvrCtx->RecvDGPktQSpinLock );

			if (!listEntry) {
			
				SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, 
							   ("[LFS] RedirDataGramSvrThreadProc: Datagram queue empty. back to waiting mode.\n") );
				break;
			}

			pkt = CONTAINING_RECORD( listEntry, LFSDG_PKT, PktListEntry );

			bret = DispatchDGReqPkt( SvrCtx, pkt );

			if (FALSE == bret) {
			
				SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, ( "[LFS] RedirDataGramSvrThreadProc: Don't send a reply.\n") );

			} else {

				SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, ( "[LFS] RedirDataGramSvrThreadProc: Send a reply.\n") );

				status = LfsSendDatagram( &ServerDatagramSocket, pkt, &pkt->SourceAddr );

				if (status != STATUS_SUCCESS) {

					SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, ( "[LFS] RedirDataGramSvrThreadProc: LfsSendDatagram() failed.\n"));
				}
			}

			//	dereference the datagram packet
	
			LfsDereferenceDGPkt( pkt );
		}
	}

	LfsCloseDGSocket( &ServerDatagramSocket );

	//	free datagram packets.

	while (1) {

		listEntry = ExInterlockedRemoveHeadList( &SvrCtx->RecvDGPktQueue,
												 &SvrCtx->RecvDGPktQSpinLock );
		
		if (!listEntry) {
		
			SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, 
						   ("[LFS] RedirDataGramSvrThreadProc: Cleared datagram packets.\n") );
			break;
		}

		pkt = CONTAINING_RECORD(listEntry, LFSDG_PKT, PktListEntry);
		
		LfsDereferenceDGPkt( pkt );
	}

	SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, ( "[LFS] RedirDataGramSvrThreadProc: terminated..\n") );
	PsTerminateSystemThread(0);

	return;
}
Ejemplo n.º 5
0
VOID
PrimarySessionThreadProc (
	IN PPRIMARY_SESSION PrimarySession
	)
{
	BOOLEAN		primarySessionTerminate = FALSE;
	NTSTATUS	status;
	_U16		slotIndex;
	PLIST_ENTRY	primarySessionRequestEntry;


	ASSERT( SESSION_SLOT_COUNT == 1 );
	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	DebugTrace2( 0, Dbg2, ("PrimarySessionThreadProc: Start PrimarySession = %p\n", PrimarySession) );
	
	PrimarySession_Reference( PrimarySession );

	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_INITIALIZING );
	
	InitializeListHead( &PrimarySession->Thread.OpenedFileQueue );
	KeInitializeSpinLock( &PrimarySession->Thread.OpenedFileQSpinLock );

	KeInitializeEvent( &PrimarySession->Thread.WorkCompletionEvent, NotificationEvent, FALSE );

	PrimarySession->SessionContext.SessionSlotCount = SESSION_SLOT_COUNT;

	for (slotIndex = 0; slotIndex < PrimarySession->SessionContext.SessionSlotCount; slotIndex ++) {

		PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT;
		PrimarySession->Thread.IdleSlotCount ++;
	}

	ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_INITIALIZING );
	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_START );
	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );

	KeSetEvent( &PrimarySession->ReadyEvent, IO_DISK_INCREMENT, FALSE );

	status = LpxTdiRecvWithCompletionEvent( PrimarySession->ConnectionFileObject,
										    &PrimarySession->Thread.TdiReceiveContext,
										    (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader,
										    sizeof(NDFS_REQUEST_HEADER),
										    0,
										    NULL,
										    NULL );

	if (NT_SUCCESS(status)) {

		PrimarySession->Thread.TdiReceiving = TRUE;
	
	} else {
	
		ASSERT( NDASFAT_BUG );
		SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
		primarySessionTerminate = TRUE;
	} 

	while (primarySessionTerminate == FALSE) {

		PKEVENT				events[3];
		LONG				eventCount;
		NTSTATUS			eventStatus;
		LARGE_INTEGER		timeOut;


		ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

		eventCount = 0;

		events[eventCount++] = &PrimarySession->RequestEvent;

		if (!FlagOn(PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING)) {

			events[eventCount++] = &PrimarySession->Thread.WorkCompletionEvent;

			if (FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN)) {
			
				if (PrimarySession->Thread.IdleSlotCount == PrimarySession->SessionContext.SessionSlotCount) {

					CloseOpenFiles( PrimarySession, TRUE );
				
					KeSetEvent( &PrimarySession->Thread.ShutdownPrimarySessionRequest->CompleteEvent, 
								IO_DISK_INCREMENT, 
								FALSE );

					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT );
					ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN );
				}
			}	 
		
			if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT)) {

				if (PrimarySession->Thread.TdiReceiving == TRUE) {

					ASSERT( PrimarySession->Thread.IdleSlotCount != 0 );
					events[eventCount++] = &PrimarySession->Thread.TdiReceiveContext.CompletionEvent;
				}
			}

			ASSERT( eventCount <= THREAD_WAIT_OBJECTS );
		}

		timeOut.QuadPart = -5*HZ;
		eventStatus = KeWaitForMultipleObjects( eventCount, 
												events, 
												WaitAny, 
												Executive, 
												KernelMode,
												TRUE,
												&timeOut,
												NULL );

#if 0
		if (!FlagOn(PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING)) {

			if (eventStatus == STATUS_TIMEOUT || eventStatus == 2) {
			
				if (PrimarySession->Thread.SessionState == SESSION_TREE_CONNECT) {
				
					ASSERT( PrimarySession->NetdiskPartition );
				
					if (!(PrimarySession->NetdiskPartition->NetdiskVolume[NETDISK_PRIMARY].VolumeState == VolumeMounted || 
						  PrimarySession->NetdiskPartition->NetdiskVolume[NETDISK_SECONDARY2PRIMARY].VolumeState == VolumeMounted)) {

						DebugTrace2( 0, Dbg2,
									   ("Netdisk Volume is unmounted\n") );

						if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT))
							primarySessionTerminate = TRUE;
		
						continue;
					}
				}
			}
		}

#endif

		if (eventStatus == STATUS_TIMEOUT) {

			continue;
		}

		if (!NT_SUCCESS(eventStatus) || eventStatus >= eventCount) {

			NDASFAT_ASSERT( FALSE );
			SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
			primarySessionTerminate = TRUE;
			continue;
		}
		
		KeClearEvent( events[eventStatus] );

		if (eventStatus == 0) {

			while (primarySessionRequestEntry = ExInterlockedRemoveHeadList( &PrimarySession->RequestQueue,
																			 &PrimarySession->RequestQSpinLock)) {

				PPRIMARY_SESSION_REQUEST	primarySessionRequest;
			
				primarySessionRequest = CONTAINING_RECORD( primarySessionRequestEntry,
														   PRIMARY_SESSION_REQUEST,
														   ListEntry );

				if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT ||
					primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE) {

					DebugTrace2( 0, Dbg2, 
								   ((primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT) ?
								   ("PRIMARY_SESSION_REQ_DISCONNECT: DisconnectFromSecondary\n") :
									("PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE: DisconnectFromSecondary\n")) );

					if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) {

						DisconnectFromSecondary( PrimarySession );
						ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
					}

					if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE)
						primarySessionTerminate = TRUE;

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );

				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DOWN) {
					
					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_STOPED );
					primarySessionTerminate = TRUE;

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );
				
				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_SHUTDOWN) {

					DebugTrace2( 0, Dbg, ("PrimarySessionThreadProc: PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN\n") );
					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN );

					ASSERT (primarySessionRequest->Synchronous == TRUE);

					PrimarySession->Thread.ShutdownPrimarySessionRequest = primarySessionRequest;

					if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) {

						DisconnectFromSecondary( PrimarySession );
						ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
					}

				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_STOPPING) {

					SetFlag( PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING );
					
					if (PrimarySession->IsLocalAddress == FALSE) {

						CloseOpenFiles( PrimarySession, FALSE );
					}

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );

				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_CANCEL_STOPPING) {

					ClearFlag( PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING );

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );

				} else {

					ASSERT( NDASFAT_BUG );
					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
				}
			}

			continue;
		
		} else if (eventStatus == 1) {

			while (TRUE) {
	
				for (slotIndex = 0; slotIndex < PrimarySession->SessionContext.SessionSlotCount; slotIndex ++) {

					if (PrimarySession->Thread.SessionSlot[slotIndex].State == SLOT_FINISH)
						break;
				}

				if (slotIndex == PrimarySession->SessionContext.SessionSlotCount)
					break;
			
				PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT;
				PrimarySession->Thread.IdleSlotCount ++;

				if (PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS) {

					PNDFS_REPLY_HEADER		ndfsReplyHeader;

					ndfsReplyHeader = (PNDFS_REPLY_HEADER)PrimarySession->Thread.SessionSlot[slotIndex].ReplyMessageBuffer;
										
					PrimarySession->Thread.SessionSlot[slotIndex].Status
						= SendNdfsWinxpMessage( PrimarySession,
												ndfsReplyHeader,
												PrimarySession->Thread.SessionSlot[slotIndex].NdfsWinxpReplyHeader,
												PrimarySession->Thread.SessionSlot[slotIndex].ReplyDataSize,
												slotIndex );

				}
	
				if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool) {

					ExFreePool(PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool);	
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool = NULL;
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
				}
		
				if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool) {

					ExFreePool(PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool);	
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool = NULL;
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
				}

				if (!(PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS || 
					  PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_PENDING)) {

					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );

#if 0
					if (PrimarySession->NetdiskPartition) {

						NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
															   PrimarySession,
															   PrimarySession->NetdiskPartition, 
															   PrimarySession->IsLocalAddress );

						PrimarySession->NetdiskPartition = NULL;
					}
#endif

					primarySessionTerminate = TRUE;
					break;		
				 }
				
				if (PrimarySession->Thread.SessionState == SESSION_CLOSED) {

#if 0
					if (PrimarySession->NetdiskPartition) {

						NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
															   PrimarySession,
															   PrimarySession->NetdiskPartition, 
															   PrimarySession->IsLocalAddress );
	
						PrimarySession->NetdiskPartition = NULL;
					}
#endif

					primarySessionTerminate = TRUE;
					break;		
				}

				if (PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS) {

					if (PrimarySession->Thread.TdiReceiving == FALSE) {

						status = LpxTdiRecvWithCompletionEvent( PrimarySession->ConnectionFileObject,
															    &PrimarySession->Thread.TdiReceiveContext,
															    (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader,
															    sizeof(NDFS_REQUEST_HEADER),
															    0,
															    NULL,
															    NULL );

						if (!NT_SUCCESS(status)) {

							ASSERT( NDASFAT_BUG );

							SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
							primarySessionTerminate = TRUE;
							break;
						}
						
						PrimarySession->Thread.TdiReceiving = TRUE;
					}
				}
			}		
		
			continue;
		
		} else {

			ASSERT( eventStatus == 2 );  // Receive Event
			ASSERT( !FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT) &&
				    !FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN) );

			if (PrimarySession->Thread.TdiReceiveContext.Result != sizeof(NDFS_REQUEST_HEADER)) {

				DebugTrace2( 0, Dbg,
							   ("DispatchRequest: Disconnected, PrimarySession = Data received:%d\n",
							   PrimarySession->Thread.TdiReceiveContext.Result) );

				SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
				primarySessionTerminate = TRUE;
				
				continue;		
			}

			PrimarySession->Thread.TdiReceiving = FALSE;

#if 0
			if (PrimarySession->NetdiskPartition) {

				PENABLED_NETDISK EnabledNetdisk = PrimarySession->NetdiskPartition->EnabledNetdisk;
				
				ASSERT( EnabledNetdisk );

				if (NetdiskManager_IsStoppedNetdisk(GlobalLfs.NetdiskManager, EnabledNetdisk)) {
				    
					DebugTrace2( 0, Dbg2,
								   ("PrimarySessionThread: %p Netdisk is stopped\n", PrimarySession) );

					DebugTrace2( 0, Dbg2, ("DispatchWinXpRequest: Netdisk is stopped.\n") );

					if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) { 
					
						// no other way to notify secondary about unmount without break backward compatability.
						
						DebugTrace2( 0, Dbg2, ("IsStoppedNetdisk: DisconnectFromSecondary\n") );
						DisconnectFromSecondary( PrimarySession );
						ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
					}

					primarySessionTerminate = TRUE;
					continue;
				}
			} 

#endif

			status = DispatchRequest( PrimarySession );

			if (!(status == STATUS_SUCCESS || status == STATUS_PENDING)) {

				primarySessionTerminate = TRUE;
				continue;		
			}

			if (PrimarySession->Thread.SessionState == SESSION_CLOSED) {

				primarySessionTerminate = TRUE;
				continue;		
			}

			if (status == STATUS_SUCCESS) {

				if (PrimarySession->Thread.TdiReceiving == FALSE) {

					status = LpxTdiRecvWithCompletionEvent( PrimarySession->ConnectionFileObject,
														    &PrimarySession->Thread.TdiReceiveContext,
														    (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader,
														    sizeof(NDFS_REQUEST_HEADER),
														    0,
														    NULL,
														    NULL );

					if (!NT_SUCCESS(status)) {

						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
						primarySessionTerminate = TRUE;
					}

					PrimarySession->Thread.TdiReceiving = TRUE;
				}
			}
			
			continue;
		}
	}

	ExAcquireFastMutexUnsafe( &PrimarySession->FastMutex );
	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_STOPED );
	ExReleaseFastMutexUnsafe( &PrimarySession->FastMutex );

	while (TRUE) {

		LARGE_INTEGER	timeOut;
		NTSTATUS		eventStatus;


		if (PrimarySession->Thread.IdleSlotCount == PrimarySession->SessionContext.SessionSlotCount)
			break;

		timeOut.QuadPart = -10*HZ;
		eventStatus = KeWaitForSingleObject( &PrimarySession->Thread.WorkCompletionEvent,
											 Executive,
											 KernelMode,
											 FALSE,
											 &timeOut );

		KeClearEvent( &PrimarySession->Thread.WorkCompletionEvent );

		if (eventStatus == STATUS_TIMEOUT) {

			ASSERT( NDASFAT_UNEXPECTED );
			continue;
		}

		while (TRUE) {
	
			for (slotIndex = 0; slotIndex < PrimarySession->SessionContext.SessionSlotCount; slotIndex++) {

				if (PrimarySession->Thread.SessionSlot[slotIndex].State == SLOT_FINISH)
					break;
			}

			if (slotIndex == PrimarySession->SessionContext.SessionSlotCount)
				break;

			DebugTrace2( 0, Dbg, ("PrimarySessionThreadProc: eventStatus = %d\n", eventStatus) );
			
			PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT;
			PrimarySession->Thread.IdleSlotCount++;

			if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool );	
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
			}
		
			if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool );	
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
			}
		}		
	}
	
	if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) {

		DebugTrace2( 0, Dbg2, ("PsTerminateSystemThread: DisconnectFromSecondary\n") );
		DisconnectFromSecondary( PrimarySession );
		ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
		SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
	}

	CloseOpenFiles( PrimarySession, TRUE );

	while (primarySessionRequestEntry = ExInterlockedRemoveHeadList( &PrimarySession->RequestQueue,
																	 &PrimarySession->RequestQSpinLock)) {

		PPRIMARY_SESSION_REQUEST	primarySessionRequest;
			
		primarySessionRequest = CONTAINING_RECORD( primarySessionRequestEntry,
												   PRIMARY_SESSION_REQUEST,
												   ListEntry );

		if (primarySessionRequest->Synchronous == TRUE)
			KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
		else
			DereferencePrimarySessionRequest( primarySessionRequest );
	}

#if 0
	if (PrimarySession->NetdiskPartition) {

		NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager,
											   PrimarySession,
											   PrimarySession->NetdiskPartition, 
											   PrimarySession->IsLocalAddress );

		PrimarySession->NetdiskPartition = NULL;
	}
#endif

	DebugTrace2( 0, Dbg2,
				   ("PrimarySessionThreadProc: PsTerminateSystemThread PrimarySession = %p\n", 
				    PrimarySession) );

	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_TERMINATED );

	PrimarySession_Dereference( PrimarySession );

	PsTerminateSystemThread( STATUS_SUCCESS );
}
Ejemplo n.º 6
0
Archivo: Openclos.c Proyecto: 52M/npcap
NTSTATUS
NPF_GetDeviceMTU(
			 IN POPEN_INSTANCE pOpen,
			 IN PIRP	pIrp,
			 OUT PUINT  pMtu)
{
    PLIST_ENTRY			RequestListEntry;
	PINTERNAL_REQUEST	MaxSizeReq;
	NDIS_STATUS			ReqStatus;

	TRACE_ENTER();

	ASSERT(pOpen != NULL);
	ASSERT(pIrp != NULL);
	ASSERT(pMtu != NULL);

	// Extract a request from the list of free ones
	RequestListEntry = ExInterlockedRemoveHeadList(&pOpen->RequestList, &pOpen->RequestSpinLock);

	if (RequestListEntry == NULL)
	{
		//
		// THIS IS WRONG
		//

		//
		// Assume Ethernet
		//
		*pMtu = 1514;	
		TRACE_EXIT();
		return STATUS_SUCCESS;
	}

	MaxSizeReq = CONTAINING_RECORD(RequestListEntry, INTERNAL_REQUEST, ListElement);

	MaxSizeReq->Request.RequestType = NdisRequestQueryInformation;
	MaxSizeReq->Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;

	MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBuffer = pMtu;
	MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(*pMtu);

	NdisResetEvent(&MaxSizeReq->InternalRequestCompletedEvent);

	//  submit the request
	NdisRequest(
		&ReqStatus,
		pOpen->AdapterHandle,
		&MaxSizeReq->Request);

	if (ReqStatus == NDIS_STATUS_PENDING)
	{
		NdisWaitEvent(&MaxSizeReq->InternalRequestCompletedEvent, 0);
		ReqStatus = MaxSizeReq->RequestStatus;
	}

	//
	// Put the request in the list of the free ones
	//
	ExInterlockedInsertTailList(&pOpen->RequestList, &MaxSizeReq->ListElement, &pOpen->RequestSpinLock);

	if (ReqStatus == NDIS_STATUS_SUCCESS)
	{
		TRACE_EXIT();
		return STATUS_SUCCESS;
	}
	else
	{
		//
		// THIS IS WRONG
		//

		//
		// Assume Ethernet
		//
		*pMtu = 1514;	

		TRACE_EXIT();
		return STATUS_SUCCESS;
	
		// return ReqStatus;
	}
}
Ejemplo n.º 7
0
//
// Wait for incoming request to any arbiter on this host.
//
VOID DraidListenerThreadProc(
	PVOID Param
) {
	PDRAID_GLOBALS DraidGlobals = (PDRAID_GLOBALS)Param;
	NTSTATUS		status;
	PLIST_ENTRY	listEntry;
	PDRAID_LISTEN_CONTEXT ListenContext;
	KIRQL oldIrql;
	INT32 				MaxEventCount = 0;
	PKEVENT				*events = NULL;
	PKWAIT_BLOCK		WaitBlocks = NULL;
	INT32				eventCount;
	NTSTATUS			waitStatus;
	SOCKETLPX_ADDRESS_LIST	socketLpxAddressList;
	INT32 i;
	
	KDPrintM(DBG_LURN_INFO, ("Starting\n"));

	MaxEventCount = DraidReallocEventArray(&events, &WaitBlocks, MaxEventCount);
	
	status = LpxTdiGetAddressList(
		&socketLpxAddressList
        );
	if (!NT_SUCCESS(status)) {
		KDPrintM(DBG_LURN_INFO, ("Failed to get address list\n"));	
		goto out;
	}
	for(i=0;i<socketLpxAddressList.iAddressCount;i++) {
		ListenContext = DraidCreateListenContext(DraidGlobals, &socketLpxAddressList.SocketLpx[i].LpxAddress);
		if (ListenContext) {
			status = DraidStartListenAddress(DraidGlobals, ListenContext);
			if (!NT_SUCCESS(status)) {
				DraidStopListenAddress(DraidGlobals, ListenContext);
			}
		}
	}
	
	while(TRUE) {
restart:
		if (events == NULL || WaitBlocks == NULL) {
			KDPrintM(DBG_LURN_INFO, ("Insufficient memory\n"));
			break;
		}
		eventCount = 0;
		//
		//	Wait exit event, net change event, connect request.
		//
		events[0] = &DraidGlobals->DraidExitEvent;
		eventCount++;
		events[1] = &DraidGlobals->NetChangedEvent;
		eventCount++;

		//
		// Add listening event 
		//
		ACQUIRE_SPIN_LOCK(&DraidGlobals->ListenContextSpinlock, &oldIrql);
		for (listEntry = DraidGlobals->ListenContextList.Flink;
			listEntry != &DraidGlobals->ListenContextList;
			listEntry = listEntry->Flink) 
		{
			ListenContext = CONTAINING_RECORD (listEntry, DRAID_LISTEN_CONTEXT, Link);
			if (!ListenContext->Destroy) {
				if (MaxEventCount < eventCount+1) {
					RELEASE_SPIN_LOCK(&DraidGlobals->ListenContextSpinlock, oldIrql);
					MaxEventCount = DraidReallocEventArray(&events, &WaitBlocks, MaxEventCount);
					goto restart;
				}
				events[eventCount] = &ListenContext->TdiListenContext.CompletionEvent;
				eventCount++;
			}
		}
		RELEASE_SPIN_LOCK(&DraidGlobals->ListenContextSpinlock, oldIrql);
		
		waitStatus = KeWaitForMultipleObjects(
					eventCount, 
					events,
					WaitAny, 
					Executive,
					KernelMode,
					TRUE,
					NULL, //&TimeOut,
					WaitBlocks);
		if (KeReadStateEvent(&DraidGlobals->DraidExitEvent)) {
			KDPrintM(DBG_LURN_INFO, ("Exit requested\n"));
			break;
		}
		if (KeReadStateEvent(&DraidGlobals->NetChangedEvent)) {
			KDPrintM(DBG_LURN_INFO, ("NIC status has changed\n"));
			KeClearEvent(&DraidGlobals->NetChangedEvent);
			//
			// Start if not listening and stop if destorying request is on.
			//
			ACQUIRE_SPIN_LOCK(&DraidGlobals->ListenContextSpinlock, &oldIrql);
			for (listEntry = DraidGlobals->ListenContextList.Flink;
				listEntry != &DraidGlobals->ListenContextList;
				listEntry = listEntry->Flink) 
			{
				ListenContext = CONTAINING_RECORD (listEntry, DRAID_LISTEN_CONTEXT, Link);
				status = STATUS_SUCCESS;
				if (!ListenContext->Started) {
					RELEASE_SPIN_LOCK(&DraidGlobals->ListenContextSpinlock, oldIrql);	
					status = DraidStartListenAddress(DraidGlobals, ListenContext);
					ACQUIRE_SPIN_LOCK(&DraidGlobals->ListenContextSpinlock, &oldIrql);
				}
				if (!NT_SUCCESS(status) || ListenContext->Destroy) {
					listEntry = listEntry->Blink; // // Move to next entry. There may be multiple interface is down.
					RemoveEntryList(&ListenContext->Link);
					RELEASE_SPIN_LOCK(&DraidGlobals->ListenContextSpinlock, oldIrql);					
					DraidStopListenAddress(DraidGlobals, ListenContext);
					ACQUIRE_SPIN_LOCK(&DraidGlobals->ListenContextSpinlock, &oldIrql);					
				}
			}
			RELEASE_SPIN_LOCK(&DraidGlobals->ListenContextSpinlock, oldIrql);
			continue; // Reset listen event.
		}

		// Check whether listen event has been signaled.
		for(i=2;i<eventCount;i++) {
			if (KeReadStateEvent(events[i])) {
				BOOLEAN Found;
				KeClearEvent(events[i]);
				// Find listencontext related to this event.
				ACQUIRE_SPIN_LOCK(&DraidGlobals->ListenContextSpinlock, &oldIrql);
				Found = FALSE;
				for (listEntry = DraidGlobals->ListenContextList.Flink;
					listEntry != &DraidGlobals->ListenContextList;
					listEntry = listEntry->Flink) 
				{
					ListenContext = CONTAINING_RECORD (listEntry, DRAID_LISTEN_CONTEXT, Link);
					if (&ListenContext->TdiListenContext.CompletionEvent == events[i]) {
						Found = TRUE;
						break;
					}
				}
				RELEASE_SPIN_LOCK(&DraidGlobals->ListenContextSpinlock, oldIrql);	
				if (Found) {
					DraidAcceptConnection(DraidGlobals, ListenContext);
				} else {
					ASSERT(FALSE);
				}
			}
		}
	}
out:
	//
	// to do: clean-up pending client
	//

	//
	// Close and free pending listen contexts
	//
	while(listEntry = 
		ExInterlockedRemoveHeadList(&DraidGlobals->ListenContextList,  
			&DraidGlobals->ListenContextSpinlock)) 
	{
		ListenContext = CONTAINING_RECORD (listEntry, DRAID_LISTEN_CONTEXT, Link);
		DraidStopListenAddress(DraidGlobals, ListenContext);
	}

	DraidFreeEventArray(events, WaitBlocks);
	
	KDPrint(1,("Exiting.\n"));
	PsTerminateSystemThread(STATUS_SUCCESS);	
}
Ejemplo n.º 8
0
static VOID MainThreadProc (PVOID threadArg)
{
	EncryptedIoQueue *queue = (EncryptedIoQueue *) threadArg;
	PLIST_ENTRY listEntry;
	EncryptedIoQueueItem *item;

	LARGE_INTEGER fragmentOffset;
	ULONG dataRemaining;
	PUCHAR activeFragmentBuffer = queue->FragmentBufferA;
	PUCHAR dataBuffer;
	EncryptedIoRequest *request;
	uint64 intersectStart;
	uint32 intersectLength;
	ULONGLONG addResult;
	HRESULT hResult;

	if (IsEncryptionThreadPoolRunning())
		KeSetPriorityThread (KeGetCurrentThread(), LOW_REALTIME_PRIORITY);

	while (!queue->ThreadExitRequested)
	{
		if (!NT_SUCCESS (KeWaitForSingleObject (&queue->MainThreadQueueNotEmptyEvent, Executive, KernelMode, FALSE, NULL)))
			continue;

		while ((listEntry = ExInterlockedRemoveHeadList (&queue->MainThreadQueue, &queue->MainThreadQueueLock)))
		{
			PIRP irp = CONTAINING_RECORD (listEntry, IRP, Tail.Overlay.ListEntry);
			PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (irp);
			
			if (queue->Suspended)
				KeWaitForSingleObject (&queue->QueueResumedEvent, Executive, KernelMode, FALSE, NULL);

			item = GetPoolBuffer (queue, sizeof (EncryptedIoQueueItem));
			if (!item)
			{
				TCCompleteDiskIrp (irp, STATUS_INSUFFICIENT_RESOURCES, 0);
				DecrementOutstandingIoCount (queue);
				IoReleaseRemoveLock (&queue->RemoveLock, irp);

				continue;
			}

			item->Queue = queue;
			item->OriginalIrp = irp;
			item->Status = STATUS_SUCCESS;

			IoSetCancelRoutine (irp, NULL);
			if (irp->Cancel)
			{
				CompleteOriginalIrp (item, STATUS_CANCELLED, 0);
				continue;
			}

			switch (irpSp->MajorFunction)
			{
			case IRP_MJ_READ:
				item->Write = FALSE;
				item->OriginalOffset = irpSp->Parameters.Read.ByteOffset;
				item->OriginalLength = irpSp->Parameters.Read.Length;
				break;

			case IRP_MJ_WRITE:
				item->Write = TRUE;
				item->OriginalOffset = irpSp->Parameters.Write.ByteOffset;
				item->OriginalLength = irpSp->Parameters.Write.Length;
				break;

			default:
				CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0);
				continue;
			}

#ifdef TC_TRACE_IO_QUEUE
			item->OriginalIrpOffset = item->OriginalOffset;
#endif

			// Handle misaligned read operations to work around a bug in Windows System Assessment Tool which does not follow FILE_FLAG_NO_BUFFERING requirements when benchmarking disk devices
			if (queue->IsFilterDevice
				&& !item->Write
				&& item->OriginalLength > 0
				&& (item->OriginalLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) == 0
				&& (item->OriginalOffset.QuadPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0)
			{
				byte *buffer;
				ULONG alignedLength;
				LARGE_INTEGER alignedOffset;
				hResult = ULongAdd(item->OriginalLength, ENCRYPTION_DATA_UNIT_SIZE, &alignedLength);
				if (hResult != S_OK)
				{
					CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0);
					continue;
				}

				alignedOffset.QuadPart = item->OriginalOffset.QuadPart & ~((LONGLONG) ENCRYPTION_DATA_UNIT_SIZE - 1);

				buffer = TCalloc (alignedLength);
				if (!buffer)
				{
					CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0);
					continue;
				}

				item->Status = TCReadDevice (queue->LowerDeviceObject, buffer, alignedOffset, alignedLength);

				if (NT_SUCCESS (item->Status))
				{
					UINT64_STRUCT dataUnit;

					dataBuffer = (PUCHAR) MmGetSystemAddressForMdlSafe (irp->MdlAddress, HighPagePriority);
					if (!dataBuffer)
					{
						TCfree (buffer);
						CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0);
						continue;
					}

					if (queue->EncryptedAreaStart != -1 && queue->EncryptedAreaEnd != -1)
					{
						GetIntersection (alignedOffset.QuadPart, alignedLength, queue->EncryptedAreaStart, queue->EncryptedAreaEnd, &intersectStart, &intersectLength);
						if (intersectLength > 0)
						{
							dataUnit.Value = intersectStart / ENCRYPTION_DATA_UNIT_SIZE;
							DecryptDataUnits (buffer + (intersectStart - alignedOffset.QuadPart), &dataUnit, intersectLength / ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo);
						}
					}

					memcpy (dataBuffer, buffer + (item->OriginalOffset.LowPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)), item->OriginalLength);
				}

				TCfree (buffer);
				CompleteOriginalIrp (item, item->Status, NT_SUCCESS (item->Status) ? item->OriginalLength : 0);
				continue;
			}

			// Validate offset and length
			if (item->OriginalLength == 0
				|| (item->OriginalLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0
				|| (item->OriginalOffset.QuadPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0
				|| (	!queue->IsFilterDevice && 
						(	(S_OK != ULongLongAdd(item->OriginalOffset.QuadPart, item->OriginalLength, &addResult))
							||	(addResult > (ULONGLONG) queue->VirtualDeviceLength)
						)
					)
				)
			{
				CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0);
				continue;
			}

#ifdef TC_TRACE_IO_QUEUE
			Dump ("Q  %I64d [%I64d] %c len=%d\n", item->OriginalOffset.QuadPart, GetElapsedTime (&queue->LastPerformanceCounter), item->Write ? 'W' : 'R', item->OriginalLength);
#endif

			if (!queue->IsFilterDevice)
			{
				// Adjust the offset for host file or device
				if (queue->CryptoInfo->hiddenVolume)
					hResult = ULongLongAdd(item->OriginalOffset.QuadPart, queue->CryptoInfo->hiddenVolumeOffset, &addResult);
				else
					hResult = ULongLongAdd(item->OriginalOffset.QuadPart, queue->CryptoInfo->volDataAreaOffset, &addResult); 

				if (hResult != S_OK)
				{
					CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0);
					continue;
				}
				else
					item->OriginalOffset.QuadPart = addResult;

				// Hidden volume protection
				if (item->Write && queue->CryptoInfo->bProtectHiddenVolume)
				{
					// If there has already been a write operation denied in order to protect the
					// hidden volume (since the volume mount time)
					if (queue->CryptoInfo->bHiddenVolProtectionAction)	
					{
						// Do not allow writing to this volume anymore. This is to fake a complete volume
						// or system failure (otherwise certain kinds of inconsistency within the file
						// system could indicate that this volume has used hidden volume protection).
						CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0);
						continue;
					}

					// Verify that no byte is going to be written to the hidden volume area
					if (RegionsOverlap ((unsigned __int64) item->OriginalOffset.QuadPart,
						(unsigned __int64) item->OriginalOffset.QuadPart + item->OriginalLength - 1,
						queue->CryptoInfo->hiddenVolumeOffset,
						(unsigned __int64) queue->CryptoInfo->hiddenVolumeOffset + queue->CryptoInfo->hiddenVolumeProtectedSize - 1))
					{
						Dump ("Hidden volume protection triggered: write %I64d-%I64d (protected %I64d-%I64d)\n", item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, queue->CryptoInfo->hiddenVolumeOffset, queue->CryptoInfo->hiddenVolumeOffset + queue->CryptoInfo->hiddenVolumeProtectedSize - 1);
						queue->CryptoInfo->bHiddenVolProtectionAction = TRUE;

						// Deny this write operation to prevent the hidden volume from being overwritten
						CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0);
						continue;
					}
				}
			}
			else if (item->Write
				&& RegionsOverlap (item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET + TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE - 1))
			{
				// Prevent inappropriately designed software from damaging important data that may be out of sync with the backup on the Rescue Disk (such as the end of the encrypted area).
				Dump ("Preventing write to the system encryption key data area\n");
				CompleteOriginalIrp (item, STATUS_MEDIA_WRITE_PROTECTED, 0);
				continue;
			}
			else if (item->Write && IsHiddenSystemRunning()
				&& (RegionsOverlap (item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, TC_SECTOR_SIZE_BIOS, TC_BOOT_LOADER_AREA_SECTOR_COUNT * TC_SECTOR_SIZE_BIOS - 1)
				 || RegionsOverlap (item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, GetBootDriveLength(), _I64_MAX)))
			{
				Dump ("Preventing write to boot loader or host protected area\n");
				CompleteOriginalIrp (item, STATUS_MEDIA_WRITE_PROTECTED, 0);
				continue;
			}

			dataBuffer = (PUCHAR) MmGetSystemAddressForMdlSafe (irp->MdlAddress, HighPagePriority);

			if (dataBuffer == NULL)
			{
				CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0);
				continue;
			}

			// Divide data block to fragments to enable efficient overlapping of encryption and IO operations

			dataRemaining = item->OriginalLength;
			fragmentOffset = item->OriginalOffset;

			while (dataRemaining > 0)
			{
				BOOL isLastFragment = dataRemaining <= TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE;
				
				ULONG dataFragmentLength = isLastFragment ? dataRemaining : TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE;
				activeFragmentBuffer = (activeFragmentBuffer == queue->FragmentBufferA ? queue->FragmentBufferB : queue->FragmentBufferA);

				InterlockedIncrement (&queue->IoThreadPendingRequestCount);

				// Create IO request
				request = GetPoolBuffer (queue, sizeof (EncryptedIoRequest));
				if (!request)
				{
					CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0);
					break;
				}
				request->Item = item;
				request->CompleteOriginalIrp = isLastFragment;
				request->Offset = fragmentOffset;
				request->Data = activeFragmentBuffer;
				request->OrigDataBufferFragment = dataBuffer;
				request->Length = dataFragmentLength;

				if (queue->IsFilterDevice)
				{
					if (queue->EncryptedAreaStart == -1 || queue->EncryptedAreaEnd == -1)
					{
						request->EncryptedLength = 0;
					}
					else
					{
						// Get intersection of data fragment with encrypted area
						GetIntersection (fragmentOffset.QuadPart, dataFragmentLength, queue->EncryptedAreaStart, queue->EncryptedAreaEnd, &intersectStart, &intersectLength);

						request->EncryptedOffset = intersectStart - fragmentOffset.QuadPart;
						request->EncryptedLength = intersectLength;
					}
				}
				else
				{
					request->EncryptedOffset = 0;
					request->EncryptedLength = dataFragmentLength;
				}

				AcquireFragmentBuffer (queue, activeFragmentBuffer);

				if (item->Write)
				{
					// Encrypt data
					memcpy (activeFragmentBuffer, dataBuffer, dataFragmentLength);

					if (request->EncryptedLength > 0)
					{
						UINT64_STRUCT dataUnit;
						ASSERT (request->EncryptedOffset + request->EncryptedLength <= request->Offset.QuadPart + request->Length);

						dataUnit.Value = (request->Offset.QuadPart + request->EncryptedOffset) / ENCRYPTION_DATA_UNIT_SIZE;

						if (queue->CryptoInfo->bPartitionInInactiveSysEncScope)
							dataUnit.Value += queue->CryptoInfo->FirstDataUnitNo.Value;
						else if (queue->RemapEncryptedArea)
							dataUnit.Value += queue->RemappedAreaDataUnitOffset;
								
						EncryptDataUnits (activeFragmentBuffer + request->EncryptedOffset, &dataUnit, request->EncryptedLength / ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo);
					}
				}

				// Queue IO request
				ExInterlockedInsertTailList (&queue->IoThreadQueue, &request->ListEntry, &queue->IoThreadQueueLock);
				KeSetEvent (&queue->IoThreadQueueNotEmptyEvent, IO_DISK_INCREMENT, FALSE);

				if (isLastFragment)
					break;

				dataRemaining -= TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE;
				dataBuffer += TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE;
				fragmentOffset.QuadPart += TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE;
			}
		}
	}

	PsTerminateSystemThread (STATUS_SUCCESS);
}
NTSTATUS KDispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    NTSTATUS              status = STATUS_UNSUCCESSFUL;
    PIO_STACK_LOCATION    irpStack  = IoGetCurrentIrpStackLocation(Irp);
    PPROCESS_EVENT        pProcessEvent;
	PCHAR pOutputBuffer;
	PPROCESS_INFORMATION pInputBuffer;
	UINT dwDataWritten = 0;
	PCAPTURE_PROCESS_MANAGER pProcessManager;

	/* Get the process manager from the device extension */
    pProcessManager = gpDeviceObject->DeviceExtension;

    switch(irpStack->Parameters.DeviceIoControl.IoControlCode)
    {
        case IOCTL_CAPTURE_GET_PROCINFO:
			/* Update the time the user space program last sent an IOCTL */
			//UpdateLastContactTime();
			/* Return some of the process events that are queued */
            if(irpStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(PROCESS_EVENT))
            {
				ULONG left = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
				ULONG done = 0;
				pOutputBuffer = Irp->UserBuffer;
				__try {
					ProbeForWrite(pOutputBuffer, 
								irpStack->Parameters.DeviceIoControl.OutputBufferLength,
								__alignof (PROCESS_EVENT));
					//ExAcquireFastMutex(&pProcessManager->mProcessWaitingSpinLock);
					//if(pProcessManager->pCurrentProcessEvent != NULL)
					//{
					//	RtlCopyMemory(pOutputBuffer+done, pProcessManager->pCurrentProcessEvent, sizeof(PROCESS_EVENT));
					//	done += sizeof(PROCESS_EVENT);
					//	ExFreePoolWithTag(pProcessManager->pCurrentProcessEvent, PROCESS_POOL_TAG);
					//	pProcessManager->pCurrentProcessEvent = NULL;
					//}
					//ExReleaseFastMutex(&pProcessManager->mProcessWaitingSpinLock);
					
					if(!IsListEmpty(&pProcessManager->lQueuedProcessEvents))
					{
						PLIST_ENTRY head;
						PPROCESS_EVENT_PACKET pProcessEventPacket;
						head = ExInterlockedRemoveHeadList(&pProcessManager->lQueuedProcessEvents, &pProcessManager->lQueuedProcessEventsSpinLock);
						pProcessManager->nQueuedProcessEvents--;
						pProcessEventPacket = CONTAINING_RECORD(head, PROCESS_EVENT_PACKET, Link);
						
						RtlCopyMemory(pOutputBuffer, &pProcessEventPacket->processEvent, sizeof(PROCESS_EVENT));
						done = sizeof(PROCESS_EVENT);

						ExFreePool(pProcessEventPacket);

						// Notify that we still have process events queued
						if( pProcessManager->nQueuedProcessEvents )
						{
							KeSetEvent(pProcessManager->eNewProcessEvent, 0, FALSE);
							KeClearEvent(pProcessManager->eNewProcessEvent);
						}
					}
					
					dwDataWritten = done;
					status = STATUS_SUCCESS;
				} __except( EXCEPTION_EXECUTE_HANDLER ) {
					DbgPrint("CaptureProcessMonitor: EXCEPTION IOCTL_CAPTURE_GET_PROCINFO - %08x\n", GetExceptionCode());
					status = GetExceptionCode();     
				}        
            }
            break;
        default:
            break;
    }
Ejemplo n.º 10
0
VOID
Thread (
    IN PVOID Context
    )
{
    PDEVICE_OBJECT      DeviceObject;
    PDEVICE_EXTENSION   deviceExtension;
    PLIST_ENTRY         request;
    PIRP                Irp;
    PIO_STACK_LOCATION  currentIrpStack;
    PIO_STACK_LOCATION  nextIrpStack;
	DWORD				dwStartSec;
	DWORD				dwLength;
	PVOID				pBuffer;
	NTSTATUS			status;
	DWORD				dwRetVal;
	BOOL				bReadSys;
	PBLK_MOVER_PARAM	pParam;
    DIOC_REGISTERS		*pRegs;
	PREAD_WRITE_BUFFER	pReadWriteBuffer;
	KIRQL				Irql;
//  PAGED_CODE();
    ASSERT(Context != NULL);

    DeviceObject = (PDEVICE_OBJECT) Context;

    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    KeSetPriorityThread(KeGetCurrentThread(),HIGH_PRIORITY);//LOW_REALTIME_PRIORITY);// HIGH_PRIORITY);

    while(TRUE)
    {
        KeWaitForSingleObject(
            &deviceExtension->request_event,
            Executive,
            KernelMode,
            FALSE,
            NULL
            );

		ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
        if (deviceExtension->terminate_thread)
        {
            PsTerminateSystemThread(STATUS_SUCCESS);
        }

        while (request = ExInterlockedRemoveHeadList(
            &deviceExtension->list_head,
            &deviceExtension->list_lock
            ))
        {
            Irp = CONTAINING_RECORD(request, IRP, Tail.Overlay.ListEntry);

            currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
			nextIrpStack = IoGetNextIrpStackLocation(Irp);
			
			ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
            switch (currentIrpStack->MajorFunction)
            {
            case IRP_MJ_READ:
            case IRP_MJ_WRITE:
				pBuffer		= MmGetSystemAddressForMdlSafe(Irp->MdlAddress,NormalPagePriority);
				dwLength	= currentIrpStack->Parameters.Read.Length/SECTOR_SIZE;
				dwStartSec	= (DWORD)(currentIrpStack->Parameters.Read.ByteOffset.QuadPart/SECTOR_SIZE);

				status = BlkMoverRelocateReadWrite(DeviceObject,currentIrpStack->MajorFunction,dwStartSec,dwLength,pBuffer);

				//ASSERT(status == STATUS_SUCCESS);
				Irp->IoStatus.Status	  = status;
				Irp->IoStatus.Information = dwLength*SECTOR_SIZE;
				break;
            case IRP_MJ_DEVICE_CONTROL:
                switch (currentIrpStack->Parameters.DeviceIoControl.IoControlCode)
                {
				case IOCTL_YG_BLOCK_MOVER_FLUSH_BUFFER:
					pRegs = (DIOC_REGISTERS *)Irp->AssociatedIrp.SystemBuffer;
					pRegs->reg_EAX = TRUE;
					
					status = FlushBuf(g_pMoverData->DeviceObject);
			        Irp->IoStatus.Status	  = status;
					Irp->IoStatus.Information = sizeof(DIOC_REGISTERS);
                    break;
                case IOCTL_YG_BLOCK_MOVING_GROUP_CURRENT:
					pRegs = (DIOC_REGISTERS *)Irp->AssociatedIrp.SystemBuffer;

					g_MovingGroup.bFront		= pRegs->reg_EAX;
					g_MovingGroup.dwSStart		= pRegs->reg_EBX;
					g_MovingGroup.dwTStart		= pRegs->reg_ECX;
					g_MovingGroup.dwSize		= pRegs->reg_EDX;
					g_MovingGroup.dwMovedSize	= 0;
					g_dwMovedRecNum				= pRegs->reg_EDI;
					g_pMoverData->bWorking		= TRUE;

					pRegs->reg_EAX				= TRUE;

			        Irp->IoStatus.Status	  = STATUS_SUCCESS;
					Irp->IoStatus.Information = sizeof(DIOC_REGISTERS);
                    break;
				case IOCTL_YG_GET_MOVED_SECTORS:
					pRegs = (DIOC_REGISTERS *)Irp->AssociatedIrp.SystemBuffer;
					pRegs->reg_EAX = g_dwMovedSecs;

			        Irp->IoStatus.Status	  = STATUS_SUCCESS;
					Irp->IoStatus.Information = sizeof(DIOC_REGISTERS);
                    break;
				case IOCTL_YG_READ:
					pReadWriteBuffer = (PREAD_WRITE_BUFFER)Irp->AssociatedIrp.SystemBuffer;
					dwLength		 = pReadWriteBuffer->dwLength;
					pBuffer			 = MmGetSystemAddressForMdlSafe(Irp->MdlAddress,NormalPagePriority);
					dwStartSec		 = pReadWriteBuffer->dwStartSec;

					if (pReadWriteBuffer->dwMovedRecNum == YGBLK_READ_WRITE)
					{
						status = BlkMoverRelocateReadWrite(DeviceObject,IRP_MJ_READ,dwStartSec,dwLength,pBuffer);
					}
					else
					{
						status = SyncReadWriteSec(DeviceObject,dwStartSec,dwLength ,pBuffer ,IRP_MJ_READ);
					}
					MmUnlockPages(Irp->MdlAddress);
					IoFreeMdl(Irp->MdlAddress);
					Irp->MdlAddress = NULL;
			        Irp->IoStatus.Status	  = STATUS_SUCCESS;
					Irp->IoStatus.Information = sizeof(READ_WRITE_BUFFER);
                    break;
				case IOCTL_YG_WRITE:
					pReadWriteBuffer = (PREAD_WRITE_BUFFER)Irp->AssociatedIrp.SystemBuffer;
					dwLength		 = pReadWriteBuffer->dwLength;
					pBuffer			 = MmGetSystemAddressForMdlSafe(Irp->MdlAddress,NormalPagePriority);
					dwStartSec		 = pReadWriteBuffer->dwStartSec;

					if (pReadWriteBuffer->dwMovedRecNum == YGBLK_READ_WRITE)
					{
						status = BlkMoverRelocateReadWrite(DeviceObject,IRP_MJ_WRITE,dwStartSec,dwLength,pBuffer);
					}
					else
					{
						status = SyncReadWriteSec(DeviceObject,dwStartSec,dwLength ,pBuffer ,IRP_MJ_WRITE);
					}
					MmUnlockPages(Irp->MdlAddress);
					IoFreeMdl(Irp->MdlAddress);
					Irp->MdlAddress = NULL;

					if (pReadWriteBuffer->dwMovedRecNum != YGBLK_READ_WRITE)
					{
						if(!pReadWriteBuffer->bSys && g_dwDataRecNum)
						{
							//g_dwMovedRecNum = pReadWriteBuffer->dwMovedRecNum;
							g_MovingGroup.dwMovedSize += dwLength;
						}

						if(g_bReLocate && pReadWriteBuffer->bSys) 
							g_dwRePointer = pReadWriteBuffer->dwStartSec + dwLength;
					}

			        Irp->IoStatus.Status	  = STATUS_SUCCESS;
					Irp->IoStatus.Information = sizeof(READ_WRITE_BUFFER);
                    break;
                default:
                    Irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
                    Irp->IoStatus.Information = 0;
                }
                break;
            default:
                DbgPrint("BlkMover:Thread default conditions.");

                Irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
                Irp->IoStatus.Information = 0;
            }
			IoCompleteRequest(Irp,
							(CCHAR) (NT_SUCCESS(Irp->IoStatus.Status) ?
							IO_DISK_INCREMENT : IO_NO_INCREMENT));
        }
    }
}
Ejemplo n.º 11
0
NTSTATUS
CleanupRtAddress(
    IN  PDEVICE  pDevice,
    IN  PIRP     pIrp)

/*++
Routine Description;

    This Routine handles closing the Rt Object that is used by
    by RT to send and receive name service datagrams on port 137.


Arguments;

    pIrp - a  ptr to an IRP

Return Value;

    NTSTATUS - status of the request

--*/

{
    NTSTATUS                   status;
    PRT_INFO                   pRt;
    CTELockHandle              OldIrq;
    PLIST_ENTRY                pHead;
    ULONG                      Index;
    PLIST_ENTRY                pLE;
    PIRP                       pTmpIrp;



    IpxPrint0("CleanupRtAddress - entered\n");

    //
    // if the endpoint structure is allocated, then deallocate it
    //
    // pRt   = REQUEST_OPEN_CONTEXT(pIrp);
    pRt = pRtInfo;

    Index = RT_ADDRESS_INDEX(pIrp);
    IpxPrint1("CleanupRtAdd: Index = (%d)\n", Index);

    IpxVerifyRt(pRt);
    CTEAssert(pRt  && (pRt == pRtInfo));
    CTEAssert(Index < IPX_RT_MAX_ADDRESSES);

    do
    {
        PLIST_ENTRY          pRcvEntry;
        PRTRCV_BUFFER        pRcv;
        PRT_IRP pRtAddFl   = &pRt->AddFl[Index];

        CTEAssert(pRtAddFl->State == RT_OPEN);
        IpxPrint1("CleanupRtAddress: Got AF handle = (%lx)\n", pRtAddFl);
        IpxReferenceRt(pRt, RT_CLEANUP);
        status = STATUS_SUCCESS;

        CTEGetLock (&pRt->Lock, &OldIrq);

        //
        // prevent any more dgram getting queued up
        //
        pRtAddFl->State = RT_CLOSING;
        CTEFreeLock (&pRt->Lock, OldIrq);

        //
        // free any rcv buffers that may be queued up
        //
        pHead = &pRtAddFl->RcvList;
        while (pRcvEntry = ExInterlockedRemoveHeadList(pHead, &pRt->Lock))
        {
           pRcv = CONTAINING_RECORD(pRcvEntry,RTRCV_BUFFER,Linkage);

           CTEAssert(pRcv);
           IpxPrint1("CleanupRtAddress:Freeing buffer = (%lx)\n", pRcv);
           RtFreeMem(pRcv,pRcv->TotalAllocSize);
        }

        //
        // Complete all irps that are queued
        //
        while (pLE = ExInterlockedRemoveHeadList(&pRtAddFl->RcvIrpList, &pRt->Lock)) {

           //
           // The recv irp is here so copy the data to its buffer and
           // pass it up to RT
           //
           pTmpIrp = CONTAINING_RECORD(pLE, IRP, Tail.Overlay.ListEntry);
           IpxPrint1("CleanupRtAddress: Completing Rt rcv Irp from AdFl queue pIrp=%X\n" ,pTmpIrp);
           pTmpIrp->IoStatus.Information = 0;
           pTmpIrp->IoStatus.Status      = STATUS_CANCELLED;

           NTIoComplete(pTmpIrp, (NTSTATUS)-1, (ULONG)-1);

        } //end of while

       //
       // dequeue and complete any irps on the complete queue.
       //

       while (pLE = ExInterlockedRemoveHeadList(&pRt->CompletedIrps, &pRt->Lock))
       {
           pTmpIrp = CONTAINING_RECORD(pLE, IRP, Tail.Overlay.ListEntry);
           if (RT_ADDRESS_INDEX(pTmpIrp) == Index)
           {
              IpxPrint1("CleanupRtAddress:Completing Rt rcv Irp from CompleteIrps queue pIrp=%X\n" ,pTmpIrp);

               pTmpIrp->IoStatus.Information = 0;
               pTmpIrp->IoStatus.Status = STATUS_CANCELLED;
               NTIoComplete(pTmpIrp, (NTSTATUS)-1, (ULONG)-1);
           }
           else
           {
                ExInterlockedInsertHeadList(&pRt->HolderIrpsList, pLE, &pRt->Lock);
           }
       }
       CTEGetLock(&pRt->Lock, &OldIrq);
       while(!IsListEmpty(&pRt->HolderIrpsList))
       {
          pLE = RemoveHeadList(&pRt->HolderIrpsList);
          InsertHeadList(&pRt->CompletedIrps, pLE);
       }
       CTEFreeLock(&pRt->Lock, OldIrq);

       //
       // Store AF pointer in Irp since we will now be freeing the address file
       // (in driver.c).
       //

       //
       // We always have addressfile in the Irp
       //

       // REQUEST_OPEN_CONTEXT(pIrp) = (PVOID)(pRtAddFl->AddressFile);

       IpxDereferenceRt(pRt, RT_CLEANUP);
  } while (FALSE);

   IpxPrint0("CleanupRtAddress: Return\n");
   return(status);
}
Ejemplo n.º 12
0
/*
kd> dt ndis!_NDIS_PROTOCOL_BLOCK
+0x000 Header           : _NDIS_OBJECT_HEADER
+0x004 ProtocolDriverContext : Ptr32 Void
+0x008 NextProtocol     : Ptr32 _NDIS_PROTOCOL_BLOCK
+0x00c OpenQueue        : Ptr32 _NDIS_OPEN_BLOCK
win7
*/
BOOLEAN	EnumNetCards()
{
	PNDIS_MINIPORT_BLOCK pMiniBlock=NULL;
	PNDIS_COMMON_OPEN_BLOCK_2k3_early	pOpenBlock=NULL;

	ULONG	MiniDriverBlockHeader	;
	ULONG	NetCardType	=	0;
	LIST_ENTRY		*pListEntry=NULL;
	NETCARDS_INFO		*pNI=NULL;
	NTSTATUS			status = STATUS_SUCCESS;
	ULONG			uTmp=0;
	ADAPTER_INFOEX	*pAdapterInfoEx	=	NULL;
	ADAPTER_INFO	AI;
	WCHAR			*p1,*p2;
	ULONG			index=0;
	UNICODE_STRING	uniTmp;
	DWORD		dwVersion=0;


	

	PKK_NDIS_PROTOCOL_BLOCK	pProtocol	=	(PKK_NDIS_PROTOCOL_BLOCK)GetProtocolHeader();

	dwVersion = GetWindowsVersion();
	p1=p2=NULL;

	//清空列表
	if (!IsListEmpty(&g_NetCardsInfoHeader.Next))
	{
		ExInterlockedRemoveHeadList(&g_NetCardsInfoHeader.Next, &g_NetCardsInfoLock);
// 		LockResource(&g_NetCardsInfoLock, TRUE);
// 		pListEntry = RemoveHeadList(&g_NetCardsInfoHeader.Next);
// 		UnlockResource(&g_NetCardsInfoLock);
		pNI	=	CONTAINING_RECORD(pListEntry, NETCARDS_INFO, Next);
		if (NULL==pNI)
		{

			DbgBreakPoint();

		}
		RtlFreeAnsiString(&pNI->Name);
		kfree(pNI);
	}
	status	=	GetAdapterInfo(NULL, &uTmp);
	if (status==STATUS_BUFFER_TOO_SMALL)
	{
		pAdapterInfoEx	=	kmalloc(uTmp);
		RtlZeroMemory(pAdapterInfoEx, uTmp);
		if (NULL== pAdapterInfoEx)
		{
			return FALSE;
		}
	}
	status = GetAdapterInfo(pAdapterInfoEx, &uTmp);
	if (pAdapterInfoEx->uNumber==0)
	{
		kprintf("GetAdapterInfo() return pAdapterInfoEx->uNumber==0");
		kfree(pAdapterInfoEx);
		return FALSE;
	}

	while (pProtocol)	
	{
		//search for  the nic driver block
		if (dwVersion==Windows_7||dwVersion==Windows_Vista)
		{
			if (((PNDIS_PROTOCOL_BLOCKWin7)pProtocol)->OpenQueue==0)
			{
				goto NextBlock;
			}
		}
		else
		{
			if (pProtocol->OpenQueue==NULL)
			{
				goto NextBlock;
			}
		}

		uTmp=0;
		//现在使用了protocol链表,所以要防止一个miniport多次使用的情况
		if (dwVersion==Windows_Vista||dwVersion==Windows_7)
		{
			PNDIS_OPEN_BLOCKWIN7 pOP7	=	(PNDIS_OPEN_BLOCKWIN7)((PNDIS_PROTOCOL_BLOCKWin7)pProtocol)->OpenQueue;
			pMiniBlock	=	pOP7->MiniportHandle;
		}
		else
		{
			pMiniBlock	=	pProtocol->OpenQueue->MiniportHandle;
		}

		pListEntry	=	g_NetCardsInfoHeader.Next.Flink;
		while(pListEntry&& (pListEntry!=&g_NetCardsInfoHeader.Next))
		{
			pNI	=	CONTAINING_RECORD(pListEntry, NETCARDS_INFO, Next);
			if (pNI==NULL)
			{
				kprintf("Crash......when checking pMiniBlock is in g_NetCardsInfoHeader already\n");
				return FALSE;
			//	DbgBreakPoint();
			}
			if (pNI->pMiniBlock==pMiniBlock)
			{
				uTmp	=	1;
				break;
			}
			pListEntry	=	pListEntry->Flink;
		}
		if (uTmp==1)
		{
			//这个miniport已经使用过了
			goto NextBlock;
		}
		NetCardType		=	IsPhysicalMiniport(pMiniBlock);	//只取物理网卡
		if (NetCardType==0)
		{
			goto NextBlock;
		}
		
		pNI	=	kmalloc(sizeof(NETCARDS_INFO));
		RtlZeroMemory(pNI, sizeof(NETCARDS_INFO));
		if (NetCardType==1)
		{
			SetFlag(pNI->flag, REGULARNETCARD);
			
		}
		if (NetCardType==2)
		{
			SetFlag(pNI->flag, WIRELESSNETCARD);
		}
		/*
		p_mini_block->SymbolicLinkName
		亦可直接Createfile (p_mini_block->SymbolicLinkName....)发OID_802_3_CURRENT_ADDRESS来查询
		*/
		pNI->pMiniBlock	=	pMiniBlock;
		uTmp =0;
		
		for (index=0; index<pAdapterInfoEx->uNumber; index++)
		{
			p1	=	kmalloc(pMiniBlock->SymbolicLinkName.Length+2);
			RtlZeroMemory(p1, pMiniBlock->SymbolicLinkName.Length+2);
			RtlCopyMemory(p1, pMiniBlock->SymbolicLinkName.Buffer, pMiniBlock->SymbolicLinkName.Length);

			AI	=	pAdapterInfoEx->pAI[index];
			p2	=	kmalloc(AI.GUID.Length+2);
			RtlZeroMemory(p2, AI.GUID.Length+2);
			RtlCopyMemory(p2, AI.GUID.Buffer, AI.GUID.Length);
			_wcsupr(p1);_wcsupr(p2);
			if (wcsstr(p1,p2))
			{
				kfree(p1);kfree(p2);
				uTmp	=	1;
				break;	//找到了,已经获取网卡MAC地址
			}
			kfree(p1);kfree(p2);

		}//end for (index=0; index<pAdapterInfoEx->uNumber; index++)
		
		if (uTmp==1)
		{
			RtlCopyMemory(pNI->MacAddr, AI.macAddress, sizeof(pNI->MacAddr));
			pNI->IPAddr	=	 AI.IPAddr;
			pNI->GatewayIpAddr	=	 AI.GatewayIpAddr;
			if (pAdapterInfoEx->pAI[index].bDhcp)
			{
				SetFlag(pNI->flag, DHCPENABLE);
	
			}
			ExInterlockedInsertHeadList(&g_NetCardsInfoHeader.Next, &pNI->Next, &g_NetCardsInfoLock);
// 			LockResource(&g_NetCardsInfoLock, TRUE);
// 			InsertHeadList(&g_NetCardsInfoHeader.Next, &pNI->Next);
// 			UnlockResource(&g_NetCardsInfoLock);
		}
		else
		{
			kfree(pNI);
			pNI	=	NULL;
			goto NextBlock;

		}

// 		if ((p_mini_block->Flags&ISCONNECTED))
// 		{
// 			SetFlag(pNI->flag, ISCONNECTED);
// 		}
		if (AI.status==NdisMediaStateConnected)
		{
			SetFlag(pNI->flag, ISCONNECTED);
		}
		//HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}

		GetNicNameByGUID(&AI.GUID, &uniTmp);
		RtlUnicodeStringToAnsiString(&pNI->Name, &uniTmp, TRUE);
		kprintf("\r\n 检举网卡信息如下:\r\nMAC : %02X:%02X:%02X:%02X:%02X:%02X   \nIP :0x%x   \nflag:0X%X  \n网关IP:0x%x   \nName: %Z \n\n", pNI->MacAddr[0], pNI->MacAddr[1], pNI->MacAddr[2], pNI->MacAddr[3], pNI->MacAddr[4], pNI->MacAddr[5], (pNI->IPAddr), pNI->flag, (pNI->GatewayIpAddr),&pNI->Name);


NextBlock:
		if (dwVersion==Windows_Vista||dwVersion==Windows_7)
		{
			pProtocol	=	(PKK_NDIS_PROTOCOL_BLOCK )((PNDIS_PROTOCOL_BLOCKWin7)pProtocol)->NextProtocol;
		}
		else
		pProtocol	=	pProtocol->NextProtocol;
	}	//end  while (p_driver_block->NextDriver)	
	

	//释放上面申请的内容
	for (index=0; index<pAdapterInfoEx->uNumber; index++)
	{
		kfree(pAdapterInfoEx->pAI[index].GUID.Buffer);

	}
	kfree(pAdapterInfoEx);

	return 1;
}
Ejemplo n.º 13
0
//////////////////////////////////////////////////////////////////////////
//取出pendding的IRP,并完成,用户层异步得到通知
VOID	AskUserWorker(PDEVICE_OBJECT  DeviceObject, PVOID	pContext)
{

	PIO_WORKITEM	pWorkItem	=	NULL;
	PASKUserWorkItemContext	pAskContext	=NULL;
	PIRP		Irp=NULL;
	PLIST_ENTRY	pListEntry=NULL;
	NTSTATUS			Status = STATUS_SUCCESS;
	PIO_STACK_LOCATION	irpStack;
	PVOID				ioBuf;
	ULONG				inBufLength, outBufLength;
	PFIREWALL_ASKUSER	pFireAskUser=NULL;
	KIRQL				CIrql,CIrql2;
	CIrql=CIrql2=0;

	CIrql	=	KeGetCurrentIrql();

	pAskContext	=	(PASKUserWorkItemContext)pContext;
	do 
	{
		if (pAskContext==NULL)
		{
			break;
		}
		while(!IsListEmpty(&g_AskUserConnectListHeader))
		{

			//find a pendding irp 2 ask user decision
			pListEntry	=	ExInterlockedRemoveHeadList(&g_AskUserConnectListHeader, &g_AskUserConnectListLock);
			Irp = CONTAINING_RECORD(pListEntry, IRP, Tail.Overlay.ListEntry);		
			break;

		}
		if (Irp==NULL)
		{
			break;
		}

		irpStack = IoGetCurrentIrpStackLocation(Irp);

		ioBuf = Irp->AssociatedIrp.SystemBuffer;
		inBufLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
		outBufLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;

		pFireAskUser	=	(PFIREWALL_ASKUSER)ioBuf;
		//把DST、SRC IP,PORT带上去,后面再带下来
		//let ring3 know what the port is asking for permission
		*pFireAskUser	=	*(PFIREWALL_ASKUSER)pAskContext->pContext;
		Status = STATUS_SUCCESS;
		Irp->IoStatus.Status = Status;
		Irp->IoStatus.Information	=	sizeof(FIREWALL_ASKUSER);
		IoCompleteRequest(Irp, IO_NO_INCREMENT);

	} while (0);
	if (pAskContext)
	{
		IoFreeWorkItem(pAskContext->pWorkItem);
		kfree(pAskContext->pContext);
		kfree(pAskContext);

	}
	if (KeGetCurrentIrql()>CIrql)
	{
		KeLowerIrql(CIrql);
	}
	if (KeGetCurrentIrql()<CIrql)
	{
		KeRaiseIrql(CIrql, &CIrql2);
	}

}
Ejemplo n.º 14
0
VOID
MiniTimer(
    IN PMINIPORT_DEVICE_EXTENSION HwDeviceExtension
    )
{
	BOOLEAN	BusChanged;

	MiniCounter ++;
	BusChanged = FALSE;

	do {
		PLIST_ENTRY			listEntry;
		PCCB				ccb;
		PSCSI_REQUEST_BLOCK	srb;

		// Get Completed CCB
		listEntry = ExInterlockedRemoveHeadList(
							&HwDeviceExtension->CcbCompletionList,
							&HwDeviceExtension->CcbCompletionListSpinLock
						);

		if(listEntry == NULL)
			break;

		ccb = CONTAINING_RECORD(listEntry, CCB, ListEntry);
		srb = ccb->Srb;
		ASSERT(srb);
		ASSERT(LSCcbIsStatusFlagOn(ccb, CCBSTATUS_FLAG_TIMER_COMPLETE));
		KDPrint(1,("completed SRB:%p SCSIOP:%x\n", srb, srb->Cdb[0]));

		if(LSCcbIsStatusFlagOn(ccb, CCBSTATUS_FLAG_BUSRESET_REQUIRED)) {
			BusChanged = TRUE;
		}
		//
		//	Free a CCB
		//
		LSCcbPostCompleteCcb(ccb);

		ScsiPortNotification(
			RequestComplete,
			HwDeviceExtension,
			srb
			);

		InterlockedDecrement(&HwDeviceExtension->RequestExecuting);

	} while(1);


	if(BusChanged) {
		KDPrint(1,("Bus change detected. RequestExecuting = %d\n", HwDeviceExtension->RequestExecuting));
		ScsiPortNotification(
			BusChangeDetected,
			HwDeviceExtension,
			NULL
			);
	}

	if((MiniCounter % 1000) == 0)
		KDPrint(4,("RequestExecuting = %d\n", HwDeviceExtension->RequestExecuting));

	if(HwDeviceExtension->RequestExecuting != 0) {
		ScsiPortNotification(
			RequestTimerCall,
			HwDeviceExtension,
			MiniTimer,
			1
			);
	} else {
		HwDeviceExtension->TimerOn = FALSE;

		if(ADAPTER_ISSTATUS(HwDeviceExtension,ADAPTER_STATUS_RUNNING))
			ScsiPortNotification(
				RequestTimerCall,
				HwDeviceExtension,
				MiniTimer,
				1 //1000
				);
		
	}

	ScsiPortNotification(
		NextRequest,
		HwDeviceExtension,
		NULL
		);

	return;
}
Ejemplo n.º 15
0
VOID
Readonly_Close (
	IN  PREADONLY	Readonly
	)
{
	NTSTATUS		status;
	LARGE_INTEGER	timeOut;

	PLIST_ENTRY			readonlyRequestEntry;
	PREADONLY_REQUEST	readonlyRequest;


	SPY_LOG_PRINT( LFS_DEBUG_READONLY_INFO, ("Readonly close Readonly = %p\n", Readonly) );

	ExAcquireFastMutex( &Readonly->FastMutex );

	ASSERT( !FlagOn(Readonly->Flags, READONLY_FLAG_RECONNECTING) );

	if (FlagOn(Readonly->Flags, READONLY_FLAG_CLOSED)) {

		//ASSERT( FALSE );
		ExReleaseFastMutex( &Readonly->FastMutex );
		return;
	}

	SetFlag( Readonly->Flags, READONLY_FLAG_CLOSED );

	ExReleaseFastMutex( &Readonly->FastMutex );

	FsRtlNotifyUninitializeSync( &Readonly->NotifySync );

	if (Readonly->ThreadHandle == NULL) {

		//ASSERT( FALSE );
		Readonly_Dereference( Readonly );
		return;
	}

	ASSERT( Readonly->ThreadObject != NULL );

	SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("Readonly close READONLY_REQ_DISCONNECT Readonly = %p\n", Readonly) );

	readonlyRequest = AllocReadonlyRequest( Readonly, 0, FALSE );
	readonlyRequest->RequestType = READONLY_REQ_DISCONNECT;

	QueueingReadonlyRequest( Readonly, readonlyRequest );

	readonlyRequest = AllocReadonlyRequest( Readonly, 0, FALSE );
	readonlyRequest->RequestType = READONLY_REQ_DOWN;

	QueueingReadonlyRequest( Readonly, readonlyRequest );

	SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("Readonly close READONLY_REQ_DISCONNECT end Readonly = %p\n", Readonly) );

	timeOut.QuadPart = -LFS_TIME_OUT;

	status = KeWaitForSingleObject( Readonly->ThreadObject,
									Executive,
									KernelMode,
									FALSE,
									&timeOut );

	if (status == STATUS_SUCCESS) {
	   
		SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("Readonly_Close: thread stoped Readonly = %p\n", Readonly) );

		ObDereferenceObject( Readonly->ThreadObject );

		Readonly->ThreadHandle = NULL;
		Readonly->ThreadObject = NULL;
	
	} else {

		ASSERT( LFS_BUG );
		return;
	}

	if (!IsListEmpty(&Readonly->FcbQueue))
		NDAS_ASSERT( FALSE );

	if (!IsListEmpty(&Readonly->CcbQueue))
		NDAS_ASSERT( FALSE );

	if (!IsListEmpty(&Readonly->RequestQueue))
		NDAS_ASSERT( FALSE );

	while (readonlyRequestEntry = ExInterlockedRemoveHeadList(&Readonly->RequestQueue,
															   &Readonly->RequestQSpinLock)) {

		PREADONLY_REQUEST readonlyRequest2;

		InitializeListHead( readonlyRequestEntry );
			
		readonlyRequest2 = CONTAINING_RECORD( readonlyRequestEntry,
											   READONLY_REQUEST,
											   ListEntry );
        
		readonlyRequest2->ExecuteStatus = STATUS_IO_DEVICE_ERROR;
		
		if (readonlyRequest2->Synchronous == TRUE)
			KeSetEvent( &readonlyRequest2->CompleteEvent, IO_DISK_INCREMENT, FALSE );
		else
			DereferenceReadonlyRequest( readonlyRequest2 );
	}
	
	Readonly_Dereference( Readonly );

	return;
}
Ejemplo n.º 16
0
static VOID IoThreadProc (PVOID threadArg)
{
	EncryptedIoQueue *queue = (EncryptedIoQueue *) threadArg;
	PLIST_ENTRY listEntry;
	EncryptedIoRequest *request;

	KeSetPriorityThread (KeGetCurrentThread(), LOW_REALTIME_PRIORITY);

	if (!queue->IsFilterDevice && queue->SecurityClientContext)
	{
#ifdef DEBUG
		NTSTATUS status =
#endif
		SeImpersonateClientEx (queue->SecurityClientContext, NULL);
		ASSERT (NT_SUCCESS (status));
	}

	while (!queue->ThreadExitRequested)
	{
		if (!NT_SUCCESS (KeWaitForSingleObject (&queue->IoThreadQueueNotEmptyEvent, Executive, KernelMode, FALSE, NULL)))
			continue;

		if (queue->ThreadExitRequested)
			break;

		while ((listEntry = ExInterlockedRemoveHeadList (&queue->IoThreadQueue, &queue->IoThreadQueueLock)))
		{
			InterlockedDecrement (&queue->IoThreadPendingRequestCount);
			request = CONTAINING_RECORD (listEntry, EncryptedIoRequest, ListEntry);
			
#ifdef TC_TRACE_IO_QUEUE
			Dump ("%c   %I64d [%I64d] roff=%I64d rlen=%d\n", request->Item->Write ? 'W' : 'R', request->Item->OriginalIrpOffset.QuadPart, GetElapsedTime (&queue->LastPerformanceCounter), request->Offset.QuadPart, request->Length);
#endif

			// Perform IO request if no preceding request of the item failed
			if (NT_SUCCESS (request->Item->Status))
			{
				if (queue->IsFilterDevice)
				{
					if (queue->RemapEncryptedArea && request->EncryptedLength > 0)
					{
						if (request->EncryptedLength != request->Length)
						{
							// Up to three subfragments may be required to handle a partially remapped fragment
							int subFragment;
							byte *subFragmentData = request->Data;

							for (subFragment = 0 ; subFragment < 3; ++subFragment)
							{
								LARGE_INTEGER subFragmentOffset;
								ULONG subFragmentLength;
								subFragmentOffset.QuadPart = request->Offset.QuadPart;

								switch (subFragment)
								{
								case 0:
									subFragmentLength = (ULONG) request->EncryptedOffset;
									break;

								case 1:
									subFragmentOffset.QuadPart += request->EncryptedOffset + queue->RemappedAreaOffset;
									subFragmentLength = request->EncryptedLength;
									break;

								case 2:
									subFragmentOffset.QuadPart += request->EncryptedOffset + request->EncryptedLength;
									subFragmentLength = (ULONG) (request->Length - (request->EncryptedOffset + request->EncryptedLength));
									break;
								}

								if (subFragmentLength > 0)
								{
									if (request->Item->Write)
										request->Item->Status = TCWriteDevice (queue->LowerDeviceObject, subFragmentData, subFragmentOffset, subFragmentLength);
									else
										request->Item->Status = TCCachedRead (queue, NULL, subFragmentData, subFragmentOffset, subFragmentLength);

									subFragmentData += subFragmentLength;
								}
							}
						}
						else
						{
							// Remap the fragment
							LARGE_INTEGER remappedOffset;
							remappedOffset.QuadPart = request->Offset.QuadPart + queue->RemappedAreaOffset;

							if (request->Item->Write)
								request->Item->Status = TCWriteDevice (queue->LowerDeviceObject, request->Data, remappedOffset, request->Length);
							else
								request->Item->Status = TCCachedRead (queue, NULL, request->Data, remappedOffset, request->Length);
						}
					}
					else
					{
						if (request->Item->Write)
							request->Item->Status = TCWriteDevice (queue->LowerDeviceObject, request->Data, request->Offset, request->Length);
						else
							request->Item->Status = TCCachedRead (queue, NULL, request->Data, request->Offset, request->Length);
					}
				}
				else
				{
					IO_STATUS_BLOCK ioStatus;

					if (request->Item->Write)
						request->Item->Status = ZwWriteFile (queue->HostFileHandle, NULL, NULL, NULL, &ioStatus, request->Data, request->Length, &request->Offset, NULL);
					else
						request->Item->Status = TCCachedRead (queue, &ioStatus, request->Data, request->Offset, request->Length);

					if (NT_SUCCESS (request->Item->Status) && ioStatus.Information != request->Length)
						request->Item->Status = STATUS_END_OF_FILE;
				}
			}

			if (request->Item->Write)
			{
				queue->ReadAheadBufferValid = FALSE;

				ReleaseFragmentBuffer (queue, request->Data);

				if (request->CompleteOriginalIrp)
				{
					CompleteOriginalIrp (request->Item, request->Item->Status,
						NT_SUCCESS (request->Item->Status) ? request->Item->OriginalLength : 0);
				}

				ReleasePoolBuffer (queue, request);
			}
			else
			{
				BOOL readAhead = FALSE;

				if (NT_SUCCESS (request->Item->Status))
					memcpy (request->OrigDataBufferFragment, request->Data, request->Length);

				ReleaseFragmentBuffer (queue, request->Data);
				request->Data = request->OrigDataBufferFragment;

				if (request->CompleteOriginalIrp
					&& queue->LastReadLength > 0
					&& NT_SUCCESS (request->Item->Status)
					&& InterlockedExchangeAdd (&queue->IoThreadPendingRequestCount, 0) == 0)
				{
					readAhead = TRUE;
					InterlockedIncrement (&queue->OutstandingIoCount);
				}

				ExInterlockedInsertTailList (&queue->CompletionThreadQueue, &request->CompletionListEntry, &queue->CompletionThreadQueueLock);
				KeSetEvent (&queue->CompletionThreadQueueNotEmptyEvent, IO_DISK_INCREMENT, FALSE);

				if (readAhead)
				{
					queue->ReadAheadBufferValid = FALSE;
					queue->ReadAheadOffset.QuadPart = queue->LastReadOffset.QuadPart + queue->LastReadLength;
					queue->ReadAheadLength = queue->LastReadLength;

					if (queue->ReadAheadOffset.QuadPart + queue->ReadAheadLength <= queue->MaxReadAheadOffset.QuadPart)
					{
#ifdef TC_TRACE_IO_QUEUE
						Dump ("A   %I64d [%I64d] roff=%I64d rlen=%d\n", request->Item->OriginalIrpOffset.QuadPart, GetElapsedTime (&queue->LastPerformanceCounter), queue->ReadAheadOffset, queue->ReadAheadLength);
#endif
						if (queue->IsFilterDevice)
						{
							queue->ReadAheadBufferValid = NT_SUCCESS (TCReadDevice (queue->LowerDeviceObject, queue->ReadAheadBuffer, queue->ReadAheadOffset, queue->ReadAheadLength));
						}
						else
						{
							IO_STATUS_BLOCK ioStatus;
							queue->ReadAheadBufferValid = NT_SUCCESS (ZwReadFile (queue->HostFileHandle, NULL, NULL, NULL, &ioStatus, queue->ReadAheadBuffer, queue->ReadAheadLength, &queue->ReadAheadOffset, NULL));
							queue->ReadAheadLength = (ULONG) ioStatus.Information;
						}
					}

					DecrementOutstandingIoCount (queue);
				}
			}
		}
	}

	PsTerminateSystemThread (STATUS_SUCCESS);
}
Ejemplo n.º 17
0
VOID
ReadonlyThreadProc (
	IN	PREADONLY	Readonly
	)
{
	BOOLEAN		readonlyThreadTerminate = FALSE;
	PLIST_ENTRY	readonlyRequestEntry;

	
	SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("ReadonlyThreadProc: Start Readonly = %p\n", Readonly) );
	
	Readonly_Reference( Readonly );
	
	Readonly->Thread.Flags = READONLY_THREAD_FLAG_INITIALIZING;

	ExAcquireFastMutex( &Readonly->FastMutex );		
	SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_START );
	ClearFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_INITIALIZING );
	ExReleaseFastMutex( &Readonly->FastMutex );
			
	KeSetEvent( &Readonly->ReadyEvent, IO_DISK_INCREMENT, FALSE );

	readonlyThreadTerminate = FALSE;
	
	while (readonlyThreadTerminate == FALSE) {

		PKEVENT			events[2];
		LONG			eventCount;
		NTSTATUS		eventStatus;
		LARGE_INTEGER	timeOut;
		

		ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

		eventCount = 0;
		events[eventCount++] = &Readonly->RequestEvent;

		timeOut.QuadPart = -LFS_READONLY_THREAD_FLAG_TIME_OUT;

		eventStatus = KeWaitForMultipleObjects(	eventCount,
												events,
												WaitAny,
												Executive,
												KernelMode,
												TRUE,
												&timeOut,
												NULL );

		if (eventStatus == STATUS_TIMEOUT) {

			ReadonlyTryCloseCcb( Readonly );
			ReadonlyDismountVolumeStart( Readonly );
			continue;
		}

		ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
		ASSERT( eventCount < THREAD_WAIT_OBJECTS );
		
		if (!NT_SUCCESS( eventStatus ) || eventStatus >= eventCount) {

			ASSERT( LFS_UNEXPECTED );
			SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_ERROR );
			readonlyThreadTerminate = TRUE;
			continue;
		}
		
		KeClearEvent( events[eventStatus] );

		if (eventStatus == 0) {

			while (!FlagOn(Readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED) && 
				   (readonlyRequestEntry = ExInterlockedRemoveHeadList(&Readonly->RequestQueue,
																	    &Readonly->RequestQSpinLock))) {

				PREADONLY_REQUEST	readonlyRequest;


				InitializeListHead( readonlyRequestEntry );

				readonlyRequest = CONTAINING_RECORD( readonlyRequestEntry,
													  READONLY_REQUEST,
													  ListEntry );

				if (!(readonlyRequest->RequestType == READONLY_REQ_DISCONNECT ||
					  readonlyRequest->RequestType == READONLY_REQ_DOWN		  ||
					  readonlyRequest->RequestType == READONLY_REQ_SEND_MESSAGE)) {

					ASSERT( FALSE );

					ExAcquireFastMutex( &Readonly->FastMutex );
					SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED | READONLY_THREAD_FLAG_ERROR );
					ExReleaseFastMutex( &Readonly->FastMutex );

					ExInterlockedInsertHeadList( &Readonly->RequestQueue,
												 &readonlyRequest->ListEntry,
												 &Readonly->RequestQSpinLock );

					readonlyThreadTerminate = TRUE;
					break;
				}

				if (readonlyRequest->RequestType == READONLY_REQ_DISCONNECT) {
				
					if (readonlyRequest->Synchronous == TRUE)
						KeSetEvent(&readonlyRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE);
					else
						DereferenceReadonlyRequest( readonlyRequest );

					continue;
				}

				if (readonlyRequest->RequestType == READONLY_REQ_DOWN) {

					SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("ReadonlyThread READONLY_REQ_DOWN Readonly = %p\n", Readonly) );

					ExAcquireFastMutex( &Readonly->FastMutex );		
					SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED );
					ExReleaseFastMutex( &Readonly->FastMutex );

					ASSERT( IsListEmpty(&Readonly->RequestQueue) );

					if (readonlyRequest->Synchronous == TRUE)
						KeSetEvent( &readonlyRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferenceReadonlyRequest( readonlyRequest );

					readonlyThreadTerminate = TRUE;
					break;
				}

				ASSERT( readonlyRequest->RequestType == READONLY_REQ_SEND_MESSAGE );
				ASSERT( readonlyRequest->Synchronous == TRUE );

			} // while 
		
		} else {

			NDAS_ASSERT( FALSE );
		}
	}

	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	ExAcquireFastMutex( &Readonly->FastMutex );

	SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED );

	while (readonlyRequestEntry = ExInterlockedRemoveHeadList(&Readonly->RequestQueue,
															   &Readonly->RequestQSpinLock)) {

		PREADONLY_REQUEST readonlyRequest;

		InitializeListHead( readonlyRequestEntry );
			
		readonlyRequest = CONTAINING_RECORD( readonlyRequestEntry,
											  READONLY_REQUEST,
											  ListEntry );
        
		readonlyRequest->ExecuteStatus = STATUS_IO_DEVICE_ERROR;
		
		if (readonlyRequest->Synchronous == TRUE)
			KeSetEvent( &readonlyRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
		else
			DereferenceReadonlyRequest( readonlyRequest );
	}

	ExReleaseFastMutex( &Readonly->FastMutex );

	SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE,
				   ("ReadonlyThreadProc: PsTerminateSystemThread Readonly = %p, IsListEmpty(&Readonly->RequestQueue) = %d\n", 
				     Readonly, IsListEmpty(&Readonly->RequestQueue)) );
	
	ExAcquireFastMutex( &Readonly->FastMutex );
	SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_TERMINATED );
	ExReleaseFastMutex( &Readonly->FastMutex );
	
	Readonly_Dereference( Readonly );

	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
	
	PsTerminateSystemThread( STATUS_SUCCESS );
}
Ejemplo n.º 18
0
VOID
Secondary_Stop (
	IN  PSECONDARY	Secondary
	)
{
	NTSTATUS		status;
	LARGE_INTEGER	timeOut;

	PLIST_ENTRY			secondaryRequestEntry;
	PSECONDARY_REQUEST	secondaryRequest;


	DebugTrace2( 0, Dbg2, ("Secondary stop\n") );

	ExAcquireFastMutex( &Secondary->FastMutex );

	if (FlagOn(Secondary->Flags, SECONDARY_FLAG_CLOSED)) {

		ASSERT( FALSE );
		ExReleaseFastMutex( &Secondary->FastMutex );
		return;
	}

	SetFlag( Secondary->Flags, SECONDARY_FLAG_CLOSED );

	ExReleaseFastMutex( &Secondary->FastMutex );

	if (Secondary->ThreadHandle == NULL) {

		Secondary_Dereference(Secondary);
		return;
	}

	ASSERT( Secondary->ThreadObject != NULL );


	secondaryRequest = AllocSecondaryRequest( Secondary, 0, FALSE );
	secondaryRequest->RequestType = SECONDARY_REQ_DISCONNECT;

	QueueingSecondaryRequest( Secondary, secondaryRequest );

	secondaryRequest = AllocSecondaryRequest( Secondary, 0, FALSE );
	secondaryRequest->RequestType = SECONDARY_REQ_DOWN;

	QueueingSecondaryRequest( Secondary, secondaryRequest );

	timeOut.QuadPart = - NDFAT_TIME_OUT;

	status = KeWaitForSingleObject( Secondary->ThreadObject,
									Executive,
									KernelMode,
									FALSE,
									&timeOut );

	if (status == STATUS_SUCCESS) {
	   
		DebugTrace2( 0, Dbg, ("Secondary_Stop: thread stoped Secondary = %p\n", Secondary));

		ObDereferenceObject( Secondary->ThreadObject );

		Secondary->ThreadHandle = NULL;
		Secondary->ThreadObject = NULL;
	
	} else {

		ASSERT( NDFAT_BUG );
		return;
	}

	ASSERT( IsListEmpty(&Secondary->RecoveryCcbQueue) );
	ASSERT( IsListEmpty(&Secondary->RequestQueue) );

	while (secondaryRequestEntry = ExInterlockedRemoveHeadList(&Secondary->RequestQueue,
															   &Secondary->RequestQSpinLock)) {

		PSECONDARY_REQUEST secondaryRequest;
			
		secondaryRequest = CONTAINING_RECORD( secondaryRequestEntry,
											  SECONDARY_REQUEST,
											  ListEntry );
        
		secondaryRequest->ExecuteStatus = STATUS_IO_DEVICE_ERROR;
		
		if (secondaryRequest->Synchronous == TRUE)
			KeSetEvent( &secondaryRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
		else
			DereferenceSecondaryRequest( secondaryRequest );
	}
	
	return;
}
Ejemplo n.º 19
0
VOID
OnUnload (
	IN PDRIVER_OBJECT DriverObject
	)
/*++

Routine Description:

	Diver exit point. Releases resources and unhooks NDIS routines.


Arguments:

	DriverObject - A pointer to this driver, provided by system.


Return Value:

	None.


Author:

	xiaonie

	2012/07/12


--*/
{
	PLIST_ENTRY pEntry;
	PNDIS_HOOK_LIST_NODE pNdisHookListNode;
	PNDIS_OPEN_BLOCK pOpenBlock;
	LARGE_INTEGER interval;

	// unhook NDIS routines
	while (TRUE) {
		pEntry = ExInterlockedRemoveHeadList(&g_linkListHead, &g_lock);
		if (pEntry == NULL)
			break;
		pNdisHookListNode = CONTAINING_RECORD(pEntry, NDIS_HOOK_LIST_NODE, ListEntry);

		pOpenBlock = pNdisHookListNode->pOpenBlock;

		InterlockedExchange((PLONG)&pOpenBlock->ReceiveHandler, (LONG)pNdisHookListNode->ulRealReceiveHandler);
		// InterlockedExchange((PLONG)&pOpenBlock->WanReceiveHandler, (LONG)pNdisHookListNode->ulRealWanReceivePacketHandler);
		InterlockedExchange((PLONG)&pOpenBlock->ReceivePacketHandler, (LONG)pNdisHookListNode->ulRealProtocolReceiveHandler);
		InterlockedExchange((PLONG)&pOpenBlock->TransferDataCompleteHandler, (LONG)pNdisHookListNode->ulRealTransferDataCompleteHandler);

		// release memory
		ExFreePoolWithTag(pNdisHookListNode, '!nmN');
	}

	// wait 5 sec, reduce the possibility of BSOD.
	KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);
	interval.QuadPart = - 5L * 10L * 1000L * 1000L;
	KeDelayExecutionThread(KernelMode, FALSE, &interval);

	NdisFreeBufferPool(g_BufferPool);
	NdisFreePacketPool(g_PacketPool);

	DbgPrint("NDIS Hook ------ end!\r\n");
}
Ejemplo n.º 20
0
NTSTATUS DeviceControlCompleteRoutine(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
	UNREFERENCED_PARAMETER(pDeviceObject);

	NTSTATUS			status = STATUS_SUCCESS;
	PIO_STACK_LOCATION	pIrpsp = IoGetCurrentIrpStackLocation(pIrp);
	ULONG				uLength = 0;

	PVOID				pBuffer = pIrp->AssociatedIrp.SystemBuffer;
	ULONG				ulInputlength = pIrpsp->Parameters.DeviceIoControl.InputBufferLength;
	ULONG				ulOutputlength = pIrpsp->Parameters.DeviceIoControl.OutputBufferLength;

	do
	{
		switch (pIrpsp->Parameters.DeviceIoControl.IoControlCode)
		{
		case CWK_DVC_SEND_STR:
			{
				ASSERT(pBuffer != NULL);
				ASSERT(ulInputlength > 0);
				ASSERT(ulOutputlength == 0);
			}
			break;
		case CWK_DVC_RECV_STR:
			{
				ASSERT(ulInputlength == 0);

				while (TRUE)
				{
					PEVENT_DATA_NODE pNode = (PEVENT_DATA_NODE)ExInterlockedRemoveHeadList(&g_ListHead, &g_Lock);
					if (NULL != pNode)
					{
						PREGISTRY_EVENT pOutputBuffer = (PREGISTRY_EVENT)pBuffer;
						SIZE_T			ulNumberOfBytes = sizeof(REGISTRY_EVENT) +						// 结构体大小
							pNode->pstRegistryEvent->ulProcessPathLength +								// 进程路径长度
							pNode->pstRegistryEvent->ulRegistryPathLength +								// 路径长度
							pNode->pstRegistryEvent->ulDataLength;										// 数据长度

						if (NULL != pNode->pstRegistryEvent)
						{
							if (ulOutputlength >= ulNumberOfBytes)
							{
								RtlCopyBytes(pOutputBuffer, pNode->pstRegistryEvent, ulNumberOfBytes);
								ExFreePoolWithTag(pNode->pstRegistryEvent, MEM_TAG);
								ExFreePoolWithTag(pNode, MEM_TAG);
							}
							else
							{
								ExInterlockedInsertHeadList(&g_ListHead, (PLIST_ENTRY)pNode, &g_Lock);
							}						
						}

						uLength = (ULONG)ulNumberOfBytes;
						break;
					}
					else
					{
						KeWaitForSingleObject(&g_Event, Executive, KernelMode, 0, 0);
					}
				}
			}
			break;
		default:
			{
				status = STATUS_INVALID_PARAMETER;
			}
			break;
		}
	} while (FALSE);

	pIrp->IoStatus.Status = status;
	pIrp->IoStatus.Information = uLength;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return status;
}
Ejemplo n.º 21
0
VOID AddrFileFree(
    PVOID Object)
/*
 * FUNCTION: Frees an address file object
 * ARGUMENTS:
 *     Object = Pointer to address file object to free
 */
{
  PADDRESS_FILE AddrFile = Object;
  KIRQL OldIrql;
  PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
  PDATAGRAM_SEND_REQUEST SendRequest;
  PLIST_ENTRY CurrentEntry;

  TI_DbgPrint(MID_TRACE, ("Called.\n"));

  /* We should not be associated with a connection here */
  ASSERT(!AddrFile->Connection);

  /* Remove address file from the global list */
  TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
  RemoveEntryList(&AddrFile->ListEntry);
  TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);

  /* FIXME: Kill TCP connections on this address file object */

  /* Return pending requests with error */

  TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting receive requests on AddrFile at (0x%X).\n", AddrFile));

  /* Go through pending receive request list and cancel them all */
  while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, &AddrFile->Lock))) {
    ReceiveRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry);
    (*ReceiveRequest->Complete)(ReceiveRequest->Context, STATUS_CANCELLED, 0);
    /* ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG); FIXME: WTF? */
  }

  TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting send requests on address file at (0x%X).\n", AddrFile));

  /* Go through pending send request list and cancel them all */
  while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, &AddrFile->Lock))) {
    SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry);
    (*SendRequest->Complete)(SendRequest->Context, STATUS_CANCELLED, 0);
    ExFreePoolWithTag(SendRequest, DATAGRAM_SEND_TAG);
  }

  /* Protocol specific handling */
  switch (AddrFile->Protocol) {
  case IPPROTO_TCP:
    if (AddrFile->Port)
    {
        TCPFreePort(AddrFile->Port);
    }
    break;

  case IPPROTO_UDP:
    UDPFreePort( AddrFile->Port );
    break;
  }

  RemoveEntityByContext(AddrFile);

  ExFreePoolWithTag(Object, ADDR_FILE_TAG);
}
Ejemplo n.º 22
0
void DebugPrintSystemThread(IN PVOID Context)
{
	UNICODE_STRING DebugPrintName;
	OBJECT_ATTRIBUTES ObjectAttributes;
	IO_STATUS_BLOCK IoStatus;
	HANDLE DebugPrintDeviceHandle;
	LARGE_INTEGER OneSecondTimeout;
	PDEBUGPRINT_EVENT pEvent;
	PLIST_ENTRY pListEntry;
	ULONG EventDataLen;
	NTSTATUS status;
	//LARGE_INTEGER ByteOffset;

	KeSetPriorityThread(KeGetCurrentThread(),LOW_REALTIME_PRIORITY);

	//创建文件
	
	RtlInitUnicodeString(&DebugPrintName,L"\\Device\\PHDDebugPrint");
	
	InitializeObjectAttributes(&ObjectAttributes,&DebugPrintName,OBJ_CASE_INSENSITIVE,NULL,NULL);
	
	DebugPrintDeviceHandle=NULL;
	status=ZwCreateFile(&DebugPrintDeviceHandle,
		GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
		&ObjectAttributes,
		&IoStatus,
		0,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ|FILE_SHARE_WRITE,
		FILE_OPEN,
		FILE_SYNCHRONOUS_IO_NONALERT,
		NULL,
		0);
	if(!NT_SUCCESS(status)||DebugPrintDeviceHandle==NULL)
		goto exit1;

	//线程主循环代码,写文件

	DBGPRINT(("XIAN CHENG KAI SHI"));
	
	OneSecondTimeout.QuadPart=-1i64*1000000i64;

	DebugPrintStarted=TRUE;

	while(TRUE)
	{
		KeWaitForSingleObject(&ThreadEvent,Executive,KernelMode,FALSE,&OneSecondTimeout);
		
		while(TRUE)
		{
			pListEntry=ExInterlockedRemoveHeadList(&EventList,&EventListLock);
			if(pListEntry==NULL)
			{
				//DBGPRINT(("WOKAOHAIMEILIANSHANG"));
				break;
			}
			else
			{
				DBGPRINT(("YOU QING KUANG"));
			}

			pEvent=
				CONTAINING_RECORD(pListEntry,DEBUGPRINT_EVENT,ListEntry);
			EventDataLen=pEvent->Len;

			status=ZwWriteFile(DebugPrintDeviceHandle,NULL,NULL,NULL,
				&IoStatus,pEvent->EventData,EventDataLen,NULL,NULL);

			if(!NT_SUCCESS(status))
			{
				DBGPRINT("MEI FA XIE A");
			}
			else
			{
				DBGPRINT("WO XIE!");
			}
			ExFreePool(pEvent);
		}

	if(ExitNow)
		break;
	}
exit1:
	if(ThreadObjectPointer!=NULL)
	{
		ObDereferenceObject(&ThreadObjectPointer);
		ThreadObjectPointer=NULL;
	}

	/////////////////////////////////////
	//有待商榷
	DebugPrintStarted=FALSE;
	
	ZwClose(DebugPrintDeviceHandle);
	/////////////////////////////////////

	KeSetEvent(&ThreadExiting,0,FALSE);
	
	PsTerminateSystemThread(STATUS_SUCCESS);	
}
Ejemplo n.º 23
0
VOID
DPReadWriteThread (
	IN PVOID Context
	)
{
	//NTSTATUS类型的函数返回值
	NTSTATUS					ntStatus = STATUS_SUCCESS;
	//用来指向过滤设备的设备扩展的指针
	PDP_FILTER_DEV_EXTENSION	DevExt = (PDP_FILTER_DEV_EXTENSION)Context;
	//请求队列的入口
	PLIST_ENTRY			ReqEntry = NULL;
	//irp指针
	PIRP				Irp = NULL;
	//irp stack指针
	PIO_STACK_LOCATION	Irpsp = NULL;
	//irp中包括的数据地址
	PBYTE				sysBuf = NULL;
	//irp中的数据长度
	ULONG				length = 0;
	//irp要处理的偏移量
	LARGE_INTEGER		offset = { 0 };
	//文件缓冲指针
	PBYTE				fileBuf = NULL;
	//设备缓冲指针
	PBYTE				devBuf = NULL;
	//io操作状态
	IO_STATUS_BLOCK		ios;

	//设置这个线程的优先级
	KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);
	//下面是线程的实现部分,这个循环永不退出
	for (;;)
	{	
		//先等待请求队列同步事件,如果队列中没有irp需要处理,我们的线程就等待在这里,让出cpu时间给其它线程
		KeWaitForSingleObject(
			&DevExt->ReqEvent,
			Executive,
			KernelMode,
			FALSE,
			NULL
			);
		//如果有了线程结束标志,那么就在线程内部自己结束自己
		if (DevExt->ThreadTermFlag)
		{
			//这是线程的唯一退出地点
			PsTerminateSystemThread(STATUS_SUCCESS);
			return;
		}
		//从请求队列的首部拿出一个请求来准备处理,这里使用了自旋锁机制,所以不会有冲突
		while (ReqEntry = ExInterlockedRemoveHeadList(
			&DevExt->ReqList,
			&DevExt->ReqLock
			))
		{
			//从队列的入口里找到实际的irp的地址
			Irp = CONTAINING_RECORD(ReqEntry, IRP, Tail.Overlay.ListEntry);
			//取得irp stack
			Irpsp = IoGetCurrentIrpStackLocation(Irp);
			//获取这个irp其中包含的缓存地址,这个地址可能来自mdl,也可能就是直接的缓冲,这取决于我们当前设备的io方式是buffer还是direct方式
			if (NULL == Irp->MdlAddress)
				sysBuf = (PBYTE)Irp->UserBuffer;
			else
				sysBuf = (PBYTE)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

			if (IRP_MJ_READ == Irpsp->MajorFunction)
			{
				//如果是读的irp请求,我们在irp stack中取得相应的参数作为offset和length
				offset = Irpsp->Parameters.Read.ByteOffset;
				length = Irpsp->Parameters.Read.Length;
			}
			else if (IRP_MJ_WRITE == Irpsp->MajorFunction)
			{
				//如果是写的irp请求,我们在irp stack中取得相应的参数作为offset和length
				offset = Irpsp->Parameters.Write.ByteOffset;
				length = Irpsp->Parameters.Write.Length;
			}
			else
			{
				//除此之外,offset和length都是0
				offset.QuadPart = 0;
				length = 0;
			}
			if (NULL == sysBuf || 0 == length)
			{
				//如果传下来的irp没有系统缓冲或者缓冲的长度是0,那么我们就没有必要处理这个irp,直接下发给下层设备就行了
				goto ERRNEXT;
			}
			//下面是转储的过程了
			if (IRP_MJ_READ == Irpsp->MajorFunction)
			{
				//这里是读的处理
				//首先根据bitmap来判断这次读操作读取的范围是全部为转储空间,还是全部为未转储空间,或者兼而有之
				long tstResult = DPBitmapTest(DevExt->Bitmap, offset, length);
				switch (tstResult)
				{
				case BITMAP_RANGE_CLEAR: 
					//这说明这次读取的操作全部是读取未转储的空间,也就是真正的磁盘上的内容,我们直接发给下层设备去处理
					goto ERRNEXT;
				case BITMAP_RANGE_SET: 
					//这说明这次读取的操作全部是读取已经转储的空间,也就是缓冲文件上的内容,我们从文件中读取出来,然后直接完成这个irp
					//分配一个缓冲区用来从缓冲文件中读取
					if (NULL == (fileBuf = (PBYTE)ExAllocatePoolWithTag(NonPagedPool, length, 'xypD')))
					{
						ntStatus = STATUS_INSUFFICIENT_RESOURCES;
						Irp->IoStatus.Information = 0;
						goto ERRERR;
					}
					RtlZeroMemory(fileBuf,length);
					ntStatus = ZwReadFile(
						DevExt->TempFile,
						NULL,
						NULL,
						NULL,
						&ios,
						fileBuf,
						length,
						&offset,
						NULL);
					if (NT_SUCCESS(ntStatus))
					{
						Irp->IoStatus.Information = length;
						RtlCopyMemory(sysBuf,fileBuf,Irp->IoStatus.Information);
						goto ERRCMPLT;
					}
					else
					{
						ntStatus = STATUS_INSUFFICIENT_RESOURCES;
						Irp->IoStatus.Information = 0;
						goto ERRERR;
					}
					break;

				case BITMAP_RANGE_BLEND:
					//这说明这次读取的操作是混合的,我们也需要从下层设备中读出,同时从文件中读出,然后混合并返回
					//分配一个缓冲区用来从缓冲文件中读取
					if (NULL == (fileBuf = (PBYTE)ExAllocatePoolWithTag(NonPagedPool, length, 'xypD')))
					{
						ntStatus = STATUS_INSUFFICIENT_RESOURCES;
						Irp->IoStatus.Information = 0;
						goto ERRERR;
					}
					RtlZeroMemory(fileBuf,length);
					//分配一个缓冲区用来从下层设备中读取
					if (NULL == (devBuf = (PBYTE)ExAllocatePoolWithTag(NonPagedPool, length, 'xypD')))
					{
						ntStatus = STATUS_INSUFFICIENT_RESOURCES;
						Irp->IoStatus.Information = 0;
						goto ERRERR;
					}
					RtlZeroMemory(devBuf,length);
					ntStatus = ZwReadFile(
						DevExt->TempFile,
						NULL,
						NULL,
						NULL,
						&ios,
						fileBuf,
						length,
						&offset,
						NULL);
					if (!NT_SUCCESS(ntStatus))
					{
						ntStatus = STATUS_INSUFFICIENT_RESOURCES;
						Irp->IoStatus.Information = 0;
						goto ERRERR;
					}
					//把这个irp发给下层设备去获取需要从设备上读取的信息
					ntStatus = DPForwardIrpSync(DevExt->LowerDevObj,Irp);
					if (!NT_SUCCESS(ntStatus))
					{
						ntStatus = STATUS_INSUFFICIENT_RESOURCES;
						Irp->IoStatus.Information = 0;
						goto ERRERR;
					}
					//将从下层设备获取到的数据存储到devBuf中
					memcpy(devBuf, sysBuf, Irp->IoStatus.Information);
					//把从文件获取到的数据和从设备获取到的数据根据相应的bitmap值来进行合并,合并的结果放在devBuf中
					ntStatus = DPBitmapGet(
						DevExt->Bitmap,
						offset,
						length,
						devBuf,
						fileBuf
						);
					if (!NT_SUCCESS(ntStatus))
					{
						ntStatus = STATUS_INSUFFICIENT_RESOURCES;
						Irp->IoStatus.Information = 0;
						goto ERRERR;
					}
					//把合并完的数据存入系统缓冲并完成irp
					memcpy(sysBuf, devBuf, Irp->IoStatus.Information);
					goto ERRCMPLT;
				default:
					ntStatus = STATUS_INSUFFICIENT_RESOURCES;
					goto ERRERR;
				}
			}
			else
			{
				//这里是写的过程
				//对于写,我们直接写缓冲文件,而不会写磁盘数据,这就是所谓的转储,但是转储之后需要在bitmap中做相应的标记
				ntStatus = ZwWriteFile(
					DevExt->TempFile,
					NULL,
					NULL,
					NULL,
					&ios,
					sysBuf,
					length,
					&offset,
					NULL);
				if(!NT_SUCCESS(ntStatus))
				{
					ntStatus = STATUS_INSUFFICIENT_RESOURCES;
					goto ERRERR;
				}
				else
				{
					if (NT_SUCCESS(ntStatus = DPBitmapSet(DevExt->Bitmap, offset, length)))
					{
						goto ERRCMPLT;
					}
					else
					{
						ntStatus = STATUS_INSUFFICIENT_RESOURCES;
						goto ERRERR;
					}
				}
			}
ERRERR:
			if (NULL != fileBuf)
			{
				ExFreePool(fileBuf);
				fileBuf = NULL;
			}
			if (NULL != devBuf)
			{
				ExFreePool(devBuf);
				devBuf = NULL;
			}
			DPCompleteRequest(
				Irp,
				ntStatus,
				IO_NO_INCREMENT
				);
			continue;
ERRNEXT:
			if (NULL != fileBuf)
			{
				ExFreePool(fileBuf);
				fileBuf = NULL;
			}
			if (NULL != devBuf)
			{
				ExFreePool(devBuf);
				devBuf = NULL;
			}	
			DPSendToNextDriver(
				DevExt->LowerDevObj,
				Irp);
			continue;
ERRCMPLT:
			if (NULL != fileBuf)
			{
				ExFreePool(fileBuf);
				fileBuf = NULL;
			}
			if (NULL != devBuf)
			{
				ExFreePool(devBuf);
				devBuf = NULL;
			}
			DPCompleteRequest(
				Irp,
				STATUS_SUCCESS,
				IO_DISK_INCREMENT
				);
			continue;
			
		}
	}

}