⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 create.c

📁 This is the library for all storage drivers. It simplifies writing a storage driver by implementing
💻 C
📖 第 1 页 / 共 2 页
字号:
        srb = ClasspAllocateSrb(FdoExtension);

        if(srb == NULL) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            leave;
        }

        RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));

        cdb = (PCDB) srb->Cdb;

        //
        // Determine if this is a "secured" request.
        //

        if(LockType == SecureMediaLock) {
             
            PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
            PFILE_OBJECT fileObject = irpStack->FileObject;

            //
            // Make sure that the file object we are supplied has a
            // proper FsContext before we try doing a secured lock.
            //

            if(fileObject != NULL) {
                fsContext = ClasspGetFsContext(commonExtension, fileObject);
            }

            if (fsContext == NULL) {

                //
                // This handle isn't setup correctly.  We can't let the
                // operation go.
                //

                status = STATUS_INVALID_PARAMETER;
                leave;
            }
        }

        if(Lock) {

            //
            // This is a lock command.  Reissue the command in case bus or
            // device was reset and the lock was cleared.
            // note: may need to decrement count if actual lock operation
            //       failed....
            //

            switch(LockType) {

                case SimpleMediaLock: {
                    FdoExtension->LockCount++;
                    countChanged = TRUE;
                    break;
                }

                case SecureMediaLock: {
                    fsContext->LockCount++;
                    FdoExtension->ProtectedLockCount++;
                    countChanged = TRUE;
                    break;
                }

                case InternalMediaLock: {
                    FdoExtension->InternalLockCount++;
                    countChanged = TRUE;
                    break;
                }
            }
        
        } else {

            //
            // This is an unlock command.  If it's a secured one then make sure
            // the caller has a lock outstanding or return an error.
            // note: may need to re-increment the count if actual unlock
            //       operation fails....
            //

            switch(LockType) {

                case SimpleMediaLock: {
                    if(FdoExtension->LockCount != 0) {
                        FdoExtension->LockCount--;
                        countChanged = TRUE;
                    }
                    break;
                }

                case SecureMediaLock: {
                    if(fsContext->LockCount == 0) {
                        status = STATUS_INVALID_DEVICE_STATE;
                        leave;
                    }
                    fsContext->LockCount--;
                    FdoExtension->ProtectedLockCount--;
                    countChanged = TRUE;
                    break;
                }

                case InternalMediaLock: {
                    ASSERT(FdoExtension->InternalLockCount != 0);
                    FdoExtension->InternalLockCount--;
                    countChanged = TRUE;
                    break;
                }
            }

            //
            // We only send an unlock command to the drive if both the
            // secured and unsecured lock counts have dropped to zero.
            //

            if((FdoExtension->ProtectedLockCount != 0) ||
               (FdoExtension->InternalLockCount != 0) ||
               (FdoExtension->LockCount != 0)) {

                status = STATUS_SUCCESS;
                leave;
            }
        }

        status = STATUS_SUCCESS;
        if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {

            srb->CdbLength = 6;
            cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
    
            //
            // TRUE - prevent media removal.
            // FALSE - allow media removal.
            //
    
            cdb->MEDIA_REMOVAL.Prevent = Lock;
    
            //
            // Set timeout value.
            //
    
            srb->TimeOutValue = FdoExtension->TimeOutValue;
    
            //
            // The actual lock operation on the device isn't so important
            // as the internal lock counts.  Ignore failures.
            //
    
            status = ClassSendSrbSynchronous(FdoExtension->DeviceObject,
                                             srb,
                                             NULL,
                                             0,
                                             FALSE);
        }

    } finally {

        if (!NT_SUCCESS(status)) {
            DebugPrint((2,
                        "ClasspEjectionControl: FAILED status %x -- "
                        "reverting lock counts\n", status));
            
            if (countChanged) {

                //
                // have to revert to previous counts if the
                // lock/unlock operation actually failed.
                //

                if(Lock) {
                    
                    switch(LockType) {

                        case SimpleMediaLock: {
                            FdoExtension->LockCount--;
                            break;
                        }

                        case SecureMediaLock: {
                            fsContext->LockCount--;
                            FdoExtension->ProtectedLockCount--;
                            break;
                        }

                        case InternalMediaLock: {
                            FdoExtension->InternalLockCount--;
                            break;
                        }
                    }

                } else {

                    switch(LockType) {

                        case SimpleMediaLock: {
                            FdoExtension->LockCount++;
                            break;
                        }

                        case SecureMediaLock: {
                            fsContext->LockCount++;
                            FdoExtension->ProtectedLockCount++;
                            break;
                        }

                        case InternalMediaLock: {
                            FdoExtension->InternalLockCount++;
                            break;
                        }
                    }
                }

            }

        } else {

            DebugPrint((2,
                        "ClasspEjectionControl: Succeeded\n"));

        }

        DebugPrint((2,
                    "ClasspEjectionControl: "
                    "Current Counts: Internal: %x  Secure: %x  Simple: %x\n",
                    FdoExtension->InternalLockCount,
                    FdoExtension->ProtectedLockCount,
                    FdoExtension->LockCount
                    ));

        KeSetEvent(&(FdoExtension->EjectSynchronizationEvent),
                   IO_NO_INCREMENT,
                   FALSE);
        KeLeaveCriticalRegion();
                   
        if (srb) {
            ClassFreeOrReuseSrb(FdoExtension, srb);
        }

    }
    return status;
}

