文件删除

操作系统内部文件删除的步骤:

  删除的操作,第一步是打开文件,打开文件的时候必须设置为可以删除。如果打开失败,则直接导致无法删除文件。第二步设置文件属性为用于删除,第三步关闭文件即可。关闭的时候,文件被系统删除。 这里的“删除”并非把文件删除到回收站,而是彻底的就爱那个文件清除,文件删除到回收站只是一种改名操作。

I、打开文件 IoCreateFile

完成例程 
NTSTATUS 
SetInformationCompletion( 
                            IN PDEVICE_OBJECT DeviceObject, 
                            IN PIRP Irp, 
                            IN PVOID Context 
                            ) 
{ 
    Irp->UserIosb->Status = Irp->IoStatus.Status; 
    Irp->UserIosb->Information = Irp->IoStatus.Information; 

    KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, FALSE); 

    IoFreeIrp(Irp); 
    return STATUS_MORE_PROCESSING_REQUIRED; 
} 
/************************************************************************/
/*       根据文件路径打开文件 并获取相应的文件句柄                                                               */
/************************************************************************/
HANDLE 
OpenFile( 
            IN PCWSTR FileName, 
            IN ACCESS_MASK DesiredAccess, 
            IN ULONG ShareAccess 
            ) 
{ 
    NTSTATUS            ntStatus; 
    UNICODE_STRING      uniFileName; 
    OBJECT_ATTRIBUTES  objectAttributes; 
    HANDLE              ntFileHandle; 
    IO_STATUS_BLOCK    ioStatus; 

    //确保IRQL在PASSIVE_LEVEL上
    if (KeGetCurrentIrql() > PASSIVE_LEVEL) 
    { 
        KdPrint(("Do Not At PASSIVE_LEVEL!\n"));
        return 0; 
    } 

    RtlInitUnicodeString(&uniFileName, FileName); 
//初始化对象属性 
    InitializeObjectAttributes(&objectAttributes, &uniFileName, 
        OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); 
    ntStatus = IoCreateFile(&ntFileHandle, 
        GENERIC_READ|SYNCHRONIZE, 
        &objectAttributes, 
        &ioStatus, 
        0, 
        FILE_ATTRIBUTE_NORMAL, 
        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 
        FILE_OPEN, 
        0, 
        NULL, 
        0, 
        CreateFileTypeNone, 
        NULL, 
        IO_NO_PARAMETER_CHECKING); 

    if (!NT_SUCCESS(ntStatus)) 
    { 
        KdPrint(("IrpCreateFile: IoCreateFile 0x%X.\n",ntStatus));
        return 0; 
    } 

    return ntFileHandle; 
} 
BOOLEAN 
DeleteFile( 
              IN HANDLE  FileHandle 
              ) 
{ 
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PFILE_OBJECT fileObject;
    PDEVICE_OBJECT DeviceObject;
    PIRP Irp;
    KEVENT SycEvent ;
    FILE_DISPOSITION_INFORMATION FileInformation;
    IO_STATUS_BLOCK ioStatus;
    PIO_STACK_LOCATION irpSp;
    PSECTION_OBJECT_POINTERS pSectionObjectPointer; 

    // 获取文件对象
    ntStatus = ObReferenceObjectByHandle ( FileHandle, DELETE,
        *IoFileObjectType, KernelMode, (PVOID*)&fileObject, NULL) ;
    if ( !NT_SUCCESS(ntStatus) )
    {
        DbgPrint ( "ObReferenceObjectByHandle error!" ) ;
        return FALSE;
    }

    // 获取与指定文件对象相关联的设备对象
    DeviceObject = IoGetRelatedDeviceObject ( fileObject ) ;

    // 创建IRP
    Irp = IoAllocateIrp ( DeviceObject->StackSize, TRUE ) ;
    if (Irp == NULL)
    {
        ObDereferenceObject ( fileObject ) ;
        DbgPrint ( "FD_DeleteFile IoAllocateIrp error" ) ;
        return FALSE;
    }

    // 初始化同步事件对象
    KeInitializeEvent ( &SycEvent, SynchronizationEvent, FALSE ) ;

    FileInformation.DeleteFile = TRUE;

    // 初始化IRP
    Irp->AssociatedIrp.SystemBuffer = &FileInformation;
    Irp->UserEvent = &SycEvent;
    Irp->UserIosb = &ioStatus;
    Irp->Tail.Overlay.OriginalFileObject = fileObject;
    Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
    Irp->RequestorMode = KernelMode;

    // 设置IRP堆栈
    irpSp = IoGetNextIrpStackLocation(Irp);
    irpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
    irpSp->DeviceObject = DeviceObject;
    irpSp->FileObject = fileObject;
    irpSp->Parameters.SetFile.Length = sizeof(FILE_DISPOSITION_INFORMATION);
    irpSp->Parameters.SetFile.FileInformationClass = FileDispositionInformation;
    irpSp->Parameters.SetFile.FileObject = fileObject;

    // 设置完成例程
    IoSetCompletionRoutine ( Irp, SetInformationCompletion, NULL, TRUE, TRUE, TRUE ) ;

    // 如果没有这3行,就无法删除正在运行的文件
    pSectionObjectPointer = fileObject->SectionObjectPointer;
    pSectionObjectPointer->ImageSectionObject = 0;
    pSectionObjectPointer->DataSectionObject = 0;
/*

强制删除文件的思路很简单,把SECTION_OBJECT_POINTERS结构的DataSectionObject和 ImageSectionObject两个域清空即可删除正在运行的文件。
如果不清空就不能删除运行中的文件。正在运行的文件的这两个域值不为0而文件系 统正在根据这两个域决定该文件是否可以删除。如果文件系统检测这两个值为0,
就理解为文件没有被使用,可以删除。接下去,就是直接发IRP。

*/
    // 派发IRP
    IoCallDriver ( DeviceObject, Irp ) ;

    // 等待IRP完成
    KeWaitForSingleObject ( &SycEvent, Executive, KernelMode, TRUE, NULL);

    // 递减引用计数
    ObDereferenceObject ( fileObject ) ;

    return TRUE ;

} 

 

NTSTATUS
IoCreateFile(
    __out PHANDLE FileHandle,//返回的文件句柄
    __in  ACCESS_MASK DesiredAccess,//访问权限,FILE_READ_ATTRIBUTES

    __in  POBJECT_ATTRIBUTES ObjectAttributes,
    __out PIO_STATUS_BLOCK IoStatusBlock,
    __in_opt PLARGE_INTEGER AllocationSize,
    __in  ULONG FileAttributes,
    __in  ULONG ShareAccess,
    __in  ULONG Disposition,
    __in  ULONG CreateOptions,
    __in_opt PVOID EaBuffer,
    __in  ULONG EaLength,
    __in  CREATE_FILE_TYPE CreateFileType,
    __in_opt PVOID InternalParameters,
    __in  ULONG Options
    );

 ObjectAttributes 为文件属性

//初始化对象属性
 InitializeObjectAttributes(&objectAttributes, &uniFileName,  OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);

uniFileName 为输入的文件名 绝对路径 "\\??\\C:\\test.exe"(或者"\\DosDevice\\C:\\test.exe")

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

至此生成文件句柄,再根据文件句柄获取文件对象FileObject

// 获取文件对象
 ntStatus = ObReferenceObjectByHandle ( FileHandle, DELETE,
  *IoFileObjectType, KernelMode, (PVOID*)&fileObject, NULL) ;

FileHandle :IoCreateFile生成的文件句柄

IoFileObjectType:为系统的全局变量

fileObject:生成的文件对象

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// 获取与指定文件对象相关联的设备对象
 DeviceObject = IoGetRelatedDeviceObject ( fileObject ) ;

 // 创建IRP
 Irp = IoAllocateIrp ( DeviceObject->StackSize, TRUE ) ;

// 初始化同步事件对象

 KeInitializeEvent ( &SycEvent, SynchronizationEvent, FALSE ) ;

 FileInformation.DeleteFile = TRUE;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// 初始化IRP

 Irp->AssociatedIrp.SystemBuffer = &FileInformation;

 Irp->UserEvent = &SycEvent;

 Irp->UserIosb = &ioStatus;

 Irp->Tail.Overlay.OriginalFileObject = fileObject;

 Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();

 Irp->RequestorMode = KernelMode;

 // 设置IRP堆栈

 irpSp = IoGetNextIrpStackLocation(Irp);

 irpSp->MajorFunction = IRP_MJ_SET_INFORMATION;  

irpSp->DeviceObject = DeviceObject;

 irpSp->FileObject = fileObject;

 irpSp->Parameters.SetFile.Length = sizeof(FILE_DISPOSITION_INFORMATION);

 irpSp->Parameters.SetFile.FileInformationClass = FileDispositionInformation;

 irpSp->Parameters.SetFile.FileObject = fileObject;

 // 设置完成例程

 IoSetCompletionRoutine ( Irp, SetInformationCompletion, NULL, TRUE, TRUE, TRUE ) ;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 pSectionObjectPointer = fileObject->SectionObjectPointer;
 pSectionObjectPointer->ImageSectionObject = 0;
 pSectionObjectPointer->DataSectionObject = 0;
强制删除文件的思路很简单,把SECTION_OBJECT_POINTERS结构的DataSectionObject和 ImageSectionObject两个域清空即可删除正在运行的文件。
如果不清空就不能删除运行中的文件。正在运行的文件的这两个域值不为0而文件系 统正在根据这两个域决定该文件是否可以删除。如果文件系统检测这两个值为0,
就理解为文件没有被使用,可以删除。接下去,就是直接发IRP。

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

收尾工作

IoCallDriver ( DeviceObject, Irp ) ;

 // 等待IRP完成

 KeWaitForSingleObject ( &SycEvent, Executive, KernelMode, TRUE, NULL);

 // 递减引用计数  

ObDereferenceObject ( fileObject ) ;

///////////////////////////////////////////////////////////////////////////////////////////////////

 

posted on 2012-04-30 15:12  xmcc  阅读(756)  评论(0编辑  收藏  举报

导航