Example #1
0
NTSTATUS
PvfsListAddTail(
    PPVFS_LIST pList,
    PLW_LIST_LINKS pItem
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;

    BAIL_ON_INVALID_PTR(pList, ntError);
    BAIL_ON_INVALID_PTR(pItem, ntError);

    /* Using >= here to be safe.  Technically, == should
       be fine */

    if (PvfsListIsFull(pList)) {
        ntError = STATUS_INSUFFICIENT_RESOURCES;
        BAIL_ON_NT_STATUS(ntError);
    }

    LwListInsertTail(&pList->DataList, pItem);
    pList->CurrentSize++;

    ntError = STATUS_SUCCESS;

cleanup:
    return ntError;

error:
    goto cleanup;
}
Example #2
0
VOID
RdrNotifyContextList(
    PLW_LIST_LINKS pList,
    BOOLEAN bLocked,
    pthread_mutex_t* pMutex,
    NTSTATUS status,
    PVOID pParam
    )
{
    LW_LIST_LINKS List;
    PLW_LIST_LINKS pLink = NULL;
    BOOLEAN bWasLocked = bLocked;

    LWIO_LOCK_MUTEX(bLocked, pMutex);

    LwListInit(&List);

    while ((pLink = LwListRemoveHead(pList)))
    {
        LwListInsertTail(&List, pLink);
    }

    LWIO_UNLOCK_MUTEX(bLocked, pMutex);
    RdrContinueContextList(&List, status, pParam);
    LWIO_LOCK_MUTEX(bLocked, pMutex);

    while ((pLink = LwListRemoveHead(&List)))
    {
        LwListInsertTail(pList, pLink);
    }

    if (!bWasLocked)
    {
        LWIO_UNLOCK_MUTEX(bLocked, pMutex);
    }
}
Example #3
0
NTSTATUS
IopIrpAttach(
    IN OUT PIRP pIrp,
    IN IRP_TYPE Type,
    IN PIO_FILE_OBJECT pFileObject
    )
{
    NTSTATUS status = 0;
    int EE = 0;
    PIRP_INTERNAL irpInternal = IopIrpGetInternal(pIrp);

    LWIO_ASSERT(!pIrp->FileHandle);
    LWIO_ASSERT(pIrp->Type == IRP_TYPE_UNINITIALIZED);
    LWIO_ASSERT(Type != IRP_TYPE_UNINITIALIZED);

    IopFileObjectLock(pFileObject);

    // TODO-Add FILE_OBJECT_FLAG_CLOSED
    if ((Type != IRP_TYPE_CLOSE) &&
        (IsSetFlag(pFileObject->Flags, FILE_OBJECT_FLAG_CANCELLED) ||
         IsSetFlag(pFileObject->Flags, FILE_OBJECT_FLAG_RUNDOWN)))
    {
        status = STATUS_CANCELLED;
        GOTO_CLEANUP_EE(EE);
    }
    else
    {
        LwListInsertTail(&pFileObject->IrpList,
                         &irpInternal->FileObjectLinks);
    }

    // These are immutable from here until the IRP is freed.
    pIrp->Type = Type;
    pIrp->FileHandle = pFileObject;
    IopFileObjectReference(pFileObject);
    // The file object reference keeps an implicit reference to the
    // device and driver.
    pIrp->DeviceHandle = pFileObject->pDevice;
    pIrp->DriverHandle = pFileObject->pDevice->Driver;

cleanup:
    IopFileObjectUnlock(pFileObject);

    IO_LOG_LEAVE_ON_STATUS_EE(status, EE);
    return status;
}
Example #4
0
PVOID
IopIrpSaveZctIrp(
    IN OUT PIO_FILE_OBJECT pFileObject,
    IN PIRP pIrp,
    IN PVOID pCompletionContext
    )
{
    PIRP_INTERNAL irpInternal = IopIrpGetInternal(pIrp);

    LWIO_ASSERT(pCompletionContext);

    IopIrpReference(pIrp);

    pIrp->Args.ReadWrite.ZctCompletionContext = pCompletionContext;

    IopFileObjectLock(pFileObject);
    LwListInsertTail(&pFileObject->ZctCompletionIrpList, &irpInternal->CancelLinks);
    IopFileObjectUnlock(pFileObject);

    return pIrp;
}
Example #5
0
static
BOOLEAN
RdrSessionSetupComplete2(
    PRDR_OP_CONTEXT pContext,
    NTSTATUS status,
    PVOID pParam
    )
{
    PRDR_SESSION2 pSession = pParam;
    PRDR_TREE2 pTree = NULL;
    BOOLEAN bTreeLocked = FALSE;
    BOOLEAN bFreeContext = FALSE;

    BAIL_ON_NT_STATUS(status);

    status = RdrTree2FindOrCreate(
        &pSession,
        pContext->State.TreeConnect.pwszSharename,
        &pTree);
    BAIL_ON_NT_STATUS(status);

    pContext->State.TreeConnect.pTree2 = pTree;

    LWIO_LOCK_MUTEX(bTreeLocked, &pTree->mutex);

    switch (pTree->state)
    {
    case RDR_TREE_STATE_NOT_READY:
        pTree->state = RDR_TREE_STATE_INITIALIZING;

        pContext->Continue = RdrFinishTreeConnect2;

        status = RdrTransceiveTreeConnect2(pContext, pTree, pTree->pwszPath);
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_TREE_STATE_INITIALIZING:
        pContext->Continue = RdrTreeConnect2Complete;
        LwListInsertTail(&pTree->StateWaiters, &pContext->Link);
        bFreeContext = TRUE;
        status = STATUS_PENDING;
        break;
    case RDR_TREE_STATE_READY:
        RdrTreeConnect2Complete(pContext, status, pTree);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_TREE_STATE_ERROR:
        status = pTree->error;
        BAIL_ON_NT_STATUS(status);
        break;
    }

 cleanup:

    LWIO_UNLOCK_MUTEX(bTreeLocked, &pTree->mutex);

    if (status != STATUS_PENDING)
    {
        RdrContinueContext(pContext->State.TreeConnect.pContinue, status, NULL);
        bFreeContext = TRUE;
    }

    if (bFreeContext)
    {
        RdrFreeTreeConnectContext(pContext);
    }

    return FALSE;

 error:

    if (status != STATUS_PENDING && pTree)
    {
        LWIO_UNLOCK_MUTEX(bTreeLocked, &pTree->mutex);
        RdrTree2Invalidate(pTree, status);
        RdrTree2Release(pTree);
    }

    if (status != STATUS_PENDING && pSession)
    {
        RdrSession2Release(pSession);
    }

    goto cleanup;
}
Example #6
0
BOOLEAN
RdrNegotiateComplete2(
    PRDR_OP_CONTEXT pContext,
    NTSTATUS status,
    PVOID pParam
    )
{
    PRDR_SOCKET pSocket = pParam;
    PRDR_SESSION2 pSession = NULL;
    BOOLEAN bSessionLocked = FALSE;
    BOOLEAN bFreeContext = FALSE;
    PIO_CREDS pCreds = pContext->State.TreeConnect.pCreds;

    BAIL_ON_NT_STATUS(status);

    if (pContext->State.TreeConnect.bStopOnDfs &&
        pSocket->capabilities & RDR_SMB2_CAP_DFS)
    {
        status = STATUS_DFS_EXIT_PATH_FOUND;
        BAIL_ON_NT_STATUS(status);
    }

    status = RdrSession2FindOrCreate(
        &pSocket,
        pContext->State.TreeConnect.pCreds,
        pContext->State.TreeConnect.Uid,
        &pSession);
    BAIL_ON_NT_STATUS(status);

    pContext->State.TreeConnect.pSession2 = pSession;

    LWIO_LOCK_MUTEX(bSessionLocked, &pSession->mutex);

    switch (pSession->state)
    {
    case RDR_SESSION_STATE_NOT_READY:
        pSession->state = RDR_SESSION_STATE_INITIALIZING;

        switch (pCreds->type)
        {
        case IO_CREDS_TYPE_KRB5_TGT:
            status = SMBCredTokenToKrb5CredCache(
                pCreds,
                &pContext->State.TreeConnect.pszCachePath);
            BAIL_ON_NT_STATUS(status);
            break;
        case IO_CREDS_TYPE_PLAIN:
            break;
        default:
            status = STATUS_ACCESS_DENIED;
            BAIL_ON_NT_STATUS(status);
        }

        LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
        RdrProcessSessionSetupResponse2(pContext, STATUS_SUCCESS, NULL);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_INITIALIZING:
        pContext->Continue = RdrSessionSetupComplete2;
        LwListInsertTail(&pSession->StateWaiters, &pContext->Link);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_READY:
        LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
        RdrSessionSetupComplete2(pContext, status, pSession);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_ERROR:
        status = pSession->error;
        BAIL_ON_NT_STATUS(status);
        break;
    }

 cleanup:

     LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);

     if (status != STATUS_PENDING)
     {
         RdrContinueContext(pContext->State.TreeConnect.pContinue, status, NULL);
         bFreeContext = TRUE;
     }

     if (bFreeContext)
     {
         RdrFreeTreeConnectContext(pContext);
     }

     return FALSE;

 error:

     if (status != STATUS_PENDING && pSession)
     {
         LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
         if (status != STATUS_DFS_EXIT_PATH_FOUND)
         {
             RdrSession2Invalidate(pSession, status);
         }
         RdrSession2Release(pSession);
     }

     if (status != STATUS_PENDING && pSocket)
     {
         if (status != STATUS_DFS_EXIT_PATH_FOUND)
         {
             RdrSocketInvalidate(pSocket, status);
         }
         RdrSocketRelease(pSocket);
     }

     goto cleanup;
}
Example #7
0
static
BOOLEAN
RdrNegotiateComplete(
    PRDR_OP_CONTEXT pContext,
    NTSTATUS status,
    PVOID pParam
    )
{
    PRDR_SOCKET pSocket = pParam;
    PRDR_SESSION pSession = NULL;
    BOOLEAN bSessionLocked = FALSE;
    BOOLEAN bFreeContext = FALSE;
    PIO_CREDS pCreds = pContext->State.TreeConnect.pCreds;

    BAIL_ON_NT_STATUS(status);

    /* Several op contexts could be queued with this function
     * as the continue routine before we transition to SMB2 mode,
     * so we need to hand off to the correct function in this case.
     * Subsequent attempts should go straight to connect2.c
     */
    if (pSocket->version == SMB_PROTOCOL_VERSION_2)
    {
        /* Short circuit to SMB2 session setup logic in connect2.c */
        return RdrNegotiateComplete2(pContext, status, pParam);
    }

    if (pContext->State.TreeConnect.bStopOnDfs &&
        pSocket->capabilities & CAP_DFS)
    {
        /* Abort tree connect because we need to do DFS referral processing first */
        status = STATUS_DFS_EXIT_PATH_FOUND;
        BAIL_ON_NT_STATUS(status);
    }

    status = RdrSessionFindOrCreate(
        &pSocket,
        pContext->State.TreeConnect.pCreds,
        pContext->State.TreeConnect.Uid,
        &pSession);
    BAIL_ON_NT_STATUS(status);

    pContext->State.TreeConnect.pSession = pSession;

    LWIO_LOCK_MUTEX(bSessionLocked, &pSession->mutex);

    switch (pSession->state)
    {
    case RDR_SESSION_STATE_NOT_READY:
        pSession->state = RDR_SESSION_STATE_INITIALIZING;

        switch (pCreds->type)
        {
        case IO_CREDS_TYPE_KRB5_TGT:
            status = SMBCredTokenToKrb5CredCache(
                pCreds,
                &pContext->State.TreeConnect.pszCachePath);
            BAIL_ON_NT_STATUS(status);
            break;
        case IO_CREDS_TYPE_PLAIN:
            break;
        default:
            status = STATUS_ACCESS_DENIED;
            BAIL_ON_NT_STATUS(status);
        }

        LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
        RdrProcessSessionSetupResponse(pContext, STATUS_SUCCESS, NULL);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_INITIALIZING:
        pContext->Continue = RdrSessionSetupComplete;
        LwListInsertTail(&pSession->StateWaiters, &pContext->Link);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_READY:
        LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
        RdrSessionSetupComplete(pContext, status, pSession);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_ERROR:
        status = pSession->error;
        BAIL_ON_NT_STATUS(status);
        break;
    }

cleanup:

    LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);

    if (status != STATUS_PENDING)
    {
        RdrContinueContext(pContext->State.TreeConnect.pContinue, status, NULL);
        bFreeContext = TRUE;
    }

    if (bFreeContext)
    {
        RdrFreeTreeConnectContext(pContext);
    }

    return FALSE;

