有关费尔防火墙一书TDI代码“网上邻居”不能访问功能的修复

 

本文首先发表于:http://bbs.driverdevelop.com/htm_data/10/0703/100349.html

有关费尔防火墙一书TDI代码“网上邻居”不能访问功能的修复  

 

参照了开源代码,现修正如下:
/*if (Irp->CurrentLocation == 1)
   {
       ULONG ReturnedInformation = 0;

       DBGPRINT(("PacketDispatch encountered bogus current location/n"));

       RC = STATUS_INVALID_DEVICE_REQUEST;
       Irp->IoStatus.Status = RC;
       Irp->IoStatus.Information = ReturnedInformation;
       IoCompleteRequest(Irp, IO_NO_INCREMENT);

       return( RC );
   }*/

修正如下:
sequenceNumber = 0;
   seq = InterlockedIncrement(&sequenceNumber);
   if (Irp->CurrentLocation < DeviceObject->StackSize)
   {
       return PassThroughWithNewIrp(DeviceObject, Irp, seq);
   }
   else
   {
       NextIrpStack    = IoGetNextIrpStackLocation(Irp);
       *NextIrpStack    = *IrpStack;
       IoSetCompletionRoutine(Irp,PacketCompletion,NULL,TRUE,TRUE,TRUE);
       return IoCallDriver(pTDIH_DeviceExtension->LowerDeviceObject,Irp);
   }

上面用到的子函数体内容如下:
NTSTATUS NetPassOnNormally (PDEVICE_OBJECT HookDevice, IN PIRP Irp)
{
   PTDIH_DeviceExtension hookExt = HookDevice->DeviceExtension;
   
   // Back the stack up one
   IoSkipCurrentIrpStackLocation(Irp);
   
   // Call the next lower driver
   return IoCallDriver(hookExt->LowerDeviceObject, Irp);
}

NTSTATUS NetOtherIRPCompletionRoutine (PDEVICE_OBJECT DeviceObject,
                            PIRP Irp, PVOID Context)
{
PIRP origIrp = (PIRP) Context;
ULONG seq;
KIRQL oldirql;
PCHAR eventBuffer;
   
// Extract the sequence number from the original IRP's UserEvent field,
// then restore that field's proper value from the new IRP's field

seq = (ULONG) origIrp->UserEvent;
origIrp->UserEvent = Irp->UserEvent;
       
// Copy important possibly returned fields in this IRP to the original IRP
origIrp->IoStatus = Irp->IoStatus;
origIrp->PendingReturned = Irp->PendingReturned;
origIrp->MdlAddress = Irp->MdlAddress;

// If this IRP was pending, mark the new and original IRP's pending
if (Irp->PendingReturned) {
  IoMarkIrpPending(Irp);
  IoMarkIrpPending(origIrp);
}

// Free the IRP we created
IoFreeIrp(Irp);

// Complete the original IRP

IoCompleteRequest(origIrp, IO_NO_INCREMENT);

// Return STATUS_MORE_PROCESSING_REQUIRED to indicate that we're going
// to take control of our IRP and finish handling it. Actually, we've
// already handled it by freeing it. If we didn't take control of it,
// the I/O Manager might try to process our IRP further, which would
// we bad since it's been freed.
return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS PassThroughWithNewIrp(PDEVICE_OBJECT HookDevice, IN PIRP Irp, ULONG seq)
{
   PTDIH_DeviceExtension    hookExt = HookDevice->DeviceExtension;
   PIRP                    newIrp;
   PIO_STACK_LOCATION        currentIrpStackLocation;
   PIO_STACK_LOCATION        newIrpFirstStackLocation;
   
   // Allocate a new IRP with stack size sufficient for the next lower device
   newIrp = IoAllocateIrp(hookExt->LowerDeviceObject->StackSize, FALSE);
   DbgPrint("FilterTdiDriver.sys, lower stack, %d, current stack, %d",
       hookExt->LowerDeviceObject->StackSize, hookExt->TargetDeviceObject->StackSize);
   if (newIrp == NULL){
       return NetPassOnNormally(HookDevice, Irp);
   }
   
   // Fill in important fields of new IRP with those of original IRP
   newIrp->MdlAddress = Irp->MdlAddress;
   newIrp->Flags = Irp->Flags;
   newIrp->AssociatedIrp = Irp->AssociatedIrp;
   newIrp->RequestorMode = Irp->RequestorMode;
   newIrp->UserIosb = Irp->UserIosb;
   newIrp->UserEvent = Irp->UserEvent;
   newIrp->Overlay = Irp->Overlay;
   newIrp->UserBuffer = Irp->UserBuffer;
   newIrp->Tail.Overlay.AuxiliaryBuffer = Irp->Tail.Overlay.AuxiliaryBuffer;
   newIrp->Tail.Overlay.OriginalFileObject = Irp->Tail.Overlay.OriginalFileObject;
   newIrp->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread;
   
   // Copy current stack location to the first stack location in the new IRP
   currentIrpStackLocation = IoGetCurrentIrpStackLocation(Irp);
   newIrpFirstStackLocation = IoGetNextIrpStackLocation(newIrp);
   *newIrpFirstStackLocation = *currentIrpStackLocation;
   
   // Set the completion routine to VTrcNetOtherIRPCompletionRoutine, with
   // the original IRP as context. Save the sequence number in the UserEvent
   // field so that it can be used in the completion routine. (The completion
   // routine will restore the original UserEvent field from the new IRP.)
   Irp->UserEvent = (PKEVENT) seq;
   IoSetCompletionRoutine(newIrp, NetOtherIRPCompletionRoutine, (PVOID) Irp, TRUE, TRUE, TRUE);
   
   // Send the new IRP to the lower-level device
   return IoCallDriver(hookExt->LowerDeviceObject, newIrp);
}

你可能感兴趣的:(有关费尔防火墙一书TDI代码“网上邻居”不能访问功能的修复)