Пример #1
0
NTSTATUS EVhdNotifyRecoveryStatus(ParserInstance *parser, RecoveryStatusCompletionRoutine pfnCompletionCb, void *pInterface)
{
	PDEVICE_OBJECT pDeviceObject = NULL;
	if (parser->bResiliencyEnabled)
	{
		if (!ExAcquireRundownProtection(&parser->RecoveryRundownProtection))
			return STATUS_UNSUCCESSFUL;

		parser->pfnRecoveryStatusCallback = pfnCompletionCb;
		parser->pRecoveryStatusInterface = pInterface;

		IoReuseIrp(parser->pRecoveryStatusIrp, STATUS_PENDING);
		parser->pRecoveryStatusIrp->Tail.Overlay.Thread = (PETHREAD)__readgsqword(0x188);				// Pointer to calling thread control block
		PIO_STACK_LOCATION pStackFrame = IoGetNextIrpStackLocation(parser->pRecoveryStatusIrp);
		pDeviceObject = IoGetRelatedDeviceObject(parser->pVhdmpFileObject);
		pStackFrame->FileObject = parser->pVhdmpFileObject;
		pStackFrame->DeviceObject = pDeviceObject;
		pStackFrame->Parameters.DeviceIoControl.IoControlCode = IOCTL_STORAGE_VHD_NOTIFY_RECOVERY_STATUS;
		pStackFrame->Parameters.DeviceIoControl.InputBufferLength = 0;
		pStackFrame->Parameters.DeviceIoControl.OutputBufferLength = 0;
		pStackFrame->MajorFunction = IRP_MJ_DEVICE_CONTROL;
		pStackFrame->MinorFunction = 0;
		pStackFrame->Flags = 0;
		pStackFrame->Control = SL_INVOKE_ON_CANCEL | SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
		pStackFrame->Context = parser;
		pStackFrame->CompletionRoutine = EvhdRecoveryStatusCompletionRoutine;
		IoCallDriver(pDeviceObject, parser->pRecoveryStatusIrp);
		return STATUS_PENDING;
	}
	else
		return STATUS_UNSUCCESSFUL;
}
Пример #2
0
static NTSTATUS EvhdDirectIoControl(ParserInstance *parser, ULONG ControlCode, PVOID pSystemBuffer, ULONG InputBufferSize,
	ULONG OutputBufferSize)
{
	NTSTATUS status = STATUS_SUCCESS;
	PDEVICE_OBJECT pDeviceObject = NULL;
	KeEnterCriticalRegion();
	FltAcquirePushLockExclusive(&parser->DirectIoPushLock);

	IoReuseIrp(parser->pDirectIoIrp, STATUS_PENDING);
	parser->pDirectIoIrp->Flags |= IRP_NOCACHE;
	parser->pDirectIoIrp->Tail.Overlay.Thread = (PETHREAD)__readgsqword(0x188);		// Pointer to calling thread control block
	parser->pDirectIoIrp->AssociatedIrp.SystemBuffer = pSystemBuffer;				// IO buffer for buffered control code
	// fill stack frame parameters for synchronous IRP call
	PIO_STACK_LOCATION pStackFrame = IoGetNextIrpStackLocation(parser->pDirectIoIrp);
	pDeviceObject = IoGetRelatedDeviceObject(parser->pVhdmpFileObject);
	pStackFrame->FileObject = parser->pVhdmpFileObject;
	pStackFrame->DeviceObject = pDeviceObject;
	pStackFrame->Parameters.DeviceIoControl.IoControlCode = ControlCode;
	pStackFrame->Parameters.DeviceIoControl.InputBufferLength = InputBufferSize;
	pStackFrame->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferSize;
	pStackFrame->MajorFunction = IRP_MJ_DEVICE_CONTROL;
	pStackFrame->MinorFunction = 0;
	pStackFrame->Flags = 0;
	pStackFrame->Control = 0;
	IoSynchronousCallDriver(pDeviceObject, parser->pDirectIoIrp);
	status = parser->pDirectIoIrp->IoStatus.Status;
	FltReleasePushLock(&parser->DirectIoPushLock);
	KeLeaveCriticalRegion();
	return status;
}
Пример #3
0
NTSTATUS EVhdGetQosStatusDisk(ParserInstance *parser, PVOID pSystemBuffer, ULONG32 dwSize, QoSStatusCompletionRoutine pfnCompletionCb, PVOID pInterface)
{
	PDEVICE_OBJECT pDeviceObject = NULL;
	parser->pQoSStatusInterface = pInterface;
	parser->pfnQoSStatusCallback = pfnCompletionCb;
	memmove(parser->pQoSStatusBuffer, pSystemBuffer, dwSize);

	IoReuseIrp(parser->pQoSStatusIrp, STATUS_PENDING);
	parser->pQoSStatusIrp->Tail.Overlay.Thread = (PETHREAD)__readgsqword(0x188);				// Pointer to calling thread control block
	parser->pQoSStatusIrp->AssociatedIrp.SystemBuffer = parser->pQoSStatusBuffer;				// IO buffer for buffered control code
	PIO_STACK_LOCATION pStackFrame = IoGetNextIrpStackLocation(parser->pQoSStatusIrp);
	pDeviceObject = IoGetRelatedDeviceObject(parser->pVhdmpFileObject);
	pStackFrame->FileObject = parser->pVhdmpFileObject;
	pStackFrame->DeviceObject = pDeviceObject;
	pStackFrame->Parameters.DeviceIoControl.IoControlCode = IOCTL_STORAGE_VHD_GET_QOS_STATUS;
	pStackFrame->Parameters.DeviceIoControl.InputBufferLength = dwSize;
	pStackFrame->Parameters.DeviceIoControl.OutputBufferLength = 0x58;
	pStackFrame->MajorFunction = IRP_MJ_DEVICE_CONTROL;
	pStackFrame->MinorFunction = 0;
	pStackFrame->Flags = 0;
	pStackFrame->Control = SL_INVOKE_ON_CANCEL | SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
	pStackFrame->Context = parser;
	pStackFrame->CompletionRoutine = EvhdGetQosStatusCompletionRoutine;
	IoCallDriver(pDeviceObject, parser->pQoSStatusIrp);
	return STATUS_PENDING;
}
Пример #4
0
FORCEINLINE
VOID
FxIrp::Reuse(
    __in NTSTATUS Status
    )
{
    IoReuseIrp(m_Irp, Status);
}
Пример #5
0
VOID
LspDataReset(
	__in PDEVICE_OBJECT DeviceObject,
	__in PLSP_TRANSFER_DATA LspTransferData)
{
	RtlZeroMemory(&LspTransferData->Overlapped, sizeof(XTDI_OVERLAPPED));
	LspTransferData->Overlapped.CompletionRoutine = LspTransferCompletion;
	LspTransferData->Overlapped.UserContext = DeviceObject;
	LspTransferData->Flags = 0;
	ASSERT(NULL != LspTransferData->Irp);
	// IoFreeIrp(LspTransferData->Irp);
	// LspTransferData->Irp = IoAllocateIrp(DeviceObject->StackSize + 1, FALSE);
	IoReuseIrp(LspTransferData->Irp, STATUS_SUCCESS);
}
Пример #6
0
VOID
ReInitWskData(
__out PIRP*		pIrp,
__out PKEVENT	CompletionEvent
)
{
	ASSERT(pIrp);
	ASSERT(CompletionEvent);

	KeResetEvent(CompletionEvent);
	IoReuseIrp(*pIrp, STATUS_UNSUCCESSFUL);
	IoSetCompletionRoutine(*pIrp, CompletionRoutine, CompletionEvent, TRUE, TRUE, TRUE);

	return;
}
Пример #7
0
/*
 *  SubmitTransferPacket
 *
 *        Set up the IRP for the TRANSFER_PACKET submission and send it down.
 */
VOID SubmitTransferPacket(PTRANSFER_PACKET Pkt)
{
    PCOMMON_DEVICE_EXTENSION commonExtension = Pkt->Fdo->DeviceExtension;
    PDEVICE_OBJECT nextDevObj = commonExtension->LowerDeviceObject;
    PIO_STACK_LOCATION nextSp = IoGetNextIrpStackLocation(Pkt->Irp);
    
    ASSERT(Pkt->Irp->CurrentLocation == Pkt->Irp->StackCount+1);

    /*
     *  Attach the SRB to the IRP.
     *  The reused IRP's stack location has to be rewritten for each retry
     *  call because IoCompleteRequest clears the stack locations.
     */
    IoReuseIrp(Pkt->Irp, STATUS_NOT_SUPPORTED);
    nextSp->MajorFunction = IRP_MJ_SCSI;
    nextSp->Parameters.Scsi.Srb = &Pkt->Srb;
    Pkt->Srb.ScsiStatus = Pkt->Srb.SrbStatus = 0;
    if (Pkt->CompleteOriginalIrpWhenLastPacketCompletes){
        /*
         *  Only dereference the "original IRP"'s stack location
         *  if its a real client irp (as opposed to a static irp 
         *  we're using just for result status for one of the non-IO scsi commands).
         *
         *  For read/write, propagate the storage-specific IRP stack location flags
         *  (e.g. SL_OVERRIDE_VERIFY_VOLUME, SL_WRITE_THROUGH).
         */
        PIO_STACK_LOCATION origCurSp = IoGetCurrentIrpStackLocation(Pkt->OriginalIrp);
        nextSp->Flags = origCurSp->Flags;
    }

    /*
     *  Write MDL address to new IRP. In the port driver the SRB DataBuffer
     *  field is used as the actual buffer pointer within the MDL, 
     *  so the same MDL can be used for each partial transfer. 
     *  This saves having to build a new MDL for each partial transfer.
     */
    Pkt->Irp->MdlAddress = Pkt->OriginalIrp->MdlAddress;
    
    IoSetCompletionRoutine(Pkt->Irp, TransferPktComplete, Pkt, TRUE, TRUE, TRUE);
    IoCallDriver(nextDevObj, Pkt->Irp);
}
Пример #8
0
// for Reusing IRP, first, create IRP outside, and input SendEx's parameter. Irp can be freed in finalize point.
LONG
NTAPI
SendEx(
__in PIRP           pIrp,
__in PWSK_SOCKET	WskSocket,
__in PVOID			Buffer,
__in ULONG			BufferSize,
__in ULONG			Flags,
__in struct			drbd_transport *transport,
__in enum			drbd_stream stream
)
{
	KEVENT		CompletionEvent = { 0 };
	WSK_BUF		WskBuffer = { 0 };
	LONG		BytesSent = SOCKET_ERROR;
	NTSTATUS	Status = STATUS_UNSUCCESSFUL;

	if (g_SocketsState != INITIALIZED || !WskSocket || !Buffer || !pIrp || ((int)BufferSize <= 0))
		return SOCKET_ERROR;
		

	Status = InitWskBuffer(Buffer, BufferSize, &WskBuffer);
	if (!NT_SUCCESS(Status)) {
		return SOCKET_ERROR;
	}

	IoReuseIrp(pIrp, STATUS_UNSUCCESSFUL);
	KeInitializeEvent(&CompletionEvent, SynchronizationEvent, FALSE);
	IoSetCompletionRoutine(pIrp, CompletionRoutine, &CompletionEvent, TRUE, TRUE, TRUE);
	

	Flags |= WSK_FLAG_NODELAY;

	Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH)WskSocket->Dispatch)->WskSend(
		WskSocket,
		&WskBuffer,
		Flags,
		pIrp);

	if (Status == STATUS_PENDING) {
		KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
		Status = pIrp->IoStatus.Status;
	}

	if (NT_SUCCESS(Status)) {
		BytesSent = (LONG)pIrp->IoStatus.Information;
	}
	else {
		WDRBD_WARN("tx error(%s) wsk(0x%p)\n", GetSockErrorString(pIrp->IoStatus.Status), WskSocket);
		switch (Status) {
		case STATUS_IO_TIMEOUT:
			BytesSent = -EAGAIN;
			break;
		case STATUS_INVALID_DEVICE_STATE:
			BytesSent = -EAGAIN;
			break;
		default:
			BytesSent = -ECONNRESET;
			break;
		}
	}

	FreeWskBuffer(&WskBuffer);
	return BytesSent;
}
Пример #9
0
NTSTATUS
IrpClose(
		 IN PFILE_OBJECT FileObject)
{
	NTSTATUS ntStatus;
	IO_STATUS_BLOCK IoStatusBlock;
	PIRP Irp;
	KEVENT kEvent;
	PIO_STACK_LOCATION IrpSp;
	PDEVICE_OBJECT pBaseDeviceObject = FileObject->Vpb->DeviceObject;

	if (FileObject->Vpb == 0 || FileObject->Vpb->DeviceObject == NULL)
		return STATUS_UNSUCCESSFUL;

	Irp = IoAllocateIrp(FileObject->Vpb->DeviceObject->StackSize, FALSE);
	if(Irp == NULL) return STATUS_INSUFFICIENT_RESOURCES;

	KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

	Irp->UserEvent = &kEvent;
	Irp->UserIosb = &IoStatusBlock;
	Irp->RequestorMode = KernelMode;
	Irp->Flags = IRP_CLOSE_OPERATION|IRP_SYNCHRONOUS_API;
	Irp->Tail.Overlay.Thread = PsGetCurrentThread();
	Irp->Tail.Overlay.OriginalFileObject = FileObject;

	IrpSp = IoGetNextIrpStackLocation(Irp);
	IrpSp->MajorFunction = IRP_MJ_CLEANUP;
	IrpSp->FileObject = FileObject;

	ntStatus = IoCallDriver(pBaseDeviceObject, Irp);
	if (ntStatus == STATUS_PENDING)
		KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL);

	ntStatus = IoStatusBlock.Status;
	if(!NT_SUCCESS(ntStatus))
	{
		IoFreeIrp(Irp);
		return ntStatus;
	}

	KeClearEvent(&kEvent);
	IoReuseIrp(Irp , STATUS_SUCCESS);

	Irp->UserEvent = &kEvent;
	Irp->UserIosb = &IoStatusBlock;
	Irp->Tail.Overlay.OriginalFileObject = FileObject;
	Irp->Tail.Overlay.Thread = PsGetCurrentThread();
	Irp->AssociatedIrp.SystemBuffer = (PVOID)NULL;
	Irp->Flags = IRP_CLOSE_OPERATION|IRP_SYNCHRONOUS_API;

	IrpSp = IoGetNextIrpStackLocation(Irp);
	IrpSp->MajorFunction = IRP_MJ_CLOSE;
	IrpSp->FileObject = FileObject;

	if (FileObject->Vpb && !(FileObject->Flags & FO_DIRECT_DEVICE_OPEN))
	{
		InterlockedDecrement(&FileObject->Vpb->ReferenceCount);
		FileObject->Flags |= FO_FILE_OPEN_CANCELLED;

	}

	ntStatus = IoCallDriver(pBaseDeviceObject, Irp);

	if (ntStatus == STATUS_PENDING)
		KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL);

	IoFreeIrp(Irp);

	ntStatus = IoStatusBlock.Status;

	return ntStatus;
}
Пример #10
0
/*
 *  SubmitTransferPacket
 *
 *        Set up the IRP for the TRANSFER_PACKET submission and send it down.
 */
NTSTATUS SubmitTransferPacket(PTRANSFER_PACKET Pkt)
{
    PCOMMON_DEVICE_EXTENSION commonExtension = Pkt->Fdo->DeviceExtension;
    PDEVICE_OBJECT nextDevObj = commonExtension->LowerDeviceObject;
    PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Pkt->Fdo->DeviceExtension;
    PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
    BOOLEAN idleRequest = FALSE;
    PIO_STACK_LOCATION nextSp;

    ASSERT(Pkt->Irp->CurrentLocation == Pkt->Irp->StackCount+1);

    /*
     *  Attach the SRB to the IRP.
     *  The reused IRP's stack location has to be rewritten for each retry
     *  call because IoCompleteRequest clears the stack locations.
     */
    IoReuseIrp(Pkt->Irp, STATUS_NOT_SUPPORTED);
    nextSp = IoGetNextIrpStackLocation(Pkt->Irp);
    nextSp->MajorFunction = IRP_MJ_SCSI;
    nextSp->Parameters.Scsi.Srb = &Pkt->Srb;
    Pkt->Srb.ScsiStatus = Pkt->Srb.SrbStatus = 0;
    Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
    if (Pkt->CompleteOriginalIrpWhenLastPacketCompletes){
        /*
         *  Only dereference the "original IRP"'s stack location
         *  if its a real client irp (as opposed to a static irp
         *  we're using just for result status for one of the non-IO scsi commands).
         *
         *  For read/write, propagate the storage-specific IRP stack location flags
         *  (e.g. SL_OVERRIDE_VERIFY_VOLUME, SL_WRITE_THROUGH).
         */
        PIO_STACK_LOCATION origCurSp = IoGetCurrentIrpStackLocation(Pkt->OriginalIrp);
        nextSp->Flags = origCurSp->Flags;
    }

    //
    // If the request is not split, we can use the original IRP MDL.  If the
    // request needs to be split, we need to use a partial MDL.  The partial MDL
    // is needed because more than one driver might be mapping the same MDL
    // and this causes problems.
    //
    if (Pkt->UsePartialMdl == FALSE) {
        Pkt->Irp->MdlAddress = Pkt->OriginalIrp->MdlAddress;
    } else {
        IoBuildPartialMdl(Pkt->OriginalIrp->MdlAddress, Pkt->PartialMdl, Pkt->Srb.DataBuffer, Pkt->Srb.DataTransferLength);
        Pkt->Irp->MdlAddress = Pkt->PartialMdl;
    }

    DBGLOGSENDPACKET(Pkt);
    HISTORYLOGSENDPACKET(Pkt);

    //
    // Set the original irp here for SFIO.
    //
    Pkt->Srb.SrbExtension = (PVOID) (Pkt->OriginalIrp);

    //
    // No need to lock for IdlePrioritySupported, since it will
    // be modified only at initialization time.
    //
    if (fdoData->IdlePrioritySupported == TRUE) {
        idleRequest = ClasspIsIdleRequest(Pkt->OriginalIrp);
        if (idleRequest) {
            InterlockedIncrement(&fdoData->ActiveIdleIoCount);
        } else {
            InterlockedIncrement(&fdoData->ActiveIoCount);
        }
    }

    IoSetCompletionRoutine(Pkt->Irp, TransferPktComplete, Pkt, TRUE, TRUE, TRUE);
    return IoCallDriver(nextDevObj, Pkt->Irp);
}
Пример #11
0
VOID 
NICFreeRCB(
    IN PRCB pRCB)
/*++

Routine Description:

    pRCB      - pointer to RCB block
        
Arguments:

    This routine reinitializes the RCB block and puts it back
    into the RecvFreeList for reuse.
    

Return Value:

    VOID

--*/
{
    PMP_ADAPTER Adapter = pRCB->Adapter;
    ULONG ulSendLowW= NIC_SEND_LOW_WATERMARK;
    
    DEBUGP(MP_TRACE, ("--> NICFreeRCB %p\n", pRCB));
    
    ASSERT(pRCB->Irp);    // shouldn't be NULL
    ASSERT(!pRCB->Ref); // should be 0
    ASSERT(pRCB->Adapter); // shouldn't be NULL

    IoReuseIrp(pRCB->Irp, STATUS_SUCCESS);    

	pRCB->nextndeoffset=0;    
	pRCB->nextndpoffset=0;
	pRCB->bIsOver=FALSE;
	pRCB->ulSize=0;
    // 
    // Set the MDL field to NULL so that we don't end up double freeing the
    // MDL in our call to IoFreeIrp.
    // 
      
    pRCB->Irp->MdlAddress = NULL;
    
    //
    // Re adjust the length to the originl size
    //
    //NdisAdjustBufferLength(pRCB->BufferArray[0], pRCB->ulBufferSize);

    //
    // Insert the RCB back in the Recv free list     
    //
    NdisAcquireSpinLock(&Adapter->RecvLock);
    
    RemoveEntryList(&pRCB->List);
    
    InsertTailList(&Adapter->RecvFreeList, &pRCB->List);

    NdisInterlockedDecrement(&Adapter->nBusyRecv);
    ASSERT(Adapter->nBusyRecv >= 0);
    
    NdisReleaseSpinLock(&Adapter->RecvLock); 
    
    //
    // For performance, instead of scheduling a workitem at the end of
    // every read completion, we will do it only when the number of 
    // outstanding IRPs goes below NIC_SEND_LOW_WATERMARK.
    // We shouldn't queue a workitem if it's already scheduled and waiting in
    // the system workitem queue to be fired.
    //
    if((!ulSendLowW || Adapter->nBusyRecv <= NIC_SEND_LOW_WATERMARK)
            && MP_TEST_FLAG(Adapter, fMP_POST_READS) && 
            (InterlockedExchange(&Adapter->IsReadWorkItemQueued, TRUE) == FALSE)) {

        Adapter->nReadWorkItemScheduled++;
        MP_INC_REF(Adapter);                   
        NdisScheduleWorkItem(&Adapter->ReadWorkItem);   
    }
    DEBUGP(MP_TRACE, ("<-- NICFreeRCB %d\n", Adapter->nBusyRecv));
    
}
Пример #12
0
VOID 
NICFreeNotify(
    IN PNOTICB pNotiCB)