error:

    if (status != STATUS_PENDING && pSession)
    {
        LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
        if (status != STATUS_DFS_EXIT_PATH_FOUND)
        {
            RdrSessionInvalidate(pSession, status);
        }
        RdrSessionRelease(pSession);
    }

    if (status != STATUS_PENDING && pSocket)
    {
        if (status != STATUS_DFS_EXIT_PATH_FOUND)
        {
            RdrSocketInvalidate(pSocket, status);
        }
        RdrSocketRelease(pSocket);
    }

    goto cleanup;
}
Example #8
0
NTSTATUS
RdrTreeConnect(
    PCWSTR pwszHostname,
    PCWSTR pwszSharename,
    PIO_CREDS pCreds,
    uid_t Uid,
    BOOLEAN bStopOnDfs,
    PRDR_OP_CONTEXT pContinue
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PRDR_OP_CONTEXT pContext = NULL;
    BOOLEAN bSocketLocked = FALSE;
    PRDR_SOCKET pSocket = NULL;

    status = RdrCreateContext(pContinue->pIrp, &pContext);
    BAIL_ON_NT_STATUS(status);

    LWIO_LOG_DEBUG("Tree connect context %p will continue %p\n", pContext, pContinue);

    pContext->State.TreeConnect.Uid = Uid;
    pContext->State.TreeConnect.bStopOnDfs = bStopOnDfs;
    pContext->State.TreeConnect.pContinue = pContinue;

    status = LwRtlWC16StringDuplicate(
        &pContext->State.TreeConnect.pwszSharename,
        pwszSharename);
    BAIL_ON_NT_STATUS(status);

    pContext->State.TreeConnect.pCreds = pCreds;

    status = RdrSocketFindOrCreate(
        pwszHostname,
        &pSocket);
    BAIL_ON_NT_STATUS(status);

    pContext->State.TreeConnect.pSocket = pSocket;

    LWIO_LOCK_MUTEX(bSocketLocked, &pSocket->mutex);

    switch (pSocket->state)
    {
    case RDR_SOCKET_STATE_NOT_READY:
        pSocket->state = RDR_SOCKET_STATE_CONNECTING;
        LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex);

        /* Add extra reference to socket for work item */
        RdrSocketRetain(pSocket);
        status = LwRtlQueueWorkItem(
            gRdrRuntime.pThreadPool,
            RdrSocketConnectWorkItem,
            pSocket,
            0);
        if (status)
        {
            /* Nevermind */
            RdrSocketRelease(pSocket);
        }
        BAIL_ON_NT_STATUS(status);

        pContext->Continue = RdrProcessNegotiateResponse;

        status = RdrTransceiveNegotiate(pContext, pSocket);
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SOCKET_STATE_CONNECTING:
    case RDR_SOCKET_STATE_NEGOTIATING:
        pContext->Continue = RdrNegotiateComplete;
        LwListInsertTail(&pSocket->StateWaiters, &pContext->Link);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SOCKET_STATE_READY:
        LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex);
        RdrNegotiateComplete(pContext, STATUS_SUCCESS, pSocket);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SOCKET_STATE_ERROR:
        status = pSocket->error;
        BAIL_ON_NT_STATUS(status);
        break;
    }

