阅读:1856回复:8
请问下能否在IRP_MJ_CREATE的例程中写文件的加密标识?
我的计划是当文件新建的时候就在文件头加上个加密标识,参考了前人的一些文章,使用的函数是IoBuildAsynchronousFsdRequest(.....)。目前在IRP_MJ_CREATE的例程用IoBuildAsynchronousFsdRequest()函数读已有文件中的标识是可以的,但是在文件新建的时候写标识就失败了,我想知道是自己函数处理的问题还是不能用IoBuildAsynchronousFsdRequest(.....)在IRP_MJ_CREATE的例程写标识,先谢谢热心解答的大侠。
|
|
沙发#
发布于:2009-02-25 12:19
自己re一个.......菜鸟的路真崎岖,也许这个问题太幼稚了,高手都没兴趣回答啊。
|
|
板凳#
发布于:2009-02-26 00:12
Sorry, read your post several times, still don't get what you really want. I'd suggest you describe your CREATE routine in more details, pseudocode will be perfect, and what error your got when 写标识 failed.
By the way, for a new file, before the IRP passed down to lower file system, that file is not exist. How can you write anything into a non-existing file? |
|
地板#
发布于:2009-02-26 17:04
谢谢大侠的谢心回复。我写加密标识是在文件新建完成后写的,用的函数是自定义的SfWriteEncryptFlag。
这样贴代码有些凌乱,希望大侠不见怪。由于小弟对这个理解不深,可能会有一些常识性的错误。 NTSTATUS SfCreate ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This function filters create/open operations. It simply establishes an I/O completion routine to be invoked if the operation was successful. Arguments: DeviceObject - Pointer to the target device object of the create/open. Irp - Pointer to the I/O Request Packet that represents the operation. Return Value: The function value is the status of the call to the file system's entry point. --*/ { NTSTATUS status; // //添加部分 // PSFILTER_DEVICE_EXTENSION DevExt = (PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PFILE_OBJECT FileObject = IrpSp->FileObject; PWSTR FileName = NULL; ULONG FileNameLength = 0; NTSTATUS Status = STATUS_SUCCESS; POST_CREATE_WORKER_CONTEXT WorkerCtx; // UNICODE_STRING UNIFileName; // ANSI_STRING ANSIFileName; // WCHAR UNIBuf[MAX_PATH]; // CHAR ANSIBuf[MAX_PATH]; 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 )); // // If debugging is enabled, do the processing required to see the packet // upon its completion. Otherwise, let the request go with no further // processing. // // // We only care about volume filter device object // 我们仅关心卷过滤设备对象 // if (!DevExt->StorageStackDeviceObject) { IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(DevExt->AttachedToDeviceObject, Irp); } #if DBG if (DevExt->DriveLetter != DEBUG_VOLUME) { IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(DevExt->AttachedToDeviceObject, Irp); } #endif do { KEVENT waitEvent; // // Initialize an event to wait for the completion routine to occur // KeInitializeEvent( &waitEvent, NotificationEvent, FALSE ); // // Copy the stack and set our Completion routine // IoCopyCurrentIrpStackLocationToNext( Irp ); IoSetCompletionRoutine( Irp, SfCreateCompletion, &waitEvent, TRUE, TRUE, TRUE ); // // Call the next driver in the stack. // status = IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp ); // // Wait for the completion routine to be called // if (STATUS_PENDING == status) { NTSTATUS localStatus = KeWaitForSingleObject(&waitEvent, Executive, KernelMode, FALSE, NULL); ASSERT(STATUS_SUCCESS == localStatus); } // // Verify the IoCompleteRequest was called // ASSERT(KeReadStateEvent(&waitEvent) || !NT_SUCCESS(Irp->IoStatus.Status)); 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; } SfGetFileNameFromFileObject(DevExt, FileObject, &FileNameLength, FileName); if (0 == _wcsnicmp(&FileName[3], SF_ENCRYPT_INFO_DIR, SF_ENCRYPT_INFOR_DIR_LENGTH)) { // // We deny all create request to our encrypt info dir except kernel mode // if (KernelMode == Irp->RequestorMode) { ExFreeToPagedLookasideList(&gFileNameLookAsideList, FileName); status = Irp->IoStatus.Status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } else { Status = STATUS_NO_SUCH_FILE; break; } } else { if (IrpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE) { // // We don't care about directories // ExFreeToPagedLookasideList(&gFileNameLookAsideList, FileName); status = Irp->IoStatus.Status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } } } else { if (IrpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE) { // // We don't care about directories // status = Irp->IoStatus.Status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } } //Status = SfForwardIrpSyncronously(DevExt->AttachedToDeviceObject, Irp); //if (NT_SUCCESS(Status) && (STATUS_REPARSE != Status)) { if((Irp->IoStatus.Information == FILE_CREATED) || (Irp->IoStatus.Information == FILE_OPENED)) { FILE_CONTEXT FileCtx; PFILE_CONTEXT FileCtxPtr = NULL; BOOLEAN NewElement = FALSE; FileCtx.FsContext = FileObject->FsContext; ExAcquireFastMutex(&DevExt->FsCtxTableMutex); FileCtxPtr = RtlLookupElementGenericTable(&DevExt->FsCtxTable, &FileCtx); if (FileCtxPtr) ++FileCtxPtr->RefCount; else { FileCtxPtr = RtlInsertElementGenericTable( &DevExt->FsCtxTable, &FileCtx, sizeof(FILE_CONTEXT), &NewElement ); FileCtxPtr->RefCount = 1; ASSERT(FileName); wcscpy(FileCtxPtr->Name, FileName); KeInitializeEvent(&FileCtxPtr->Event, SynchronizationEvent, TRUE); } ExReleaseFastMutex(&DevExt->FsCtxTableMutex); if(!_wcsnicmp(FileName,L"D:\\Test\\",8)) { if ((NodeType(FileObject->FsContext) == FAT_NTC_DCB) || (NodeType(FileObject->FsContext) == FAT_NTC_ROOT_DCB) || (NodeType(FileObject->FsContext) == NTFS_NTC_DCB) || (NodeType(FileObject->FsContext) == NTFS_NTC_ROOT_DCB)) { if (FileName) ExFreeToPagedLookasideList(&gFileNameLookAsideList, FileName); status = Irp->IoStatus.Status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } ExInitializeWorkItem(&WorkerCtx.WorkItem, SfWriteEncryptFlag, &WorkerCtx); WorkerCtx.DeviceObject = DeviceObject; WorkerCtx.FileObject = FileObject; KeInitializeEvent(&WorkerCtx.Event, NotificationEvent, FALSE); WorkerCtx.FileContext = FileCtxPtr; if( Irp->IoStatus.Information == FILE_CREATED ) { if (KeGetCurrentIrql() == PASSIVE_LEVEL) SfWriteEncryptFlag(&WorkerCtx); else { ExQueueWorkItem(&WorkerCtx.WorkItem, DelayedWorkQueue); KeWaitForSingleObject(&WorkerCtx.Event, Executive, KernelMode, FALSE, NULL); } } } } } }while(FALSE); // // Save the status and continue processing the IRP // if (FileName) ExFreeToPagedLookasideList(&gFileNameLookAsideList, FileName); status = Irp->IoStatus.Status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } static NTSTATUS MyIrpComplete( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context ) { UNREFERENCED_PARAMETER( DeviceObject ); UNREFERENCED_PARAMETER( Context ); // *Irp->UserIosb = Irp->IoStatus; // Copy status information to // the user if (Irp->MdlAddress) { MmUnmapLockedPages( MmGetSystemAddressForMdl(Irp->MdlAddress), Irp->MdlAddress); MmUnlockPages(Irp->MdlAddress); IoFreeMdl(Irp->MdlAddress); Irp->MdlAddress = NULL; } KeSetEvent(Irp->UserEvent, 0, FALSE); // Signal event IoFreeIrp(Irp); // Free IRP return STATUS_MORE_PROCESSING_REQUIRED; // Tell the I/O manager to stop } NTSTATUS SfIssueReadWriteIrpSynchronously( IN PDEVICE_OBJECT DeviceObject, IN PFILE_OBJECT FileObject, IN ULONG MajorFunction, IN PIO_STATUS_BLOCK IoStatus, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER ByteOffset, IN ULONG IrpFlags ) { PIRP Irp = NULL; PIO_STACK_LOCATION IrpSp = NULL; KEVENT Event; NTSTATUS Status; //FILE_STANDARD_INFORMATION StandardInformation; UNREFERENCED_PARAMETER( IrpFlags ); ASSERT((MajorFunction == IRP_MJ_READ) || (MajorFunction == IRP_MJ_WRITE)); KeInitializeEvent(&Event, NotificationEvent, FALSE); Irp = IoBuildAsynchronousFsdRequest( MajorFunction, DeviceObject, Buffer, Length, ByteOffset, IoStatus ); if (!Irp) return STATUS_INSUFFICIENT_RESOURCES; Irp = IoAllocateIrp( DeviceObject->StackSize, FALSE ); if (Irp == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } Irp->Flags = 0x43; Irp->UserEvent = &Event; IrpSp = IoGetNextIrpStackLocation(Irp); IrpSp->FileObject = FileObject; Irp->IoStatus.Information = 0; IoSetCompletionRoutine(Irp, &MyIrpComplete, 0, TRUE, TRUE, TRUE); Status = IoCallDriver(DeviceObject, Irp); if (STATUS_PENDING == Status) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); } //IoCompleteRequest( Irp, IO_NO_INCREMENT ); KdPrint(("SfIssueReadWriteIrpSynchronously! MajorFunction = %x, Buffer = %s, Length = %d\n",MajorFunction, Buffer, Length)); return IoStatus->Status; } NTSTATUS SfWriteEncryptFlag(IN PVOID Context) { PPOST_CREATE_WORKER_CONTEXT WorkerCtx = Context; NTSTATUS Status; IO_STATUS_BLOCK IoStatus={0}; UCHAR Buff[13]= "测试用的标记"; LARGE_INTEGER ByteOffset; PFILE_CONTEXT FileCtxPtr = WorkerCtx->FileContext; KeWaitForSingleObject(&FileCtxPtr->Event, Executive, KernelMode, FALSE, NULL); KdPrint(("SfWriteEncryptFlag! WorkerCtx.FileContext->Name = %ws\n", WorkerCtx->FileContext->Name)); ByteOffset.QuadPart = 0; IoStatus.Status = STATUS_SUCCESS; IoStatus.Information = 0; Status =SfIssueReadWriteIrpSynchronously(WorkerCtx->DeviceObject ,WorkerCtx->FileObject,IRP_MJ_WRITE,&IoStatus,Buff, 12,&ByteOffset,0); if (!NT_SUCCESS(Status)) { KdPrint(("SFilter!SfWriteEncryptFlag ERROR: %s\n\n", Buff)); } KeSetEvent(&FileCtxPtr->Event, IO_NO_INCREMENT, FALSE); KeSetEvent(&WorkerCtx->Event, IO_NO_INCREMENT, FALSE); return Status; } |
|
地下室#
发布于:2009-02-26 17:09
忘了说一下具体的症状,在SfWriteEncryptFlag这个函数运行之后,是有对应的fileOject进入了我的sfwrite中的,而sfwrite中的buffer也可以看到自己传下来的内容(不过不知道边界有没有处理好),然而运行完sfwrite后文件内容还是空的,什么也没写进去。我也试过去掉自己写的sfwrite程序,结果也一样。
|
|
5楼#
发布于:2009-02-26 23:58
Man, I hate read others' code. But following piece from your function SfWriteEncryptFlag doesn't make any sense:
Irp = IoBuildAsynchronousFsdRequest( MajorFunction, DeviceObject, Buffer, Length, ByteOffset, IoStatus ); if (!Irp) return STATUS_INSUFFICIENT_RESOURCES; Irp = IoAllocateIrp( DeviceObject->StackSize, FALSE ); if (Irp == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } Also mostly the reason to construct a customized IRP is to by-pass driver stack. I would suggest you either use ZwWriteFile or use attached device object to build an IRP. One question, why don't you use MiniFilter which is much more easier to understand and develop for a newcomer? |
|
6楼#
发布于:2009-02-27 18:08
Irp = IoAllocateIrp( DeviceObject->StackSize, FALSE );
if (Irp == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } 这部分代码贴出来时忘了删掉,这部分是后来用IoBuildAsynchronousFsdRequest()失败后想试下用的,误导了大侠,真是 ![]() |
|
7楼#
发布于:2009-03-01 12:47
又见michaelgz
可以写的,但是要考虑到此种情况是要判断文件名的 |
|
|
8楼#
发布于:2009-03-01 20:30
looksail大侠你好,判断文件名有什么特殊含义吗?可否详细讲讲。在我的理解里,在create里面将文件名提出来是给将来read,write和cleanup的函数用的,大侠特意说的判断文件名是有什么我完全没注意到的地方吗?
|
|