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); }
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; }
//前面说到为每一个磁盘设备对象生成了一个系统线程,用来处理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) ); } } }
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; }
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 ); }
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; } }
// // 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); }
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; }
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)); } } }
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); }
/* 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; }
////////////////////////////////////////////////////////////////////////// //取出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); } }
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; }
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; }
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); }
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 ); }
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; }
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"); }
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; }
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); }
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); }
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; } } }