cleanup:

    LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex);

    if (status != STATUS_PENDING)
    {
        RdrFreeTreeConnectContext(pContext);
    }

    return status;

error:

    if (status != STATUS_PENDING && pSocket)
    {
        LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex);
        RdrSocketInvalidate(pSocket, status);
        RdrSocketRelease(pSocket);
    }

    goto cleanup;
}
Example #9
0
NTSTATUS
IopFileObjectAllocate(
    OUT PIO_FILE_OBJECT* ppFileObject,
    IN PIO_DEVICE_OBJECT pDevice,
    IN PIO_FILE_NAME FileName
    )
{
    NTSTATUS status = 0;
    int EE = 0;
    PIO_FILE_OBJECT pFileObject = NULL;

    status = IO_ALLOCATE(&pFileObject, IO_FILE_OBJECT, sizeof(*pFileObject));
    GOTO_CLEANUP_ON_STATUS_EE(status, EE);

    pFileObject->ReferenceCount = 1;
    pFileObject->pDevice = pDevice;
    IopDeviceReference(pDevice);

    LwListInit(&pFileObject->IrpList);
    LwListInit(&pFileObject->DeviceLinks);
    LwListInit(&pFileObject->RundownLinks);
    LwListInit(&pFileObject->ZctCompletionIrpList);

    // Pre-allocate IRP for close.
    status = IopIrpCreateDetached(&pFileObject->pCloseIrp);
    GOTO_CLEANUP_ON_STATUS_EE(status, EE);

    if (FileName->RootFileHandle)
    {
        SetFlag(pFileObject->Flags, FILE_OBJECT_FLAG_RELATIVE);
    }

    status = LwRtlUnicodeStringDuplicate(
                    &pFileObject->FileName,
                    &FileName->Name);
    GOTO_CLEANUP_ON_STATUS_EE(status, EE);

    status = LwRtlInitializeMutex(&pFileObject->Mutex, TRUE);
    GOTO_CLEANUP_ON_STATUS_EE(status, EE);

    status = LwRtlInitializeConditionVariable(&pFileObject->Rundown.Condition);
    GOTO_CLEANUP_ON_STATUS_EE(status, EE);

    IopDeviceLock(pDevice);
    if (IsSetFlag(pDevice->Flags, IO_DEVICE_OBJECT_FLAG_RUNDOWN) ||
        IsSetFlag(pDevice->Flags, IO_DEVICE_OBJECT_FLAG_RUNDOWN_DRIVER))
    {
        // TODO: Find "correct" error code.
        status = STATUS_INVALID_HANDLE;
    }
    else
    {
        LwListInsertTail(&pDevice->FileObjectsList, &pFileObject->DeviceLinks);
    }
    IopDeviceUnlock(pDevice);

cleanup:
    if (status)
    {
        IopFileObjectDereference(&pFileObject);
    }

    *ppFileObject = pFileObject;

    IO_LOG_LEAVE_ON_STATUS_EE(status, EE);
    return status;
}
Example #10
0
NTSTATUS
IopDeviceRundown(
    IN PIO_DEVICE_OBJECT pDeviceObject
    )
{
    NTSTATUS status = 0;
    int EE = 0;
    BOOLEAN isLocked = FALSE;
    PLW_LIST_LINKS pLinks = NULL;
    LW_LIST_LINKS rundownList = { 0 };

    LwListInit(&rundownList);

    IopDeviceLock(pDeviceObject);
    isLocked = TRUE;

    if (IsSetFlag(pDeviceObject->Flags, IO_DEVICE_OBJECT_FLAG_RUNDOWN))
    {
        // TODO: Perhaps wait if currently running down.

        status = STATUS_SUCCESS;
        GOTO_CLEANUP_EE(EE);
    }

    SetFlag(pDeviceObject->Flags, IO_DEVICE_OBJECT_FLAG_RUNDOWN);

    // Gather rundown list

    for (pLinks = pDeviceObject->FileObjectsList.Next;
         pLinks != &pDeviceObject->FileObjectsList;
         pLinks = pLinks->Next)
    {
        PIO_FILE_OBJECT pFileObject = LW_STRUCT_FROM_FIELD(pLinks, IO_FILE_OBJECT, DeviceLinks);

        IopFileObjectReference(pFileObject);
        LwListInsertTail(&rundownList, &pFileObject->RundownLinks);
    }

    IopDeviceUnlock(pDeviceObject);
    isLocked = FALSE;

    // Now, actually run down every file w/o holding the device lock.

    while (!LwListIsEmpty(&rundownList))
    {
        PIO_FILE_OBJECT pFileObject = NULL;

        pLinks = LwListRemoveHead(&rundownList);
        pFileObject = LW_STRUCT_FROM_FIELD(pLinks, IO_FILE_OBJECT, RundownLinks);

        IopFileObjectRundown(pFileObject);
    }

    IopRootRemoveDevice(pDeviceObject->Driver->Root, &pDeviceObject->RootLinks);

cleanup:
    if (isLocked)
    {
        IopDeviceUnlock(pDeviceObject);
    }

    IO_LOG_LEAVE_ON_STATUS_EE(status, EE);
    return status;
}
Example #11
0
VOID
IopIrpCancelFileObject(
    IN PIO_FILE_OBJECT pFileObject,
    IN BOOLEAN IsForRundown
    )
{
    BOOLEAN isLocked = FALSE;
    PLW_LIST_LINKS pLinks = NULL;
    PIRP_INTERNAL irpInternal = NULL;
    LW_LIST_LINKS cancelList = { 0 };
    PIRP pIrp = NULL;

    LwListInit(&cancelList);

    // Gather IRPs we want to cancel while holding FO lock.
    IopFileObjectLock(pFileObject);
    isLocked = TRUE;

    if (IsSetFlag(pFileObject->Flags, FILE_OBJECT_FLAG_CANCELLED))
    {
        GOTO_CLEANUP();
    }

    if (IsForRundown)
    {
        SetFlag(pFileObject->Flags, FILE_OBJECT_FLAG_CANCELLED);
    }

    // gather list of IRPs
    for (pLinks = pFileObject->IrpList.Next;
         pLinks != &pFileObject->IrpList;
         pLinks = pLinks->Next)
    {
        irpInternal = LW_STRUCT_FROM_FIELD(pLinks, IRP_INTERNAL, FileObjectLinks);

        LWIO_ASSERT(irpInternal->Irp.FileHandle == pFileObject);

        // Verify that this IRP is not already being cancelled.
        if (!irpInternal->CancelLinks.Next)
        {
            IopIrpReference(&irpInternal->Irp);
            LwListInsertTail(&cancelList, &irpInternal->CancelLinks);
        }
    }
    IopFileObjectUnlock(pFileObject);
    isLocked = FALSE;

    // Iterate over list, calling IopIrpCancel as appropriate.
    while (!LwListIsEmpty(&cancelList))
    {
        pLinks = LwListRemoveHead(&cancelList);
        irpInternal = LW_STRUCT_FROM_FIELD(pLinks, IRP_INTERNAL, CancelLinks);
        pIrp = &irpInternal->Irp;

        IopIrpCancel(pIrp);
        IopIrpDereference(&pIrp);
    }

cleanup:
    if (isLocked)
    {
        IopFileObjectUnlock(pFileObject);
    }
}