/*++

Routine Description:

    pRCB      - pointer to RCB block
        
Arguments:

    This routine reinitializes the RCB block and puts it back
    into the RecvFreeList for reuse.
    

Return Value:

    VOID

--*/
{
    PMP_ADAPTER Adapter = pNotiCB->Adapter;
    
    DEBUGP(MP_TRACE, ("--> NICFreeNotify %p\n", pNotiCB));
    
    ASSERT(pNotiCB->Irp);    // shouldn't be NULL
    ASSERT(!pNotiCB->Ref); // should be 0
    ASSERT(pNotiCB->Adapter); // shouldn't be NULL

    IoReuseIrp(pNotiCB->Irp, STATUS_SUCCESS);    


	pNotiCB->ulSize=0;
    // 
    // Set the MDL field to NULL so that we don't end up double freeing the
    // MDL in our call to IoFreeIrp.
    // 
      
    pNotiCB->Irp->MdlAddress = NULL;
    
    //
    // Insert the RCB back in the Recv free list     
    //
    NdisAcquireSpinLock(&Adapter->InterruptNotifyLock);
    
    RemoveEntryList(&pNotiCB->List);
    
    InsertTailList(&Adapter->InterruptFreeList, &pNotiCB->List);

    NdisInterlockedDecrement(&Adapter->nBusyNotify);
    ASSERT(Adapter->nBusyNotify >= 0);
    
    NdisReleaseSpinLock(&Adapter->InterruptNotifyLock); 
    
    //
    // For performance, instead of scheduling a workitem at the end of
    // every read completion, we will do it only when the number of 
    // outstanding IRPs goes below NIC_SEND_LOW_WATERMARK.
    // We shouldn't queue a workitem if it's already scheduled and waiting in
    // the system workitem queue to be fired.
    //
    if((Adapter->nBusyNotify ==0)
            && MP_TEST_FLAG(Adapter, fMP_POST_INTERRUPT)) {

        MP_INC_REF(Adapter);                   
        NdisScheduleWorkItem(&Adapter->InterruptNotifyItem);   
    }
    DEBUGP(MP_TRACE, ("<-- NICFreeNotify %d\n", Adapter->nBusyNotify));
    
}
Пример #13
0
NTSTATUS
	IrpCloseFile(
	IN PDEVICE_OBJECT DeviceObject,
	IN PFILE_OBJECT FileObject
	)
{
	NTSTATUS status;
	KEVENT event;
	PIRP irp;
	PVPB vpb;
	IO_STATUS_BLOCK ioStatusBlock;
	PIO_STACK_LOCATION irpSp;

	PAGED_CODE();

	irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);

	if (irp == NULL) {
		return STATUS_INSUFFICIENT_RESOURCES;
	}
	KeInitializeEvent(&event, SynchronizationEvent, FALSE);

	irp->Tail.Overlay.OriginalFileObject = FileObject;
	irp->Tail.Overlay.Thread = PsGetCurrentThread();
	irp->RequestorMode = KernelMode;
	irp->UserEvent = &event;
	irp->UserIosb = &irp->IoStatus;
	irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE)NULL;
	irp->Flags = IRP_SYNCHRONOUS_API | IRP_CLOSE_OPERATION;

	irpSp = IoGetNextIrpStackLocation(irp);
	irpSp->MajorFunction = IRP_MJ_CLEANUP;
	irpSp->FileObject = FileObject;

	status = IoCallDriver(DeviceObject, irp);

	if (status == STATUS_PENDING) {
		KeWaitForSingleObject(&event,
			UserRequest,
			KernelMode,
			FALSE,
			NULL);
	}

	IoReuseIrp(irp , STATUS_SUCCESS);
	KeClearEvent(&event);

	irpSp = IoGetNextIrpStackLocation(irp);
	irpSp->MajorFunction = IRP_MJ_CLOSE;
	irpSp->FileObject = FileObject;

	irp->UserIosb = &ioStatusBlock;
	irp->UserEvent = &event;
	irp->Tail.Overlay.OriginalFileObject = FileObject;
	irp->Tail.Overlay.Thread = PsGetCurrentThread();
	irp->AssociatedIrp.SystemBuffer = (PVOID)NULL;
	irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API;

	vpb = FileObject->Vpb;

	if (vpb && !(FileObject->Flags & FO_DIRECT_DEVICE_OPEN)) {
		InterlockedDecrement((PLONG)&vpb->ReferenceCount);
		FileObject->Flags |= FO_FILE_OPEN_CANCELLED;
	}

	status = IoCallDriver(DeviceObject, irp);

	if (status == STATUS_PENDING) {
		KeWaitForSingleObject(	&event,
			Executive,
			KernelMode,
			FALSE,
			NULL);
	}
	//LCXL:ADD-
	InterlockedIncrement(&FileObject->DeviceObject->ReferenceCount);
	//ObDereferenceObject(FileObject);
	//LCXL:Del
	IoFreeIrp(irp);

	return status;
}