Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencreate.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
1.7.6.1
|