#else

/*
 *  ISSUE:  RESTORE this (see above)
 *      This is a new implementation of the function that doesn't thrash memory
 *      or depend on the srbLookasideList.
 *      HOWEVER, it seems to cause pagefile initialization to fail during boot
 *      for some reason.  Need to resolve this before switching to this function.
 */
NTSTATUS  
ClasspEjectionControl(
    IN PDEVICE_OBJECT Fdo,
    IN PIRP Irp,
    IN MEDIA_LOCK_TYPE LockType,
    IN BOOLEAN Lock
    )
{
    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
    PFILE_OBJECT_EXTENSION fsContext;
    BOOLEAN fileHandleOk = TRUE;
    BOOLEAN countChanged = FALSE;
    NTSTATUS status;
    
    PAGED_CODE();
    
    status = KeWaitForSingleObject(
                &fdoExt->EjectSynchronizationEvent,
                UserRequest,
                KernelMode,
                FALSE,
                NULL);
    ASSERT(status == STATUS_SUCCESS);

    /*
     *  If this is a "secured" request, we have to make sure
     *  that the file handle is valid.
     */
    if (LockType == SecureMediaLock){
        PIO_STACK_LOCATION thisSp = IoGetCurrentIrpStackLocation(Irp);

        /*
         *  Make sure that the file object we are supplied has a
         *  proper FsContext before we try doing a secured lock.
         */
        if (thisSp->FileObject){
            PCOMMON_DEVICE_EXTENSION commonExt = (PCOMMON_DEVICE_EXTENSION)fdoExt;
            fsContext = ClasspGetFsContext(commonExt, thisSp->FileObject);
        }
        else {
            fsContext = NULL;
        }

        if (!fsContext){
            ASSERT(fsContext);
            fileHandleOk = FALSE;
        }
    }

    if (fileHandleOk){

        /*
         *  Adjust the lock counts and make sure they make sense.
         */
        status = STATUS_SUCCESS;
        if (Lock){
            switch(LockType) {
                case SimpleMediaLock:
                    fdoExt->LockCount++;
                    countChanged = TRUE;
                    break;
                case SecureMediaLock: 
                    fsContext->LockCount++;
                    fdoExt->ProtectedLockCount++;
                    countChanged = TRUE;
                    break;
                case InternalMediaLock:
                    fdoExt->InternalLockCount++;
                    countChanged = TRUE;
                    break;
            }
        } 
        else {
            /*
             *  This is an unlock command.  If it's a secured one then make sure
             *  the caller has a lock outstanding or return an error.
             */
            switch (LockType){
                case SimpleMediaLock: 
                    if (fdoExt->LockCount > 0){
                        fdoExt->LockCount--;
                        countChanged = TRUE;
                    }
                    else {
                        ASSERT(fdoExt->LockCount > 0);
                        status = STATUS_INTERNAL_ERROR;
                    }
                    break;
                case SecureMediaLock:
                    if (fsContext->LockCount > 0){
                        ASSERT(fdoExt->ProtectedLockCount > 0);
                        fsContext->LockCount--;
                        fdoExt->ProtectedLockCount--;
                        countChanged = TRUE;
                    }
                    else {
                        ASSERT(fsContext->LockCount > 0);
                        status = STATUS_INVALID_DEVICE_STATE;
                    }
                    break;
                case InternalMediaLock:
                    ASSERT(fdoExt->InternalLockCount > 0);
                    fdoExt->InternalLockCount--;
                    countChanged = TRUE;
                    break;
            }
        }

        if (NT_SUCCESS(status)){
            /*
             *  We only send an unlock command to the drive if
             *  all the lock counts have dropped to zero.
             */
            if (!Lock &&
               (fdoExt->ProtectedLockCount ||
                fdoExt->InternalLockCount ||
                fdoExt->LockCount)){
                
                /*
                 *  The lock count is still positive, so don't unlock yet.
                 */
                status = STATUS_SUCCESS;
            }
            else if (!TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
                /*
                 *  The device isn't removable media.  don't send a cmd.
                 */
                status  = STATUS_SUCCESS;
            }
            else {
                TRANSFER_PACKET *pkt;
                
                pkt = DequeueFreeTransferPacket(Fdo, TRUE);
                if (pkt){
                    KEVENT event;
                    
                    /*
                     *  Store the number of packets servicing the irp (one)
                     *  inside the original IRP.  It will be used to counted down 
                     *  to zero when the packet completes.
                     *  Initialize the original IRP's status to success.
                     *  If the packet fails, we will set it to the error status.
                     */
                    Irp->Tail.Overlay.DriverContext[0] = LongToPtr(1);
                    Irp->IoStatus.Status = STATUS_SUCCESS;

                    /*
                     *  Set this up as a SYNCHRONOUS transfer, submit it,
                     *  and wait for the packet to complete.  The result
                     *  status will be written to the original irp.
                     */
                    KeInitializeEvent(&event, SynchronizationEvent, FALSE);                
                    SetupEjectionTransferPacket(pkt, Lock, &event, Irp);
                    SubmitTransferPacket(pkt);
                    KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);        
                    status = Irp->IoStatus.Status;
                }
                else {
                    status = STATUS_INSUFFICIENT_RESOURCES;
                }
            }
        }
    }
    else {
        status = STATUS_INVALID_PARAMETER;
    }

    if (!NT_SUCCESS(status) && countChanged) {

        //
        // have to revert to previous counts if the
        // lock/unlock operation actually failed.
        //

        if(Lock) {

            switch(LockType) {

                case SimpleMediaLock: {
                    FdoExtension->LockCount--;
                    break;
                }

                case SecureMediaLock: {
                    fsContext->LockCount--;
                    FdoExtension->ProtectedLockCount--;
                    break;
                }

                case InternalMediaLock: {
                    FdoExtension->InternalLockCount--;
                    break;
                }
            }

        } else {

            switch(LockType) {

                case SimpleMediaLock: {
                    FdoExtension->LockCount++;
                    break;
                }

                case SecureMediaLock: {
                    fsContext->LockCount++;
                    FdoExtension->ProtectedLockCount++;
                    break;
                }

                case InternalMediaLock: {
                    FdoExtension->InternalLockCount++;
                    break;
                }
            }
        }
    }


    
    KeSetEvent(&fdoExt->EjectSynchronizationEvent, IO_NO_INCREMENT, FALSE);

    return status;
}
#endif

PFILE_OBJECT_EXTENSION
ClasspGetFsContext(
    IN PCOMMON_DEVICE_EXTENSION CommonExtension,
    IN PFILE_OBJECT FileObject
    )
{
    PAGED_CODE();
    return GetDictionaryEntry(&(CommonExtension->FileObjectDictionary),
                              (ULONGLONG) FileObject);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -