⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dirctl.c

📁 This is a ReiserFs file system driver for Windows NT/2000/XP/Vista.
💻 C
📖 第 1 页 / 共 3 页
字号:
        RestartScan = FlagOn(((PEXTENDED_IO_STACK_LOCATION)
            IoStackLocation)->Flags, SL_RESTART_SCAN);
        ReturnSingleEntry = FlagOn(((PEXTENDED_IO_STACK_LOCATION)
            IoStackLocation)->Flags, SL_RETURN_SINGLE_ENTRY);
        IndexSpecified = FlagOn(((PEXTENDED_IO_STACK_LOCATION)
            IoStackLocation)->Flags, SL_INDEX_SPECIFIED);

/*
        if (!Irp->MdlAddress && Irp->UserBuffer) {
            ProbeForWrite(Irp->UserBuffer, Length, 1);
        }
*/

		// Check that the user's buffer for the output is valid..
        Buffer = RfsdGetUserBuffer(Irp);

        if (Buffer == NULL) {
            DbgBreak();
            Status = STATUS_INVALID_USER_BUFFER;
            __leave;
        }
        
		// Check if we have a synchronous or asynchronous request...
        if (!IrpContext->IsSynchronous) {
            Status = STATUS_PENDING;
            __leave;
        }
        
        if (!ExAcquireResourceSharedLite(
                 &Fcb->MainResource,
                 IrpContext->IsSynchronous )) {
            Status = STATUS_PENDING;
            __leave;
        }

        FcbResourceAcquired = TRUE;
        
        if (FileName != NULL) {
			// The caller provided a FileName to search on...

            if (Ccb->DirectorySearchPattern.Buffer != NULL) {
                FirstQuery = FALSE;
            } else {
                FirstQuery = TRUE;
                
				// Set up the DirectorySearchPattern to simply be an uppercase copy of the FileName.
                Ccb->DirectorySearchPattern.Length =
                    Ccb->DirectorySearchPattern.MaximumLength =
                    FileName->Length;
                
                Ccb->DirectorySearchPattern.Buffer =
                    ExAllocatePool(PagedPool, FileName->Length);
                
                if (Ccb->DirectorySearchPattern.Buffer == NULL) {
                    Status = STATUS_INSUFFICIENT_RESOURCES;
                    __leave;
                }

                Status = RtlUpcaseUnicodeString(
                    &(Ccb->DirectorySearchPattern),
                    FileName,
                    FALSE);

                if (!NT_SUCCESS(Status))
                    __leave;
            }
        } else if (Ccb->DirectorySearchPattern.Buffer != NULL) {
            FirstQuery = FALSE;
            FileName = &Ccb->DirectorySearchPattern;
        } else {
			// (The FileName and CCB's DirectorySearchPattern were null)

            FirstQuery = TRUE;
            
            Ccb->DirectorySearchPattern.Length =
                Ccb->DirectorySearchPattern.MaximumLength = 2;
            
            Ccb->DirectorySearchPattern.Buffer =
                ExAllocatePool(PagedPool, 2);
            
            if (Ccb->DirectorySearchPattern.Buffer == NULL) {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                __leave;
            }
            
            RtlCopyMemory(
                Ccb->DirectorySearchPattern.Buffer,
                L"*\0", 2);
        }
        
        if (!IndexSpecified) {
            if (RestartScan || FirstQuery) {
                FileIndex = Fcb->RfsdMcb->DeOffset = 0;
            } else {
				// If we are not starting/restaring a scan, then we must have already started.
				// Retrieve the byte offset (in the directory . file) where we left off.
                FileIndex = Ccb->CurrentByteOffset;
            }
        }
                        
        
        RtlZeroMemory(Buffer, Length);

		// Leave if a previous query has already read the entire contents of the directory
        if (Fcb->Inode->i_size <= FileIndex) {
            Status = STATUS_NO_MORE_FILES;
            __leave;
        }               		
        
		//////// 
		
		// Construct a context for the call, and call to parse the entire file system tree.
		// A callback will be triggered on any direntry span belonging to DirectoryKey.
		// This callback will fill the requested section of the user buffer.
		{
			ULONG CurrentFileIndex;

			RFSD_CALLBACK_CONTEXT  CallbackContext;
			CallbackContext.Vcb						= Vcb;
			CallbackContext.Ccb						= Ccb;
			CallbackContext.idxStartingDentry		= FileIndex / sizeof(RFSD_DENTRY_HEAD);
			CallbackContext.idxCurrentDentry		= 0;
			CallbackContext.pDirectoryKey			= pQueryKey;
			CallbackContext.FileInformationClass	= FileInformationClass;
			CallbackContext.Buffer					= Buffer;
			CallbackContext.BufferLength			= Length;
			CallbackContext.ReturnSingleEntry		= ReturnSingleEntry;
			CallbackContext.pUsedLength				= &UsedLength;
			CallbackContext.pPreviousEntry			= NULL;

			RfsdPrint((DBG_TRACE, "Calculated idxCurrentDentry to be %i\n", CallbackContext.idxStartingDentry));

			RfsdParseFilesystemTree(Vcb, pQueryKey, Vcb->SuperBlock->s_root_block, &RfsdDirectoryCallback, &CallbackContext);
		}
				
//================================================================

        if (!UsedLength) {
			// No amount of the dsetination buffer has been used (meaning there were no results)...
            if (FirstQuery) {
                Status = STATUS_NO_SUCH_FILE;
            } else {
                Status = STATUS_NO_MORE_FILES;
            }
        } else {
            Status = STATUS_SUCCESS;
        }

    } __finally {
    
        if (FcbResourceAcquired) {
            ExReleaseResourceForThreadLite(
                &Fcb->MainResource,
                ExGetCurrentResourceThread() );
        }
                       
        if (!IrpContext->ExceptionInProgress) {
            if (Status == STATUS_PENDING) {
                Status = RfsdLockUserBuffer(
                    IrpContext->Irp,
                    Length,
                    IoWriteAccess );
                
                if (NT_SUCCESS(Status)) {
                    Status = RfsdQueueRequest(IrpContext);
                } else {
                    RfsdCompleteIrpContext(IrpContext, Status);
                }
            } else {
                IrpContext->Irp->IoStatus.Information = UsedLength;
                RfsdCompleteIrpContext(IrpContext, Status);
            }
        }
    }
    
    return Status;
}

NTSTATUS
RfsdNotifyChangeDirectory (
    IN PRFSD_IRP_CONTEXT IrpContext
    )
{
    PDEVICE_OBJECT      DeviceObject;
    BOOLEAN             CompleteRequest;
    NTSTATUS            Status = STATUS_UNSUCCESSFUL;
    PRFSD_VCB           Vcb;
    PFILE_OBJECT        FileObject;
    PRFSD_FCB           Fcb;
    PIRP                Irp;
    PIO_STACK_LOCATION  IrpSp;
    ULONG               CompletionFilter;
    BOOLEAN             WatchTree;

    BOOLEAN             bFcbAcquired = FALSE;

    PUNICODE_STRING     FullName;

    __try {

        ASSERT(IrpContext);

        ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
               (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));

        //
        //  Always set the wait flag in the Irp context for the original request.
        //

        SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );

        DeviceObject = IrpContext->DeviceObject;

        if (DeviceObject == RfsdGlobal->DeviceObject) {
            CompleteRequest = TRUE;
            Status = STATUS_INVALID_DEVICE_REQUEST;
            __leave;
        }

        Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;

        ASSERT(Vcb != NULL);

        ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
               (Vcb->Identifier.Size == sizeof(RFSD_VCB)));

        ASSERT(IsMounted(Vcb));

        FileObject = IrpContext->FileObject;

        Fcb = (PRFSD_FCB) FileObject->FsContext;

        ASSERT(Fcb);

        if (Fcb->Identifier.Type == RFSDVCB) {
            DbgBreak();  
            CompleteRequest = TRUE;
            Status = STATUS_INVALID_PARAMETER;
            __leave;
        }

        ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
               (Fcb->Identifier.Size == sizeof(RFSD_FCB)));

        if (!IsDirectory(Fcb)) {
            //- DbgBreak();  // NOTE: Windows (at least I've noticed it with the image previewer), will send this request oftentimes on a file!
            CompleteRequest = TRUE;
            Status = STATUS_INVALID_PARAMETER;
            __leave;
        }

        if (ExAcquireResourceExclusiveLite(
                &Fcb->MainResource,
                TRUE ))  {
            bFcbAcquired = TRUE;
        } else {
            Status = STATUS_PENDING;
            __leave;
        }

        Irp = IrpContext->Irp;

        IrpSp = IoGetCurrentIrpStackLocation(Irp);

