📄 create.c
字号:
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 + -