Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023/*++
Copyright (C) Microsoft Corporation, 1991 - 2010
Module Name:
class.c
Abstract:
SCSI class driver routines
Environment:
kernel mode only
Notes:
Revision History:
--*/
#define CLASS_INIT_GUID 0#include "classp.h"#include "debug.h"
#ifdef DEBUG_USE_WPP#include "create.tmh"#endif
ULONG BreakOnClose = 0;
const PCSZ LockTypeStrings[] = { "Simple", "Secure", "Internal"};
VOIDClasspCleanupDisableMcn( IN PFILE_OBJECT_EXTENSION FsContext );
#ifdef ALLOC_PRAGMA#pragma alloc_text(PAGE, ClassCreateClose)#pragma alloc_text(PAGE, ClasspCreateClose)#pragma alloc_text(PAGE, ClasspCleanupProtectedLocks)#pragma alloc_text(PAGE, ClasspEjectionControl)#pragma alloc_text(PAGE, ClasspCleanupDisableMcn)#pragma alloc_text(PAGE, ClassGetFsContext)#endif
NTSTATUSNTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ClassCreateClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
/*++
Routine Description:
SCSI class driver create and close routine. This is called by the I/O system when the device is opened or closed.
Arguments:
DriverObject - Pointer to driver object created by system.
Irp - IRP involved.
Return Value:
Device-specific drivers return value or STATUS_SUCCESS.
--*/
{ PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; ULONG removeState; NTSTATUS status;
PAGED_CODE();
// // If we're getting a close request then we know the device object hasn't // been completely destroyed. Let the driver cleanup if necessary. //
removeState = ClassAcquireRemoveLock(DeviceObject, Irp);
// // Invoke the device-specific routine, if one exists. Otherwise complete // with SUCCESS //
if((removeState == NO_REMOVE) || IS_CLEANUP_REQUEST(IoGetCurrentIrpStackLocation(Irp)->MajorFunction)) {
status = ClasspCreateClose(DeviceObject, Irp);
if((NT_SUCCESS(status)) && (commonExtension->DevInfo->ClassCreateClose)) {
return commonExtension->DevInfo->ClassCreateClose(DeviceObject, Irp); }
} else { status = STATUS_DEVICE_DOES_NOT_EXIST; }
Irp->IoStatus.Status = status; ClassReleaseRemoveLock(DeviceObject, Irp); ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT); return status;}
NTSTATUSClasspCreateClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )/*++
Routine Description:
This routine will handle create/close operations for a given classpnp device if the class driver doesn't supply it's own handler. If there is a file object supplied for our driver (if it's a FO_DIRECT_DEVICE_OPEN file object) then it will initialize a file extension on create or destroy the extension on a close.
Arguments:
DeviceObject - the device object being opened or closed.
Irp - the create/close irp
Return Value:
status
--*/{ PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT fileObject = irpStack->FileObject;
NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE();
// // ISSUE-2000/3/28-henrygab - if lower stack fails create/close, we end up // in an inconsistent state. re-write to verify all args and allocate all // required resources, then pass the irp down, then complete the // transaction. this is because we also cannot forward the irp, then fail // it after it has succeeded a lower-level driver. //
if(irpStack->MajorFunction == IRP_MJ_CREATE) {
PIO_SECURITY_CONTEXT securityContext = irpStack->Parameters.Create.SecurityContext; TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCREATEClose: create received for device %p\n", DeviceObject)); TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCREATEClose: desired access %lx\n", securityContext->DesiredAccess)); TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCREATEClose: file object %p\n", irpStack->FileObject));
NT_ASSERT(BreakOnClose == FALSE);
if(irpStack->FileObject != NULL) {
PFILE_OBJECT_EXTENSION fsContext;
// // Allocate our own file object extension for this device object. //
status = AllocateDictionaryEntry( &commonExtension->FileObjectDictionary, (ULONGLONG) irpStack->FileObject, sizeof(FILE_OBJECT_EXTENSION), CLASS_TAG_FILE_OBJECT_EXTENSION, (PVOID *)&fsContext);
if(NT_SUCCESS(status)) {
RtlZeroMemory(fsContext, sizeof(FILE_OBJECT_EXTENSION));
fsContext->FileObject = irpStack->FileObject; fsContext->DeviceObject = DeviceObject; } else if (status == STATUS_OBJECT_NAME_COLLISION) { status = STATUS_SUCCESS; } }
} else {
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCreateCLOSE: close received for device %p\n", DeviceObject)); TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCreateCLOSE: file object %p\n", fileObject));
if(irpStack->FileObject != NULL) {
PFILE_OBJECT_EXTENSION fsContext = ClassGetFsContext(commonExtension, irpStack->FileObject);
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCreateCLOSE: file extension %p\n", fsContext));
if(fsContext != NULL) {
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCreateCLOSE: extension is ours - " "freeing\n")); NT_ASSERT(BreakOnClose == FALSE);
ClasspCleanupProtectedLocks(fsContext);
ClasspCleanupDisableMcn(fsContext);
FreeDictionaryEntry(&(commonExtension->FileObjectDictionary), fsContext); } } }
// // Notify the lower levels about the create or close operation - give them // a chance to cleanup too. //
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCreateClose: %s for devobj %p\n", (NT_SUCCESS(status) ? "Success" : "FAILED"), DeviceObject));
if(NT_SUCCESS(status)) {
KEVENT event;
// // Set up the event to wait on //
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, ClassSignalCompletion, &event, TRUE, TRUE, TRUE);
status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
if(status == STATUS_PENDING) { (VOID)KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); status = Irp->IoStatus.Status; }
if (!NT_SUCCESS(status)) { TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClasspCreateClose: Lower driver failed, but we " "succeeded. This is a problem, lock counts will be " "out of sync between levels.\n")); }
}
return status;}
VOIDClasspCleanupProtectedLocks( IN PFILE_OBJECT_EXTENSION FsContext ){ PCOMMON_DEVICE_EXTENSION commonExtension = FsContext->DeviceObject->DeviceExtension;
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = commonExtension->PartitionZeroExtension;
ULONG newDeviceLockCount = 1;
PAGED_CODE();
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCleanupProtectedLocks called for %p\n", FsContext->DeviceObject)); TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCleanupProtectedLocks - FsContext %p is locked " "%d times\n", FsContext, FsContext->LockCount));
NT_ASSERT(BreakOnClose == FALSE);
// // Synchronize with ejection and ejection control requests. //
KeEnterCriticalRegion(); (VOID)KeWaitForSingleObject(&(fdoExtension->EjectSynchronizationEvent), UserRequest, KernelMode, FALSE, NULL);
// // For each secure lock on this handle decrement the secured lock count // for the FDO. Keep track of the new value. //
if (FsContext->LockCount != 0) {
do {
InterlockedDecrement((volatile LONG *)&FsContext->LockCount);
newDeviceLockCount = InterlockedDecrement(&fdoExtension->ProtectedLockCount);
} while (FsContext->LockCount > 0);
// // If the new lock count has been dropped to zero then issue a lock // command to the device. //
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCleanupProtectedLocks: FDO secured lock count = %d " "lock count = %d\n", fdoExtension->ProtectedLockCount, fdoExtension->LockCount));
if ((newDeviceLockCount == 0) && (fdoExtension->LockCount == 0)) {
SCSI_REQUEST_BLOCK srb = {0}; UCHAR srbExBuffer[CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE] = {0}; PSTORAGE_REQUEST_BLOCK srbEx = (PSTORAGE_REQUEST_BLOCK)srbExBuffer; PCDB cdb = NULL; NTSTATUS status; PSCSI_REQUEST_BLOCK srbPtr;
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCleanupProtectedLocks: FDO lock count dropped " "to zero\n"));
if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {#ifdef _MSC_VER #pragma prefast(suppress:26015, "InitializeStorageRequestBlock ensures buffer access is bounded")#endif status = InitializeStorageRequestBlock(srbEx, STORAGE_ADDRESS_TYPE_BTL8, sizeof(srbExBuffer), 1, SrbExDataTypeScsiCdb16); if (NT_SUCCESS(status)) { srbEx->TimeOutValue = fdoExtension->TimeOutValue; SrbSetCdbLength(srbEx, 6); cdb = SrbGetCdb(srbEx); srbPtr = (PSCSI_REQUEST_BLOCK)srbEx; } else { // // Should not happen. Revert to legacy SRB. // NT_ASSERT(FALSE); srb.TimeOutValue = fdoExtension->TimeOutValue; srb.CdbLength = 6; cdb = (PCDB) &(srb.Cdb); srbPtr = &srb; }
} else {
srb.TimeOutValue = fdoExtension->TimeOutValue; srb.CdbLength = 6; cdb = (PCDB) &(srb.Cdb); srbPtr = &srb;
}
cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
// // TRUE - prevent media removal. // FALSE - allow media removal. //
cdb->MEDIA_REMOVAL.Prevent = FALSE;
status = ClassSendSrbSynchronous(fdoExtension->DeviceObject, srbPtr, NULL, 0, FALSE);
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCleanupProtectedLocks: unlock request to drive " "returned status %lx\n", status)); } }
KeSetEvent(&fdoExtension->EjectSynchronizationEvent, IO_NO_INCREMENT, FALSE); KeLeaveCriticalRegion(); return;}
VOIDClasspCleanupDisableMcn( IN PFILE_OBJECT_EXTENSION FsContext ){ PCOMMON_DEVICE_EXTENSION commonExtension = FsContext->DeviceObject->DeviceExtension;
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = commonExtension->PartitionZeroExtension;
PAGED_CODE();
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspCleanupDisableMcn called for %p\n", FsContext->DeviceObject)); TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspCleanupDisableMcn - FsContext %p is disabled " "%d times\n", FsContext, FsContext->McnDisableCount));
// // For each secure lock on this handle decrement the secured lock count // for the FDO. Keep track of the new value. //
while(FsContext->McnDisableCount != 0) { FsContext->McnDisableCount--; ClassEnableMediaChangeDetection(fdoExtension); }
return;}
#if 1/* * ISSUE: REMOVE this old function implementation as soon as the * boottime pagefile problems with the new one (below) * are resolved. */NTSTATUSClasspEjectionControl( IN PDEVICE_OBJECT Fdo, IN PIRP Irp, IN MEDIA_LOCK_TYPE LockType, IN BOOLEAN Lock ){ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension = Fdo->DeviceExtension; PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION) FdoExtension;
PFILE_OBJECT_EXTENSION fsContext = NULL; NTSTATUS status; PSCSI_REQUEST_BLOCK srb = NULL; BOOLEAN countChanged = FALSE;
PAGED_CODE();
/* * Ensure that the user thread is not suspended while we are holding EjectSynchronizationEvent. */ KeEnterCriticalRegion();
status = KeWaitForSingleObject( &(FdoExtension->EjectSynchronizationEvent), UserRequest, KernelMode, FALSE, NULL);
NT_ASSERT(status == STATUS_SUCCESS);
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "ClasspEjectionControl: " "Received request for %s lock type\n", LockTypeStrings[LockType] ));
_SEH2_TRY { PCDB cdb = NULL;
// // 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 = ClassGetFsContext(commonExtension, fileObject); }
if (fsContext == NULL) {
// // This handle isn't setup correctly. We can't let the // operation go. //
status = STATUS_INVALID_PARAMETER; _SEH2_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; _SEH2_LEAVE; } fsContext->LockCount--; FdoExtension->ProtectedLockCount--; countChanged = TRUE; break; }
case InternalMediaLock: { NT_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; _SEH2_LEAVE; } }
status = STATUS_SUCCESS; if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
srb = (PSCSI_REQUEST_BLOCK)ClasspAllocateSrb(FdoExtension);
if (srb == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; }
if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
// // NOTE - this is based on size used in ClasspAllocateSrb //
status = InitializeStorageRequestBlock((PSTORAGE_REQUEST_BLOCK)srb, STORAGE_ADDRESS_TYPE_BTL8, CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE, 1, SrbExDataTypeScsiCdb16); if (!NT_SUCCESS(status)) { NT_ASSERT(FALSE); _SEH2_LEAVE; }
} else { RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); }
SrbSetCdbLength(srb, 6); cdb = SrbGetCdb(srb); NT_ASSERT(cdb != NULL);
cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
// // TRUE - prevent media removal. // FALSE - allow media removal. //
cdb->MEDIA_REMOVAL.Prevent = Lock;
// // Set timeout value. //
SrbSetTimeOutValue(srb, 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); }
} _SEH2_FINALLY {
if (!NT_SUCCESS(status)) { TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "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 {
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "ClasspEjectionControl: Succeeded\n"));
}
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "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); }
} _SEH2_END; 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. */NTSTATUSClasspEjectionControl( 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); NT_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 = ClassGetFsContext(commonExt, thisSp->FileObject); } else { fsContext = NULL; }
if (!fsContext){ NT_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 { NT_ASSERT(fdoExt->LockCount > 0); status = STATUS_INTERNAL_ERROR; } break; case SecureMediaLock: if (fsContext->LockCount > 0){ NT_ASSERT(fdoExt->ProtectedLockCount > 0); fsContext->LockCount--; fdoExt->ProtectedLockCount--; countChanged = TRUE; } else { NT_ASSERT(fsContext->LockCount > 0); status = STATUS_INVALID_DEVICE_STATE; } break; case InternalMediaLock: NT_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); (VOID)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
_IRQL_requires_max_(PASSIVE_LEVEL)PFILE_OBJECT_EXTENSIONNTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ClassGetFsContext( _In_ PCOMMON_DEVICE_EXTENSION CommonExtension, _In_ PFILE_OBJECT FileObject ){ PAGED_CODE(); return GetDictionaryEntry(&(CommonExtension->FileObjectDictionary), (ULONGLONG) FileObject);}