hello i am trying to implement repeater Irp in the TDI driver for netbios insufficient stack location problem.i have some doubts regarding this. could someone please help me out. when i get request in my dispatch request.
i do like this.
if( attached ) /* TCP or UDP*/
{
//this will tell if i need to have completion routine for TDI_CONNECT, OPEN_ADDRESS etc
HandleRquest( Irp, &completionRoutine, &Context );
//completion routine??
if( completionRoutine )
{
//not enough locations?
if( irp->CurrentLocation <= 1 )
{
//alloate the context which will hold the compeltion routine address
CompletionContext* Compcontext = GetContext();
//save the comletions routine
Compcontext.CompletionRoutine = completionRoutine;
Compcontext.Context = Context;
//get current stack location
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(irp);
//allocate the new one
PIRP newIrp = IoAllocateIrp(dx->dev_lower->StackSize + 1, FALSE);
ASSERT(newIrp);
if ( newIrp == NULL )
{
//pass the request as it is
//TBD: Free the completion routine context
IoSkipCurrentIrpStackLocation(irp);
return IoCallDriver(dx->dev_lower, irp);
}
//Get the next irp Stack location that will be used by lower level driver
SubStack = IoGetNextIrpStackLocation(newIrp);
//copy the device object
SubStack->DeviceObject = dev;
SubStack->Parameters.Others.Argument1 = (PVOID)irp;
IoSetNextIrpStackLocation(newIrp);
SubStack = IoGetNextIrpStackLocation(newIrp);
RtlCopyMemory( SubStack, stack, FIELD_OFFSET( IO_STACK_LOCATION, CompletionRoutine ) );
//set the completion routine
IoSetCompletionRoutine(newIrp, OnRepeaterComplete, Compcontext, TRUE, TRUE, TRUE);
//set to not supported so that varifier will be happy
subirp->IoStatus.Status = STATUS_NOT_SUPPORTED;
//do i need to mark irp pending??
IoMarkIrpPending(Irp);
IoCallDriver(tdo, newIrp);
return STATUS_PENDING;
}
else
{
//we have enough stack location so just set out completion routine
IoCopyCurrentIrpStackLocationToNext(irp);
IoSetCompletionRoutine(irp,completionRoutine, Context, TRUE, TRUE, TRUE);
return IoCallDriver(dx->dev_lower, irp);
}
}
{
//do not have completion routine. skip it
IoSkipCurrentIrpStackLocation(irp);
return IoCallDriver(dx->dev_lower, irp);
}
}
NTSTATUS OnRepeaterComplete(PDEVICE_OBJECT tdo, PIRP subirp, PVOID context)
{
PIO_STACK_LOCATION substack = NULL;
PIRP OriginalIrp = NULL;
//get the completion context
CompletionRoutineContext* Completion_context = (CompletionRoutineContext*)context;
//get the current irp location
substack = IoGetCurrentIrpStackLocation(subirp);
//get the original irp
OriginalIrp = (PIRP) substack->Parameters.Others.Argument1;
//we need to call the completion routine that we set earlier
if( Completion_context != NULL )
{
//this will call crOpendAddress, crConnect, crTDIconnect completion routine
Completion_context->Completion_routine.CallBack( tdo,
OriginalIrp,Completion_context->Completion_routine.Conetext );
}
else
{
ASSERT(0);
}
//do i need the mark original irp pending if repeater irp returns pending
//mark the original irp pending
if(subirp->PendingReturned)
IoMarkIrpPending(OriginalIrp);
//set the status
OriginalIrp->IoStatus = subirp->IoStatus;
//free the completion context
if( Completion_context )
FreeCompletionRoutineContext(Completion_context);
//free our irp
IoFreeIrp(subirp);
//complete the oroginal irp
IoCompleteRequest(OriginalIrp, IO_NO_INCREMENT);
return STATUS_MORE_PROCESSING_REQUIRED;
}
my doubt is this.
if the repeater irp returns pending then do i have to mark the original irp as pending?
i think yes.
what are the other members of orignal irp that i still neecd to update with the results of repeater irp.
i mean besides iostatus.
also in the walter oney book there is a concept called “Needvote” does this apply for my case. i think not.
regards
Deep