#ifndef _GNU_NTIFS_

        CompletionFilter =
            IrpSp->Parameters.NotifyDirectory.CompletionFilter;

#else // _GNU_NTIFS_

        CompletionFilter = ((PEXTENDED_IO_STACK_LOCATION)
            IrpSp)->Parameters.NotifyDirectory.CompletionFilter;

#endif // _GNU_NTIFS_

        WatchTree = IsFlagOn(IrpSp->Flags, SL_WATCH_TREE);

        if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
            Status = STATUS_DELETE_PENDING;
            __leave;
        }

        FullName = &Fcb->LongName;

        if (FullName->Buffer == NULL) {
            if (!RfsdGetFullFileName(Fcb->RfsdMcb, FullName)) {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                __leave;
            }
        }

        FsRtlNotifyFullChangeDirectory( Vcb->NotifySync,
                                        &Vcb->NotifyList,
                                        FileObject->FsContext2,
                                        (PSTRING)FullName,
                                        WatchTree,
                                        FALSE,
                                        CompletionFilter,
                                        Irp,
                                        NULL,
                                        NULL );

        CompleteRequest = FALSE;

        Status = STATUS_PENDING;

/*
    Currently the driver is read-only but here is an example on how to use the
    FsRtl-functions to report a change:

    ANSI_STRING TestString;
    USHORT      FileNamePartLength;

    RtlInitAnsiString(&TestString, "\\ntifs.h");

    FileNamePartLength = 7;

    FsRtlNotifyReportChange(
        Vcb->NotifySync,            // PNOTIFY_SYNC NotifySync
        &Vcb->NotifyList,           // PLIST_ENTRY  NotifyList
        &TestString,                // PSTRING      FullTargetName
        &FileNamePartLength,        // PUSHORT      FileNamePartLength
        FILE_NOTIFY_CHANGE_NAME     // ULONG        FilterMatch
        );

    or

    ANSI_STRING TestString;

    RtlInitAnsiString(&TestString, "\\ntifs.h");

    FsRtlNotifyFullReportChange(
        Vcb->NotifySync,            // PNOTIFY_SYNC NotifySync
        &Vcb->NotifyList,           // PLIST_ENTRY  NotifyList
        &TestString,                // PSTRING      FullTargetName
        1,                          // USHORT       TargetNameOffset
        NULL,                       // PSTRING      StreamName OPTIONAL
        NULL,                       // PSTRING      NormalizedParentName OPTIONAL
        FILE_NOTIFY_CHANGE_NAME,    // ULONG        FilterMatch
        0,                          // ULONG        Action
        NULL                        // PVOID        TargetContext
        );
*/

    } __finally {

        if (bFcbAcquired) {
            ExReleaseResourceForThreadLite(
                &Fcb->MainResource,
                ExGetCurrentResourceThread());
        }

        if (!IrpContext->ExceptionInProgress) {

            if (!CompleteRequest) {
                IrpContext->Irp = NULL;
            }

            RfsdCompleteIrpContext(IrpContext, Status);
        }
    }

    return Status;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -