ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

create.c
Go to the documentation of this file.
00001 /*++
00002 
00003 Copyright (C) Microsoft Corporation, 1991 - 1999
00004 
00005 Module Name:
00006 
00007     class.c
00008 
00009 Abstract:
00010 
00011     SCSI class driver routines
00012 
00013 Environment:
00014 
00015     kernel mode only
00016 
00017 Notes:
00018 
00019 
00020 Revision History:
00021 
00022 --*/
00023 
00024 #define CLASS_INIT_GUID 0
00025 #include "classp.h"
00026 #include "debug.h"
00027 
00028 ULONG BreakOnClose = 0;
00029 
00030 PUCHAR LockTypeStrings[] = {
00031     "Simple",
00032     "Secure",
00033     "Internal"
00034 };
00035 
00036 
00037 PFILE_OBJECT_EXTENSION
00038 ClasspGetFsContext(
00039     IN PCOMMON_DEVICE_EXTENSION CommonExtension,
00040     IN PFILE_OBJECT FileObject
00041     );
00042 
00043 VOID
00044 ClasspCleanupDisableMcn(
00045     IN PFILE_OBJECT_EXTENSION FsContext
00046     );
00047 
00048 #ifdef ALLOC_PRAGMA
00049 #pragma alloc_text(PAGE, ClassCreateClose)
00050 #pragma alloc_text(PAGE, ClasspCreateClose)
00051 #pragma alloc_text(PAGE, ClasspCleanupProtectedLocks)
00052 #pragma alloc_text(PAGE, ClasspEjectionControl)
00053 #pragma alloc_text(PAGE, ClasspCleanupDisableMcn)
00054 #pragma alloc_text(PAGE, ClasspGetFsContext)
00055 #endif
00056 
00057 NTSTATUS
00058 ClassCreateClose(
00059     IN PDEVICE_OBJECT DeviceObject,
00060     IN PIRP Irp
00061     )
00062 
00063 /*++
00064 
00065 Routine Description:
00066 
00067     SCSI class driver create and close routine.  This is called by the I/O system
00068     when the device is opened or closed.
00069 
00070 Arguments:
00071 
00072     DriverObject - Pointer to driver object created by system.
00073 
00074     Irp - IRP involved.
00075 
00076 Return Value:
00077 
00078     Device-specific drivers return value or STATUS_SUCCESS.
00079 
00080 --*/
00081 
00082 {
00083     PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
00084     ULONG removeState;
00085     NTSTATUS status;
00086 
00087     PAGED_CODE();
00088 
00089     //
00090     // If we're getting a close request then we know the device object hasn't
00091     // been completely destroyed.  Let the driver cleanup if necessary.
00092     //
00093 
00094     removeState = ClassAcquireRemoveLock(DeviceObject, Irp);
00095 
00096     //
00097     // Invoke the device-specific routine, if one exists. Otherwise complete
00098     // with SUCCESS
00099     //
00100 
00101     if((removeState == NO_REMOVE) ||
00102        IS_CLEANUP_REQUEST(IoGetCurrentIrpStackLocation(Irp)->MajorFunction)) {
00103 
00104         status = ClasspCreateClose(DeviceObject, Irp);
00105 
00106         if((NT_SUCCESS(status)) &&
00107            (commonExtension->DevInfo->ClassCreateClose)) {
00108 
00109             return commonExtension->DevInfo->ClassCreateClose(DeviceObject, Irp);
00110         }
00111 
00112     } else {
00113         status = STATUS_DEVICE_DOES_NOT_EXIST;
00114     }
00115 
00116     Irp->IoStatus.Status = status;
00117     ClassReleaseRemoveLock(DeviceObject, Irp);
00118     ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
00119     return status;
00120 }
00121 
00122 
00123 NTSTATUS
00124 ClasspCreateClose(
00125     IN PDEVICE_OBJECT DeviceObject,
00126     IN PIRP Irp
00127     )
00128 /*++
00129 
00130 Routine Description:
00131 
00132     This routine will handle create/close operations for a given classpnp
00133     device if the class driver doesn't supply it's own handler.  If there
00134     is a file object supplied for our driver (if it's a FO_DIRECT_DEVICE_OPEN
00135     file object) then it will initialize a file extension on create or destroy
00136     the extension on a close.
00137 
00138 Arguments:
00139 
00140     DeviceObject - the device object being opened or closed.
00141 
00142     Irp - the create/close irp
00143 
00144 Return Value:
00145 
00146     status
00147 
00148 --*/
00149 {
00150     PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
00151     PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
00152 
00153     PFILE_OBJECT fileObject = irpStack->FileObject;
00154 
00155     NTSTATUS status = STATUS_SUCCESS;
00156 
00157     PAGED_CODE();
00158 
00159 
00160     //
00161     // ISSUE-2000/3/28-henrygab - if lower stack fails create/close, we end up
00162     // in an inconsistent state.  re-write to verify all args and allocate all
00163     // required resources, then pass the irp down, then complete the
00164     // transaction.  this is because we also cannot forward the irp, then fail
00165     // it after it has succeeded a lower-level driver.
00166     //
00167 
00168     if(irpStack->MajorFunction == IRP_MJ_CREATE) {
00169 
00170         PIO_SECURITY_CONTEXT securityContext =
00171             irpStack->Parameters.Create.SecurityContext;
00172         DebugPrint((2,
00173                     "ClasspCREATEClose: create received for device %p\n",
00174                     DeviceObject));
00175         DebugPrint((2,
00176                     "ClasspCREATEClose: desired access %lx\n",
00177                     securityContext->DesiredAccess));
00178         DebugPrint((2,
00179                     "ClasspCREATEClose: file object %lx\n",
00180                     irpStack->FileObject));
00181 
00182         ASSERT(BreakOnClose == FALSE);
00183 
00184         if(irpStack->FileObject != NULL) {
00185 
00186             PFILE_OBJECT_EXTENSION fsContext;
00187 
00188             //
00189             // Allocate our own file object extension for this device object.
00190             //
00191 
00192             status = AllocateDictionaryEntry(
00193                         &commonExtension->FileObjectDictionary,
00194                         (ULONGLONG) irpStack->FileObject,
00195                         sizeof(FILE_OBJECT_EXTENSION),
00196                         CLASS_TAG_FILE_OBJECT_EXTENSION,
00197                         &fsContext);
00198 
00199             if(NT_SUCCESS(status)) {
00200 
00201                 RtlZeroMemory(fsContext,
00202                               sizeof(FILE_OBJECT_EXTENSION));
00203 
00204                 fsContext->FileObject = irpStack->FileObject;
00205                 fsContext->DeviceObject = DeviceObject;
00206             } else if (status == STATUS_OBJECT_NAME_COLLISION) {
00207                 status = STATUS_SUCCESS;
00208             }
00209         }
00210 
00211     } else {
00212 
00213         DebugPrint((2,
00214                     "ClasspCreateCLOSE: close received for device %p\n",
00215                     DeviceObject));
00216         DebugPrint((2,
00217                     "ClasspCreateCLOSE: file object %p\n",
00218                     fileObject));
00219 
00220         if(irpStack->FileObject != NULL) {
00221 
00222             PFILE_OBJECT_EXTENSION fsContext =
00223                 ClasspGetFsContext(commonExtension, irpStack->FileObject);
00224 
00225             DebugPrint((2,
00226                         "ClasspCreateCLOSE: file extension %p\n",
00227                         fsContext));
00228 
00229             if(fsContext != NULL) {
00230 
00231                 DebugPrint((2,
00232                             "ClasspCreateCLOSE: extension is ours - "
00233                             "freeing\n"));
00234                 ASSERT(BreakOnClose == FALSE);
00235 
00236                 ClasspCleanupProtectedLocks(fsContext);
00237 
00238                 ClasspCleanupDisableMcn(fsContext);
00239 
00240                 FreeDictionaryEntry(&(commonExtension->FileObjectDictionary),
00241                                     fsContext);
00242             }
00243         }
00244     }
00245 
00246     //
00247     // Notify the lower levels about the create or close operation - give them
00248     // a chance to cleanup too.
00249     //
00250 
00251     DebugPrint((2,
00252                 "ClasspCreateClose: %s for devobj %p\n",
00253                 (NT_SUCCESS(status) ? "Success" : "FAILED"),
00254                 DeviceObject));
00255 
00256 
00257     if(NT_SUCCESS(status)) {
00258 
00259         KEVENT event;
00260 
00261         //
00262         // Set up the event to wait on
00263         //
00264 
00265         KeInitializeEvent(&event, SynchronizationEvent, FALSE);
00266 
00267         IoCopyCurrentIrpStackLocationToNext(Irp);
00268         IoSetCompletionRoutine( Irp, ClassSignalCompletion, &event,
00269                                 TRUE, TRUE, TRUE);
00270 
00271         status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
00272 
00273         if(status == STATUS_PENDING) {
00274             KeWaitForSingleObject(&event,
00275                                   Executive,
00276                                   KernelMode,
00277                                   FALSE,
00278                                   NULL);
00279             status = Irp->IoStatus.Status;
00280         }
00281 
00282         if (!NT_SUCCESS(status)) {
00283             DebugPrint((ClassDebugError,
00284                         "ClasspCreateClose: Lower driver failed, but we "
00285                         "succeeded.  This is a problem, lock counts will be "
00286                         "out of sync between levels.\n"));
00287         }
00288 
00289     }
00290 
00291 
00292     return status;
00293 }
00294 
00295 
00296 VOID
00297 ClasspCleanupProtectedLocks(
00298     IN PFILE_OBJECT_EXTENSION FsContext
00299     )
00300 {
00301     PCOMMON_DEVICE_EXTENSION commonExtension =
00302         FsContext->DeviceObject->DeviceExtension;
00303 
00304     PFUNCTIONAL_DEVICE_EXTENSION fdoExtension =
00305         commonExtension->PartitionZeroExtension;
00306 
00307     ULONG newDeviceLockCount = 1;
00308 
00309     PAGED_CODE();
00310 
00311     DebugPrint((2,
00312                 "ClasspCleanupProtectedLocks called for %p\n",
00313                 FsContext->DeviceObject));
00314     DebugPrint((2,
00315                 "ClasspCleanupProtectedLocks - FsContext %p is locked "
00316                 "%d times\n", FsContext, FsContext->LockCount));
00317 
00318     ASSERT(BreakOnClose == FALSE);
00319 
00320     //
00321     // Synchronize with ejection and ejection control requests.
00322     //
00323 
00324     KeEnterCriticalRegion();
00325     KeWaitForSingleObject(&(fdoExtension->EjectSynchronizationEvent),
00326                           UserRequest,
00327                           UserMode,
00328                           FALSE,
00329                           NULL);
00330 
00331     //
00332     // For each secure lock on this handle decrement the secured lock count
00333     // for the FDO.  Keep track of the new value.
00334     //
00335 
00336     if(FsContext->LockCount != 0) {
00337 
00338         do {
00339 
00340             InterlockedDecrement(&FsContext->LockCount);
00341 
00342             newDeviceLockCount =
00343                 InterlockedDecrement(&fdoExtension->ProtectedLockCount);
00344 
00345         } while(FsContext->LockCount != 0);
00346 
00347         //
00348         // If the new lock count has been dropped to zero then issue a lock
00349         // command to the device.
00350         //
00351 
00352         DebugPrint((2,
00353                     "ClasspCleanupProtectedLocks: FDO secured lock count = %d "
00354                     "lock count = %d\n",
00355                     fdoExtension->ProtectedLockCount,
00356                     fdoExtension->LockCount));
00357 
00358         if((newDeviceLockCount == 0) && (fdoExtension->LockCount == 0)) {
00359 
00360             SCSI_REQUEST_BLOCK srb;
00361             PCDB cdb;
00362             NTSTATUS status;
00363 
00364             DebugPrint((2,
00365                         "ClasspCleanupProtectedLocks: FDO lock count dropped "
00366                         "to zero\n"));
00367 
00368             RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
00369             cdb = (PCDB) &(srb.Cdb);
00370 
00371             srb.CdbLength = 6;
00372 
00373             cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
00374 
00375             //
00376             // TRUE - prevent media removal.
00377             // FALSE - allow media removal.
00378             //
00379 
00380             cdb->MEDIA_REMOVAL.Prevent = FALSE;
00381 
00382             //
00383             // Set timeout value.
00384             //
00385 
00386             srb.TimeOutValue = fdoExtension->TimeOutValue;
00387             status = ClassSendSrbSynchronous(fdoExtension->DeviceObject,
00388                                              &srb,
00389                                              NULL,
00390                                              0,
00391                                              FALSE);
00392 
00393             DebugPrint((2,
00394                         "ClasspCleanupProtectedLocks: unlock request to drive "
00395                         "returned status %lx\n", status));
00396         }
00397     }
00398 
00399     KeSetEvent(&fdoExtension->EjectSynchronizationEvent,
00400                IO_NO_INCREMENT,
00401                FALSE);
00402     KeLeaveCriticalRegion();
00403     return;
00404 }
00405 
00406 
00407 VOID
00408 ClasspCleanupDisableMcn(
00409     IN PFILE_OBJECT_EXTENSION FsContext
00410     )
00411 {
00412     PCOMMON_DEVICE_EXTENSION commonExtension =
00413         FsContext->DeviceObject->DeviceExtension;
00414 
00415     PFUNCTIONAL_DEVICE_EXTENSION fdoExtension =
00416         commonExtension->PartitionZeroExtension;
00417 
00418     ULONG newCount = 1;
00419 
00420     PAGED_CODE();
00421 
00422     DebugPrint((ClassDebugTrace,
00423                 "ClasspCleanupDisableMcn called for %p\n",
00424                 FsContext->DeviceObject));
00425     DebugPrint((ClassDebugTrace,
00426                 "ClasspCleanupDisableMcn - FsContext %p is disabled "
00427                 "%d times\n", FsContext, FsContext->McnDisableCount));
00428 
00429     //
00430     // For each secure lock on this handle decrement the secured lock count
00431     // for the FDO.  Keep track of the new value.
00432     //
00433 
00434     while(FsContext->McnDisableCount != 0) {
00435         FsContext->McnDisableCount--;
00436         ClassEnableMediaChangeDetection(fdoExtension);
00437     }
00438 
00439     return;
00440 }
00441 
00442 
00443 #if 1
00444 /*
00445  *  BUGBUG REMOVE this old function implementation as soon as the 
00446  *                  boottime pagefile problems with the new one (below) 
00447  *                  are resolved.
00448  */
00449 NTSTATUS
00450 ClasspEjectionControl(
00451     IN PDEVICE_OBJECT Fdo,
00452     IN PIRP Irp,
00453     IN MEDIA_LOCK_TYPE LockType,
00454     IN BOOLEAN Lock
00455     )
00456 {
00457     PFUNCTIONAL_DEVICE_EXTENSION FdoExtension = Fdo->DeviceExtension;
00458     PCOMMON_DEVICE_EXTENSION commonExtension =
00459         (PCOMMON_DEVICE_EXTENSION) FdoExtension;
00460     
00461     PFILE_OBJECT_EXTENSION fsContext = NULL;
00462     NTSTATUS status;
00463     PSCSI_REQUEST_BLOCK srb = NULL;
00464     BOOLEAN countChanged = FALSE;
00465 
00466     PAGED_CODE();
00467 
00468     //
00469     // Interlock with ejection and secure lock cleanup code.  This is a
00470     // user request so we can allow the stack to get swapped out while we
00471     // wait for synchronization.
00472     //
00473 
00474     status = KeWaitForSingleObject(
00475                 &(FdoExtension->EjectSynchronizationEvent),
00476                 UserRequest,
00477                 UserMode,
00478                 FALSE,
00479                 NULL);
00480 
00481     ASSERT(status == STATUS_SUCCESS);
00482 
00483     DebugPrint((2,
00484                 "ClasspEjectionControl: "
00485                 "Received request for %s lock type\n",
00486                 LockTypeStrings[LockType]
00487                 ));
00488 
00489     _SEH2_TRY {
00490         PCDB cdb;
00491 
00492         srb = ClasspAllocateSrb(FdoExtension);
00493 
00494         if(srb == NULL) {
00495             status = STATUS_INSUFFICIENT_RESOURCES;
00496             _SEH2_LEAVE;
00497         }
00498 
00499         RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
00500 
00501         cdb = (PCDB) srb->Cdb;
00502 
00503         //
00504         // Determine if this is a "secured" request.
00505         //
00506 
00507         if(LockType == SecureMediaLock) {
00508              
00509             PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
00510             PFILE_OBJECT fileObject = irpStack->FileObject;
00511 
00512             //
00513             // Make sure that the file object we are supplied has a
00514             // proper FsContext before we try doing a secured lock.
00515             //
00516 
00517             if(fileObject != NULL) {
00518                 fsContext = ClasspGetFsContext(commonExtension, fileObject);
00519             }
00520 
00521             if (fsContext == NULL) {
00522 
00523                 //
00524                 // This handle isn't setup correctly.  We can't let the
00525                 // operation go.
00526                 //
00527 
00528                 status = STATUS_INVALID_PARAMETER;
00529                 _SEH2_LEAVE;
00530             }
00531         }
00532 
00533         if(Lock) {
00534 
00535             //
00536             // This is a lock command.  Reissue the command in case bus or
00537             // device was reset and the lock was cleared.
00538             // note: may need to decrement count if actual lock operation
00539             //       failed....
00540             //
00541 
00542             switch(LockType) {
00543 
00544                 case SimpleMediaLock: {
00545                     FdoExtension->LockCount++;
00546                     countChanged = TRUE;
00547                     break;
00548                 }
00549 
00550                 case SecureMediaLock: {
00551                     fsContext->LockCount++;
00552                     FdoExtension->ProtectedLockCount++;
00553                     countChanged = TRUE;
00554                     break;
00555                 }
00556 
00557                 case InternalMediaLock: {
00558                     FdoExtension->InternalLockCount++;
00559                     countChanged = TRUE;
00560                     break;
00561                 }
00562             }
00563         
00564         } else {
00565 
00566             //
00567             // This is an unlock command.  If it's a secured one then make sure
00568             // the caller has a lock outstanding or return an error.
00569             // note: may need to re-increment the count if actual unlock
00570             //       operation fails....
00571             //
00572 
00573             switch(LockType) {
00574 
00575                 case SimpleMediaLock: {
00576                     if(FdoExtension->LockCount != 0) {
00577                         FdoExtension->LockCount--;
00578                         countChanged = TRUE;
00579                     }
00580                     break;
00581                 }
00582 
00583                 case SecureMediaLock: {
00584                     if(fsContext->LockCount == 0) {
00585                         status = STATUS_INVALID_DEVICE_STATE;
00586                         _SEH2_LEAVE;
00587                     }
00588                     fsContext->LockCount--;
00589                     FdoExtension->ProtectedLockCount--;
00590                     countChanged = TRUE;
00591                     break;
00592                 }
00593 
00594                 case InternalMediaLock: {
00595                     ASSERT(FdoExtension->InternalLockCount != 0);
00596                     FdoExtension->InternalLockCount--;
00597                     countChanged = TRUE;
00598                     break;
00599                 }
00600             }
00601 
00602             //
00603             // We only send an unlock command to the drive if both the
00604             // secured and unsecured lock counts have dropped to zero.
00605             //
00606 
00607             if((FdoExtension->ProtectedLockCount != 0) ||
00608                (FdoExtension->InternalLockCount != 0) ||
00609                (FdoExtension->LockCount != 0)) {
00610 
00611                 status = STATUS_SUCCESS;
00612                 _SEH2_LEAVE;
00613             }
00614         }
00615 
00616         status = STATUS_SUCCESS;
00617         if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
00618 
00619             srb->CdbLength = 6;
00620             cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
00621     
00622             //
00623             // TRUE - prevent media removal.
00624             // FALSE - allow media removal.
00625             //
00626     
00627             cdb->MEDIA_REMOVAL.Prevent = Lock;
00628     
00629             //
00630             // Set timeout value.
00631             //
00632     
00633             srb->TimeOutValue = FdoExtension->TimeOutValue;
00634     
00635             //
00636             // The actual lock operation on the device isn't so important
00637             // as the internal lock counts.  Ignore failures.
00638             //
00639     
00640             status = ClassSendSrbSynchronous(FdoExtension->DeviceObject,
00641                                              srb,
00642                                              NULL,
00643                                              0,
00644                                              FALSE);
00645         }
00646 
00647     } _SEH2_FINALLY {
00648 
00649         if (!NT_SUCCESS(status)) {
00650             DebugPrint((2,
00651                         "ClasspEjectionControl: FAILED status %x -- "
00652                         "reverting lock counts\n", status));
00653             
00654             if (countChanged) {
00655 
00656                 //
00657                 // have to revert to previous counts if the
00658                 // lock/unlock operation actually failed.
00659                 //
00660 
00661                 if(Lock) {
00662                     
00663                     switch(LockType) {
00664 
00665                         case SimpleMediaLock: {
00666                             FdoExtension->LockCount--;
00667                             break;
00668                         }
00669 
00670                         case SecureMediaLock: {
00671                             fsContext->LockCount--;
00672                             FdoExtension->ProtectedLockCount--;
00673                             break;
00674                         }
00675 
00676                         case InternalMediaLock: {
00677                             FdoExtension->InternalLockCount--;
00678                             break;
00679                         }
00680                     }
00681 
00682                 } else {
00683 
00684                     switch(LockType) {
00685 
00686                         case SimpleMediaLock: {
00687                             FdoExtension->LockCount++;
00688                             break;
00689                         }
00690 
00691                         case SecureMediaLock: {
00692                             fsContext->LockCount++;
00693                             FdoExtension->ProtectedLockCount++;
00694                             break;
00695                         }
00696 
00697                         case InternalMediaLock: {
00698                             FdoExtension->InternalLockCount++;
00699                             break;
00700                         }
00701                     }
00702                 }
00703 
00704             }
00705 
00706         } else {
00707 
00708             DebugPrint((2,
00709                         "ClasspEjectionControl: Succeeded\n"));
00710 
00711         }
00712 
00713         DebugPrint((2,
00714                     "ClasspEjectionControl: "
00715                     "Current Counts: Internal: %x  Secure: %x  Simple: %x\n",
00716                     FdoExtension->InternalLockCount,
00717                     FdoExtension->ProtectedLockCount,
00718                     FdoExtension->LockCount
00719                     ));
00720 
00721         KeSetEvent(&(FdoExtension->EjectSynchronizationEvent),
00722                    IO_NO_INCREMENT,
00723                    FALSE);
00724         if (srb) {
00725             ClassFreeOrReuseSrb(FdoExtension, srb);
00726         }
00727 
00728     } _SEH2_END;
00729     return status;
00730 }
00731 
00732 #else
00733 
00734 /*
00735  *  BUGBUG RESTORE
00736  *      This is a new implementation of the function that doesn't thrash memory
00737  *      or depend on the srbLookasideList.
00738  *      HOWEVER, it seems to cause pagefile initialization to fail during boot
00739  *      for some reason.  Need to resolve this before switching to this function.
00740  */
00741 NTSTATUS  
00742 ClasspEjectionControl(
00743     IN PDEVICE_OBJECT Fdo,
00744     IN PIRP Irp,
00745     IN MEDIA_LOCK_TYPE LockType,
00746     IN BOOLEAN Lock
00747     )
00748 {
00749     PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
00750     PFILE_OBJECT_EXTENSION fsContext;
00751     BOOLEAN fileHandleOk = TRUE;
00752     BOOLEAN countChanged = FALSE;
00753     NTSTATUS status;
00754     
00755     PAGED_CODE();
00756     
00757     status = KeWaitForSingleObject(
00758                 &fdoExt->EjectSynchronizationEvent,
00759                 UserRequest,
00760                 UserMode,
00761                 FALSE,
00762                 NULL);
00763     ASSERT(status == STATUS_SUCCESS);
00764 
00765     /*
00766      *  If this is a "secured" request, we have to make sure
00767      *  that the file handle is valid.
00768      */
00769     if (LockType == SecureMediaLock){
00770         PIO_STACK_LOCATION thisSp = IoGetCurrentIrpStackLocation(Irp);
00771 
00772         /*
00773          *  Make sure that the file object we are supplied has a
00774          *  proper FsContext before we try doing a secured lock.
00775          */
00776         if (thisSp->FileObject){
00777             PCOMMON_DEVICE_EXTENSION commonExt = (PCOMMON_DEVICE_EXTENSION)fdoExt;
00778             fsContext = ClasspGetFsContext(commonExt, thisSp->FileObject);
00779         }
00780         else {
00781             fsContext = NULL;
00782         }
00783 
00784         if (!fsContext){
00785             ASSERT(fsContext);
00786             fileHandleOk = FALSE;
00787         }
00788     }
00789 
00790     if (fileHandleOk){
00791 
00792         /*
00793          *  Adjust the lock counts and make sure they make sense.
00794          */
00795         status = STATUS_SUCCESS;
00796         if (Lock){
00797             switch(LockType) {
00798                 case SimpleMediaLock:
00799                     fdoExt->LockCount++;
00800                     countChanged = TRUE;
00801                     break;
00802                 case SecureMediaLock: 
00803                     fsContext->LockCount++;
00804                     fdoExt->ProtectedLockCount++;
00805                     countChanged = TRUE;
00806                     break;
00807                 case InternalMediaLock:
00808                     fdoExt->InternalLockCount++;
00809                     countChanged = TRUE;
00810                     break;
00811             }
00812         } 
00813         else {
00814             /*
00815              *  This is an unlock command.  If it's a secured one then make sure
00816              *  the caller has a lock outstanding or return an error.
00817              */
00818             switch (LockType){
00819                 case SimpleMediaLock: 
00820                     if (fdoExt->LockCount > 0){
00821                         fdoExt->LockCount--;
00822                         countChanged = TRUE;
00823                     }
00824                     else {
00825                         ASSERT(fdoExt->LockCount > 0);
00826                         status = STATUS_INTERNAL_ERROR;
00827                     }
00828                     break;
00829                 case SecureMediaLock:
00830                     if (fsContext->LockCount > 0){
00831                         ASSERT(fdoExt->ProtectedLockCount > 0);
00832                         fsContext->LockCount--;
00833                         fdoExt->ProtectedLockCount--;
00834                         countChanged = TRUE;
00835                     }
00836                     else {
00837                         ASSERT(fsContext->LockCount > 0);
00838                         status = STATUS_INVALID_DEVICE_STATE;
00839                     }
00840                     break;
00841                 case InternalMediaLock:
00842                     ASSERT(fdoExt->InternalLockCount > 0);
00843                     fdoExt->InternalLockCount--;
00844                     countChanged = TRUE;
00845                     break;
00846             }
00847         }
00848 
00849         if (NT_SUCCESS(status)){
00850             /*
00851              *  We only send an unlock command to the drive if
00852              *  all the lock counts have dropped to zero.
00853              */
00854             if (!Lock &&
00855                (fdoExt->ProtectedLockCount ||
00856                 fdoExt->InternalLockCount ||
00857                 fdoExt->LockCount)){
00858                 
00859                 /*
00860                  *  The lock count is still positive, so don't unlock yet.
00861                  */
00862                 status = STATUS_SUCCESS;
00863             }
00864             else if (!TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
00865                 /*
00866                  *  The device isn't removable media.  don't send a cmd.
00867                  */
00868                 status  = STATUS_SUCCESS;
00869             }
00870             else {
00871                 TRANSFER_PACKET *pkt;
00872                 
00873                 pkt = DequeueFreeTransferPacket(Fdo, TRUE);
00874                 if (pkt){
00875                     KEVENT event;
00876                     
00877                     /*
00878                      *  Store the number of packets servicing the irp (one)
00879                      *  inside the original IRP.  It will be used to counted down 
00880                      *  to zero when the packet completes.
00881                      *  Initialize the original IRP's status to success.
00882                      *  If the packet fails, we will set it to the error status.
00883                      */
00884                     Irp->Tail.Overlay.DriverContext[0] = LongToPtr(1);
00885                     Irp->IoStatus.Status = STATUS_SUCCESS;
00886 
00887                     /*
00888                      *  Set this up as a SYNCHRONOUS transfer, submit it,
00889                      *  and wait for the packet to complete.  The result
00890                      *  status will be written to the original irp.
00891                      */
00892                     KeInitializeEvent(&event, SynchronizationEvent, FALSE);                
00893                     SetupEjectionTransferPacket(pkt, Lock, &event, Irp);
00894                     SubmitTransferPacket(pkt);
00895                     KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);        
00896                     status = Irp->IoStatus.Status;
00897                 }
00898                 else {
00899                     status = STATUS_INSUFFICIENT_RESOURCES;
00900                 }
00901             }
00902         }
00903     }
00904     else {
00905         status = STATUS_INVALID_PARAMETER;
00906     }
00907 
00908     if (!NT_SUCCESS(status) && countChanged) {
00909 
00910         //
00911         // have to revert to previous counts if the
00912         // lock/unlock operation actually failed.
00913         //
00914 
00915         if(Lock) {
00916 
00917             switch(LockType) {
00918 
00919                 case SimpleMediaLock: {
00920                     FdoExtension->LockCount--;
00921                     break;
00922                 }
00923 
00924                 case SecureMediaLock: {
00925                     fsContext->LockCount--;
00926                     FdoExtension->ProtectedLockCount--;
00927                     break;
00928                 }
00929 
00930                 case InternalMediaLock: {
00931                     FdoExtension->InternalLockCount--;
00932                     break;
00933                 }
00934             }
00935 
00936         } else {
00937 
00938             switch(LockType) {
00939 
00940                 case SimpleMediaLock: {
00941                     FdoExtension->LockCount++;
00942                     break;
00943                 }
00944 
00945                 case SecureMediaLock: {
00946                     fsContext->LockCount++;
00947                     FdoExtension->ProtectedLockCount++;
00948                     break;
00949                 }
00950 
00951                 case InternalMediaLock: {
00952                     FdoExtension->InternalLockCount++;
00953                     break;
00954                 }
00955             }
00956         }
00957     }
00958 
00959 
00960     
00961     KeSetEvent(&fdoExt->EjectSynchronizationEvent, IO_NO_INCREMENT, FALSE);
00962 
00963     return status;
00964 }
00965 #endif
00966 
00967 PFILE_OBJECT_EXTENSION
00968 ClasspGetFsContext(
00969     IN PCOMMON_DEVICE_EXTENSION CommonExtension,
00970     IN PFILE_OBJECT FileObject
00971     )
00972 {
00973     PAGED_CODE();
00974     return GetDictionaryEntry(&(CommonExtension->FileObjectDictionary),
00975                               (ULONGLONG) FileObject);
00976 }
00977 

Generated on Sat May 26 2012 04:15:53 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.