📄 fsctl.c
字号:
/*
* COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
* PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
* FILE: fsctl.c
* PURPOSE:
* PROGRAMMER: Mark Piper, Matt Wu, Bo Brant閚.
* HOMEPAGE:
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "rfsd.h"
/* GLOBALS ***************************************************************/
extern PRFSD_GLOBAL RfsdGlobal;
/* DEFINITIONS *************************************************************/
BOOLEAN
RfsdIsMediaWriteProtected (
IN PRFSD_IRP_CONTEXT IrpContext,
IN PDEVICE_OBJECT TargetDevice);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RfsdSetVpbFlag)
#pragma alloc_text(PAGE, RfsdClearVpbFlag)
#pragma alloc_text(PAGE, RfsdIsHandleCountZero)
#pragma alloc_text(PAGE, RfsdLockVcb)
#pragma alloc_text(PAGE, RfsdLockVolume)
#pragma alloc_text(PAGE, RfsdUnlockVcb)
#pragma alloc_text(PAGE, RfsdUnlockVolume)
#pragma alloc_text(PAGE, RfsdAllowExtendedDasdIo)
#pragma alloc_text(PAGE, RfsdUserFsRequest)
#pragma alloc_text(PAGE, RfsdIsMediaWriteProtected)
#pragma alloc_text(PAGE, RfsdMountVolume)
#pragma alloc_text(PAGE, RfsdCheckDismount)
#pragma alloc_text(PAGE, RfsdPurgeVolume)
#pragma alloc_text(PAGE, RfsdPurgeFile)
#pragma alloc_text(PAGE, RfsdDismountVolume)
#pragma alloc_text(PAGE, RfsdIsVolumeMounted)
#pragma alloc_text(PAGE, RfsdVerifyVolume)
#pragma alloc_text(PAGE, RfsdFileSystemControl)
#endif
VOID
RfsdSetVpbFlag (
IN PVPB Vpb,
IN USHORT Flag )
{
KIRQL OldIrql;
IoAcquireVpbSpinLock(&OldIrql);
Vpb->Flags |= Flag;
IoReleaseVpbSpinLock(OldIrql);
}
VOID
RfsdClearVpbFlag (
IN PVPB Vpb,
IN USHORT Flag )
{
KIRQL OldIrql;
IoAcquireVpbSpinLock(&OldIrql);
Vpb->Flags &= ~Flag;
IoReleaseVpbSpinLock(OldIrql);
}
BOOLEAN
RfsdIsHandleCountZero(IN PRFSD_VCB Vcb)
{
PRFSD_FCB Fcb;
PLIST_ENTRY List;
for( List = Vcb->FcbList.Flink;
List != &Vcb->FcbList;
List = List->Flink ) {
Fcb = CONTAINING_RECORD(List, RFSD_FCB, Next);
ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
(Fcb->Identifier.Size == sizeof(RFSD_FCB)));
RfsdPrint((DBG_INFO, "RfsdIsHandleCountZero: Key:%x,%xh File:%S OpenHandleCount=%xh\n",
Fcb->RfsdMcb->Key.k_dir_id, Fcb->RfsdMcb->Key.k_objectid, Fcb->RfsdMcb->ShortName.Buffer, Fcb->OpenHandleCount));
if (Fcb->OpenHandleCount) {
return FALSE;
}
}
return TRUE;
}
NTSTATUS
RfsdLockVcb (IN PRFSD_VCB Vcb,
IN PFILE_OBJECT FileObject)
{
NTSTATUS Status;
__try {
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
RfsdPrint((DBG_INFO, "RfsdLockVolume: Volume is already locked.\n"));
Status = STATUS_ACCESS_DENIED;
__leave;
}
if (Vcb->OpenFileHandleCount > (ULONG)(FileObject ? 1 : 0)) {
RfsdPrint((DBG_INFO, "RfsdLockVcb: There are still opened files.\n"));
Status = STATUS_ACCESS_DENIED;
__leave;
}
if (!RfsdIsHandleCountZero(Vcb)) {
RfsdPrint((DBG_INFO, "RfsdLockVcb: Thare are still opened files.\n"));
Status = STATUS_ACCESS_DENIED;
__leave;
}
SetFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
RfsdSetVpbFlag(Vcb->Vpb, VPB_LOCKED);
Vcb->LockFile = FileObject;
RfsdPrint((DBG_INFO, "RfsdLockVcb: Volume locked.\n"));
Status = STATUS_SUCCESS;
} __finally {
// Nothing
}
return Status;
}
NTSTATUS
RfsdLockVolume (IN PRFSD_IRP_CONTEXT IrpContext)
{
PIO_STACK_LOCATION IrpSp;
PDEVICE_OBJECT DeviceObject;
PRFSD_VCB Vcb;
NTSTATUS Status;
BOOLEAN VcbResourceAcquired = FALSE;
__try {
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
(IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
Status = STATUS_UNSUCCESSFUL;
//
// This request is not allowed on the main device object
//
if (DeviceObject == RfsdGlobal->DeviceObject) {
Status = STATUS_INVALID_PARAMETER;
__leave;
}
Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
(Vcb->Identifier.Size == sizeof(RFSD_VCB)));
ASSERT(IsMounted(Vcb));
IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);
#if (_WIN32_WINNT >= 0x0500)
CcWaitForCurrentLazyWriterActivity();
#endif
ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
TRUE );
VcbResourceAcquired = TRUE;
Status = RfsdLockVcb(Vcb, IrpSp->FileObject);
} __finally {
if (VcbResourceAcquired) {
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread()
);
}
if (!IrpContext->ExceptionInProgress) {
RfsdCompleteIrpContext(IrpContext, Status);
}
}
return Status;
}
NTSTATUS
RfsdUnlockVcb ( IN PRFSD_VCB Vcb,
IN PFILE_OBJECT FileObject )
{
NTSTATUS Status;
__try {
if (FileObject && FileObject->FsContext != Vcb) {
Status = STATUS_NOT_LOCKED;
__leave;
}
if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
RfsdPrint((DBG_ERROR, ": RfsdUnlockVcb: Volume is not locked.\n"));
Status = STATUS_NOT_LOCKED;
__leave;
}
if (Vcb->LockFile == FileObject) {
ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
RfsdClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
RfsdPrint((DBG_INFO, "RfsdUnlockVcb: Volume unlocked.\n"));
Status = STATUS_SUCCESS;
} else {
Status = STATUS_NOT_LOCKED;
}
} __finally {
// Nothing
}
return Status;
}
NTSTATUS
RfsdUnlockVolume (
IN PRFSD_IRP_CONTEXT IrpContext
)
{
PIO_STACK_LOCATION IrpSp;
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status;
PRFSD_VCB Vcb;
BOOLEAN VcbResourceAcquired = FALSE;
__try {
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
(IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
//
// This request is not allowed on the main device object
//
if (DeviceObject == RfsdGlobal->DeviceObject) {
Status = STATUS_INVALID_PARAMETER;
__leave;
}
Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
(Vcb->Identifier.Size == sizeof(RFSD_VCB)));
ASSERT(IsMounted(Vcb));
IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);
ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
TRUE );
VcbResourceAcquired = TRUE;
Status = RfsdUnlockVcb(Vcb, IrpSp->FileObject);
} __finally {
if (VcbResourceAcquired) {
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread()
);
}
if (!IrpContext->ExceptionInProgress) {
RfsdCompleteIrpContext(IrpContext, Status);
}
}
return Status;
}
NTSTATUS
RfsdInvalidateVolumes ( IN PRFSD_IRP_CONTEXT IrpContext )
{
NTSTATUS Status;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
HANDLE Handle;
PLIST_ENTRY ListEntry;
PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
BOOLEAN GlobalResourceAcquired = FALSE;
LUID Privilege = {SE_TCB_PRIVILEGE, 0};
__try {
Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
if (!SeSinglePrivilegeCheck(Privilege, Irp->RequestorMode)) {
Status = STATUS_PRIVILEGE_NOT_HELD;
__leave;
}
if (
#ifndef _GNU_NTIFS_
IrpSp->Parameters.FileSystemControl.InputBufferLength
#else
((PEXTENDED_IO_STACK_LOCATION)(IrpSp))->
Parameters.FileSystemControl.InputBufferLength
#endif
!= sizeof(HANDLE)) {
Status = STATUS_INVALID_PARAMETER;
__leave;
}
Handle = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;
Status = ObReferenceObjectByHandle( Handle,
0,
*IoFileObjectType,
KernelMode,
&FileObject,
NULL );
if (!NT_SUCCESS(Status)) {
__leave;
} else {
ObDereferenceObject(FileObject);
DeviceObject = FileObject->DeviceObject;
}
RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: FileObject=%xh ...\n", FileObject));
ExAcquireResourceExclusiveLite(
&RfsdGlobal->Resource,
TRUE );
GlobalResourceAcquired = TRUE;
ListEntry = RfsdGlobal->VcbList.Flink;
while (ListEntry != &RfsdGlobal->VcbList) {
PRFSD_VCB Vcb;
Vcb = CONTAINING_RECORD(ListEntry, RFSD_VCB, Next);
ListEntry = ListEntry->Flink;
RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: Vcb=%xh Vcb->Vpb=%xh...\n", Vcb, Vcb->Vpb));
if (Vcb->Vpb && (Vcb->Vpb->RealDevice == DeviceObject))
{
ExAcquireResourceExclusive(&Vcb->MainResource, TRUE);
RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: RfsdPurgeVolume...\n"));
RfsdPurgeVolume(Vcb, FALSE);
ClearFlag(Vcb->Flags, VCB_MOUNTED);
ExReleaseResource(&Vcb->MainResource);
//
// Vcb is still attached on the list ......
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -