📄 sfilter.c
字号:
For the latter case, this file system's device object is located,
detached, and deleted. This removes this file system as a filter for
the specified file system.
Arguments:
DeviceObject - Pointer to the file system's device object.
FsActive - Boolean indicating whether the file system has registered
(TRUE) or unregistered (FALSE) itself as an active file system.
Return Value:
None.
--*/
{
UNICODE_STRING Name;
WCHAR NameBuffer[MAX_DEVNAME_LENGTH];
PAGED_CODE();
//
// Init local Name buffer
//
RtlInitEmptyUnicodeString(&Name, NameBuffer, sizeof(NameBuffer));
SfGetObjectName(DeviceObject, &Name);
//
// Display the names of all the file system we are notified of
//
SF_LOG_PRINT(SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
("SFilter!SfFsNotification: %s %p \"%wZ\" (%s)\n",
(FsActive) ? "Activating file system " : "Deactivating file system",
DeviceObject,
&Name,
GET_DEVICE_TYPE_NAME(DeviceObject->DeviceType))
);
//
// Handle attaching/detaching from the given file system.
//
if (FsActive)
SfAttachToFileSystemDevice(DeviceObject, &Name);
else
SfDetachFromFileSystemDevice(DeviceObject);
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
//
// IRP Handling Routines
//
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
NTSTATUS
SfPassThrough(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is the main dispatch routine for the general purpose file
system driver. It simply passes requests onto the next driver in the
stack, which is presumably a disk file system.
Arguments:
DeviceObject - Pointer to the device object for this driver.
Irp - Pointer to the request packet representing the I/O request.
Return Value:
The function value is the status of the operation.
Note:
A note to file system filter implementers:
This routine actually "passes" through the request by taking this
driver out of the IRP stack. If the driver would like to pass the
I/O request through, but then also see the result, then rather than
taking itself out of the loop it could keep itself in by copying the
caller's parameters to the next stack location and then set its own
completion routine.
Hence, instead of calling:
IoSkipCurrentIrpStackLocation(Irp);
You could instead call:
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, NULL, NULL, FALSE, FALSE, FALSE);
This example actually NULLs out the caller's I/O completion routine, but
this driver could set its own completion routine so that it would be
notified when the request was completed (see SfCreate for an example of
this).
--*/
{
//
// Sfilter doesn't allow handles to its control device object to be created,
// therefore, no other operation should be able to come through.
//
ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject));
ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject));
//
// Get this driver out of the driver stack and get to the next driver as
// quickly as possible.
//
IoSkipCurrentIrpStackLocation(Irp);
//
// Call the appropriate file system driver with the request.
//
return IoCallDriver(((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp);
}
NTSTATUS
SfCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PSFILTER_DEVICE_EXTENSION DevExt = (PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IrpSp->FileObject;
PFILE_OBJECT RelatedFileObject = FileObject->RelatedFileObject;
PWSTR FileName = NULL;
PFILE_CONTEXT FileCtxPtr = NULL;
BOOLEAN DeleteOnClose = (BOOLEAN) (IrpSp->Parameters.Create.Options & FILE_DELETE_ON_CLOSE);
BOOLEAN IsEncryptFlagExist = FALSE;
BOOLEAN IsNeedEncrypt = FALSE;
NTSTATUS Status = STATUS_SUCCESS;
NTSTATUS LocalStatus = STATUS_SUCCESS;
PAGED_CODE();
//
// If this is for our control device object, don't allow it to be opened.
//
if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject))
{
//
// Sfilter doesn't allow for any communication through its control
// device object, therefore it fails all requests to open a handle
// to its control device object.
//
// See the FileSpy sample for an example of how to allow creates to
// the filter's control device object and manage communication via
// that handle.
//
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INVALID_DEVICE_REQUEST;
}
ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject));
//
// We only care about volume filter device object
//
if (!DevExt->StorageStackDeviceObject)
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
if (DevExt->DriveLetter == L'\0') {
UNICODE_STRING DosName;
Status = SfVolumeDeviceNameToDosName(&DevExt->DeviceName, &DosName);
if (NT_SUCCESS(Status)) {
DevExt->DriveLetter = DosName.Buffer[0];
ExFreePool(DosName.Buffer);
if ((DevExt->DriveLetter >= L'a') && (DevExt->DriveLetter <= L'z')) {
DevExt->DriveLetter += L'A' - L'a';
}
} else {
KdPrint(("sfilter!SfCreate: SfVolumeDeviceNameToDosName(%x) failed(%x)\n",
DevExt->StorageStackDeviceObject, Status));
}
}
//
// Open Volume Device directly
//
if ((FileObject->FileName.Length == 0) && !RelatedFileObject)
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
#if DBG
if (DevExt->DriveLetter != DEBUG_VOLUME)
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
#endif
do
{
//
// If the file is opened by id, then we can't get file name directly,
// But if this case happened, the FsContext must be in GenericTable already.
// So we just update the RefCount, that's enough
//
if (!(IrpSp->Parameters.Create.Options & FILE_OPEN_BY_FILE_ID))
{
FileName = ExAllocateFromPagedLookasideList(&gFileNameLookAsideList);
if (!FileName)
{
KdPrint(("sfilter!SfCreate: ExAllocatePoolWithTag failed\n"));
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
if (!SfDissectFileName(DeviceObject, Irp, FileName))
{
KdPrint(("sfilter!SfCreate: SfDissectFileName failed\n"));
Status = STATUS_INVALID_PARAMETER;
break;
}
if (wcslen(FileName) >= SF_ENCRYPT_POSTFIX_LENGTH)
{
if (_wcsnicmp(&FileName[wcslen(FileName) - SF_ENCRYPT_POSTFIX_LENGTH],
SF_ENCRYPT_POSTFIX, SF_ENCRYPT_POSTFIX_LENGTH) == 0)
{
//
// We deny all create request to our encrypt falg file except kernel mode
//
if (KernelMode == Irp->RequestorMode)
{
ExFreeToPagedLookasideList(&gFileNameLookAsideList, FileName);
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
else
{
Status = STATUS_SUCCESS;
break;
}
}
}
}
FileCtxPtr = ExAllocatePoolWithTag(PagedPool, sizeof(FILE_CONTEXT), SFLT_POOL_TAG);
if (FileCtxPtr == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
Status = SfForwardIrpSyncronously(DevExt->AttachedToDeviceObject, Irp);
if (NT_SUCCESS(Status) && (STATUS_REPARSE != Status) && SfIsObjectFile(FileObject))
{
PFILE_CONTEXT FileCtxPtr2 = NULL;
BOOLEAN NewElement = FALSE;
FileCtxPtr->FsContext = FileObject->FsContext;
ExAcquireFastMutex(&DevExt->FsCtxTableMutex);
FileCtxPtr2 = RtlLookupElementGenericTable(&DevExt->FsCtxTable, FileCtxPtr);
if (FileCtxPtr2)
++FileCtxPtr2->RefCount;
else
{
FileCtxPtr2 = RtlInsertElementGenericTable(
&DevExt->FsCtxTable,
FileCtxPtr,
sizeof(FILE_CONTEXT),
&NewElement
);
FileCtxPtr2->RefCount = 1;
ASSERT(FileName);
wcscpy(FileCtxPtr2->Name, FileName);
KeInitializeEvent(&FileCtxPtr2->Event, SynchronizationEvent, TRUE);
}
FileCtxPtr2->DeleteOnClose = DeleteOnClose;
ExReleaseFastMutex(&DevExt->FsCtxTableMutex);
IsEncryptFlagExist = FALSE;
IsNeedEncrypt = FALSE;
LocalStatus = STATUS_SUCCESS;
KdPrint(("sfilter!SfCreate: FileName = %ws\n", FileCtxPtr2->Name));
//
// we need handle file synchronously
//
KeWaitForSingleObject(&FileCtxPtr2->Event, Executive, KernelMode, FALSE, NULL);
LocalStatus = SfIsEncryptFlagExist(DeviceObject, FileCtxPtr2->Name, &IsEncryptFlagExist,
FileCtxPtr2->EncryptExtData, sizeof(FileCtxPtr2->EncryptExtData));
if (!NT_SUCCESS(LocalStatus))
KdPrint(("sfilter!SfPostCreateWorker: SfIsEncryptFlagExist failed, return %x\n", LocalStatus));
LocalStatus = SfIsFileNeedEncrypt(DeviceObject, FileCtxPtr2->Name, &IsNeedEncrypt);
if (!NT_SUCCESS(LocalStatus))
KdPrint(("sfilter!SfPostCreateWorker: SfIsFileNeedEncrypt failed, return %x\n", LocalStatus));
FileCtxPtr2->EncryptFlagExist = IsEncryptFlagExist;
FileCtxPtr2->NeedEncrypt = IsNeedEncrypt;
KdPrint(("sfilter!SfCreate: IsEncryptFlagExist = %d, IsNeedEncrypt = %d, NewElement = %d\n",
IsEncryptFlagExist, IsNeedEncrypt, NewElement));
if (NewElement && ((!IsNeedEncrypt && IsEncryptFlagExist) || (IsNeedEncrypt && !IsEncryptFlagExist)))
{
if (!IsNeedEncrypt && IsEncryptFlagExist)
{
if (NewElement)
FileCtxPtr2->DecryptOnRead = TRUE;
FileCtxPtr2->EncryptOnWrite = FALSE;
KdPrint(("sfilter!SfPostCreateWorker: Decrypt %ws\n", FileCtxPtr2->Name));
LocalStatus = SfUpdateFileByFileObject(DeviceObject, FileObject);
if (NT_SUCCESS(LocalStatus))
{
FileCtxPtr2->DecryptOnRead = FALSE;
FileCtxPtr2->EncryptOnWrite = FALSE;
LocalStatus = SfSetFileEncrypted(DeviceObject, FileCtxPtr2->Name, FALSE, NULL, 0);
if (NT_SUCCESS(LocalStatus))
FileCtxPtr2->EncryptFlagExist = FALSE;
else
KdPrint(("sfilter!SfPostCreateWorker: SfSetFileEncrypted(%ws, FALSE) failed, return %x\n", FileCtxPtr2->Name, LocalStatus));
}
else
{
KdPrint(("sfilter!SfPostCreateWorker: SfUpdateFileByFileObject failed, return %x\n", LocalStatus));
FileCtxPtr2->DecryptOnRead = TRUE;
FileCtxPtr2->EncryptOnWrite = TRUE;
}
}
else
{
if (NewElement)
FileCtxPtr2->DecryptOnRead = FALSE;
FileCtxPtr2->EncryptOnWrite = TRUE;
KdPrint(("sfilter!SfPostCreateWorker: Encrypt %ws\n", FileCtxPtr2->Name));
LocalStatus = SfUpdateFileByFileObject(DeviceObject, FileObject);
if (NT_SUCCESS(LocalStatus))
{
FileCtxPtr2->DecryptOnRead = TRUE;
FileCtxPtr2->EncryptOnWrite = TRUE;
LocalStatus = SfSetFileEncrypted(DeviceObject, FileCtxPtr2->Name, TRUE,
FileCtxPtr2->EncryptExtData, sizeof(FileCtxPtr2->EncryptExtData));
if (NT_SUCCESS(LocalStatus))
FileCtxPtr2->EncryptFlagExist = TRUE;
else
KdPrint(("sfilter!SfPostCreateWorker: SfSetFileEncrypted(%ws, TRUE) failed, return %x\n", FileCtxPtr2->Name, LocalStatus));
}
else
{
KdPrint(("sfilter!SfPostCreateWorker: SfUpdateFileByFileObject failed, return %x\n", LocalStatus));
FileCtxPtr2->DecryptOnRead = FALSE;
FileCtxPtr2->EncryptOnWrite = FALSE;
}
}
}
else
{
if (FileCtxPtr2->NeedEncrypt)
{
FileCtxPtr2->DecryptOnRead = TRUE;
FileCtxPtr2->EncryptOnWrite = TRUE;
if (!FileCtxPtr2->EncryptFlagExist)
{
LocalStatus = SfSetFileEncrypted(DeviceObject, FileCtxPtr2->Name, TRUE,
FileCtxPtr2->EncryptExtData, sizeof(FileCtxPtr2->EncryptExtData));
if (NT_SUCCESS(LocalStatus))
FileCtxPtr2->EncryptFlagExist = TRUE;
else
KdPrint(("sfilter!SfPostCreateWorker: SfSetFileEncrypted(%ws, TRUE) failed, return %x\n", FileCtxPtr2->Name, LocalStatus));
}
}
else
{
FileCtxPtr2->DecryptOnRead = FALSE;
FileCtxPtr2->EncryptOnWrite = FALSE;
if (FileCtxPtr2->EncryptFlagExist)
{
LocalStatus = SfSetFileEncrypted(DeviceObject, FileCtxPtr2->Name, FALSE,
NULL, 0);
if (NT_SUCCESS(LocalStatus))
FileCtxPtr2->EncryptFlagExist = FALSE;
else
KdPrint(("sfilter!SfPostCreateWorker: SfSetFileEncrypted(%ws, TRUE) failed, return %x\n", FileCtxPtr2->Name, LocalStatus));
}
}
}
KeSetEvent(&FileCtxPtr2->Event, IO_NO_INCREMENT, FALSE);
}
} while (FALSE);
if (FileName)
ExFreeToPagedLookasideList(&gFileNameLookAsideList, FileName);
if (FileCtxPtr)
ExFreePool(FileCtxPtr);
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
NTSTATUS
SfCleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PSFILTER_DEVICE_EXTENSION DevExt = (PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IrpSp->FileObject;
FILE_CONTEXT_HDR FileCtxHdr;
PFILE_CONTEXT FileCtxPtr = NULL;
BOOLEAN DeletePending = FileObject->DeletePending;
BOOLEAN DeleteOnClose = FALSE;
NTSTATUS Status;
PAGED_CODE();
//
// Sfilter doesn't allow handles to its control device object to be created,
// therefore, no other operation should be able to come through.
//
ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject));
ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject));
#if DBG
if (DevExt->DriveLetter != DEBUG_VOLUME)
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
#endif
//
// We only care about volume filter device object
//
if (!DevExt->StorageStackDeviceObject)
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
FileCtxHdr.FsContext = FileObject->FsContext;
ExAcq
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -