FSD Direct IO File Operation Library Source

本文介绍了一个基于NTFS文件系统的自定义文件操作实现,包括文件创建、打开、读取及写入等功能。通过直接调用内核API实现了对文件的高级控制,并展示了如何使用这些API来完成常见的文件操作。
#include <ntddk.h>
NTSTATUS FASTCALL
MyIoCallDriver(PDEVICE_OBJECT DeviceObject,
          PIRP Irp)
{
PDRIVER_OBJECT DriverObject;
PIO_STACK_LOCATION Param;
if(!Irp)return STATUS_UNSUCCESSFUL;
if(!DeviceObject) return STATUS_UNSUCCESSFUL;
DriverObject = DeviceObject->DriverObject;
if(!DriverObject) return STATUS_UNSUCCESSFUL;
IoSetNextIrpStackLocation(Irp);
Param = IoGetCurrentIrpStackLocation(Irp);
Param->DeviceObject = DeviceObject;
return DriverObject->MajorFunction[Param->MajorFunction](DeviceObject, Irp);
}

NTSTATUS STDCALL
MypCreateFile(OUT PHANDLE            FileHandle,
        IN      ACCESS_MASK            DesiredAccess,
        IN      POBJECT_ATTRIBUTES      ObjectAttributes,
        OUT PIO_STATUS_BLOCK      IoStatusBlock,
        IN      PLARGE_INTEGER            AllocationSize            OPTIONAL,
        IN      ULONG                  FileAttributes,
        IN      ULONG                  ShareAccess,
        IN      ULONG                  CreateDisposition,
        IN      ULONG                  CreateOptions,
        IN      PVOID                  EaBuffer            OPTIONAL,
        IN      ULONG                  EaLength,
        IN      CREATE_FILE_TYPE      CreateFileType,
        IN      PVOID                  ExtraCreateParameters      OPTIONAL,
        IN      ULONG                  Options)
{
  PFILE_OBJECT            FileObject;
  NTSTATUS            Status;
  PIRP                  Irp;
  PIO_STACK_LOCATION      StackLoc;
  IO_SECURITY_CONTEXT SecurityContext;
  KPROCESSOR_MODE PreviousMode;
if (IoStatusBlock == NULL)
  return STATUS_ACCESS_VIOLATION;

  *FileHandle = 0;

  PreviousMode = ExGetPreviousMode();

  Status = ObCreateObject(PreviousMode,
                    IoFileObjectType,
                    ObjectAttributes,
                    PreviousMode,
                    NULL,
                    sizeof(FILE_OBJECT),
                    0,
                    0,
                    (PVOID*)&FileObject);
  if (!NT_SUCCESS(Status))
  {
     return(Status);
  }
  /*
  Get Us To The Lowest Device~
  */
  PDEVICE_OBJECT DVobj;
  DVobj = FileObject->DeviceObject;
  while((DVobj->NextDevice)││(DVobj->AttachedDevice))
  {
  if(DVobj->NextDevice!=DVobj->AttachedDevice)&&(DVobj!=DVobj->NextDevice)&&(DVobj!=DVobj->AttachedDevice))
  {
  DVobj = (DVobj->NextDevice ? DVobj->NextDevice : DVobj->AttachedDevice);
  }else break ;
  }
  FileObject ->DeviceBject = DVobj;
  Status = ObInsertObject ((PVOID)FileObject,
                    NULL,
                    DesiredAccess,
                    0,
                    NULL,
                    FileHandle);
  if (!NT_SUCCESS(Status))
  {
     ObDereferenceObject (FileObject);
     return(Status);
  }

  if (CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
  {
     FileObject->Flags │= (FO_ALERTABLE_IO │ FO_SYNCHRONOUS_IO);
  }
  if (CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT)
  {
     FileObject->Flags │= FO_SYNCHRONOUS_IO;
  }

  if( CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING )
  FileObject->Flags │= FO_NO_INTERMEDIATE_BUFFERING;

  SecurityContext.SecurityQos = NULL; /* ?? */
  SecurityContext.AccessState = NULL; /* ?? */
  SecurityContext.DesiredAccess = DesiredAccess;
  SecurityContext.FullCreateOptions = 0; /* ?? */
 
  KeInitializeEvent(&FileObject->Lock, SynchronizationEvent, TRUE);
  KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE);
  /*
  * Create a new IRP to hand to
  * the FS driver: this may fail
  * due to resource shortage.
  */
  Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, FALSE);
  if (Irp == NULL)
  {
     ZwClose(FileHandle);
     return (STATUS_UNSUCCESSFUL);
  }

  //trigger FileObject/Event dereferencing
  Irp->Tail.Overlay.OriginalFileObject = FileObject;
  Irp->RequestorMode = PreviousMode;
  Irp->UserIosb = IoStatusBlock;
  Irp->AssociatedIrp.SystemBuffer = EaBuffer;
  Irp->Tail.Overlay.AuxiliaryBuffer = (PCHAR)ExtraCreateParameters;
  Irp->Tail.Overlay.Thread = PsGetCurrentThread();
  Irp->UserEvent = &FileObject->Event;
  if (AllocationSize)
  {
    Irp->Overlay.AllocationSize = *AllocationSize;
  }
 
  /*
  * Get the stack location for the new
  * IRP and prepare it.
  */
  StackLoc = IoGetNextIrpStackLocation(Irp);
  switch (CreateFileType)
  {
     default:
     case CreateFileTypeNone:
      StackLoc->MajorFunction = IRP_MJ_CREATE;
      break;
     
     case CreateFileTypeNamedPipe:
      StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
      break;

     case CreateFileTypeMailslot:
      StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
      break;
  }
  StackLoc->MinorFunction = 0;
  StackLoc->Flags = (UCHAR)Options;
  StackLoc->Control = 0;
  StackLoc->DeviceObject = FileObject->DeviceObject;
  StackLoc->FileObject = FileObject;
  StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
  StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
  StackLoc->Parameters.Create.Options │= (CreateDisposition << 24);
  StackLoc->Parameters.Create.FileAttributes = (USHORT)FileAttributes;
  StackLoc->Parameters.Create.ShareAccess = (USHORT)ShareAccess;
  StackLoc->Parameters.Create.EaLength = EaLength;
 
  /*
  * Now call the driver and
  * possibly wait if it can
  * not complete the request
  * immediately.
  */
  Status = MyIoCallDriver(FileObject->DeviceObject, Irp );
 
  if (Status == STATUS_PENDING)
  {
     KeWaitForSingleObject(&FileObject->Event,
                      Executive,
                      PreviousMode,
                      FALSE,
                      NULL);
     Status = IoStatusBlock->Status;
  }
  if (!NT_SUCCESS(Status))
  {
    FileObject->DeviceObject = NULL;
    FileObject->Vpb = NULL;
     ZwClose(FileHandle);
  }
  return (Status);
}

NTSTATUS STDCALL
MyCreateFile(PHANDLE FileHandle,
        ACCESS_MASK DesiredAccess,
        POBJECT_ATTRIBUTES ObjectAttributes,
        PIO_STATUS_BLOCK IoStatusBlock,
        PLARGE_INTEGER AllocateSize,
        ULONG FileAttributes,
        ULONG ShareAccess,
        ULONG CreateDisposition,
        ULONG CreateOptions,
        PVOID EaBuffer,
        ULONG EaLength)
{
  return MypCreateFile(FileHandle,
                DesiredAccess,
                ObjectAttributes,
                IoStatusBlock,
                AllocateSize,
                FileAttributes,
                ShareAccess,
                CreateDisposition,
                CreateOptions,
                EaBuffer,
                EaLength,
                CreateFileTypeNone,
                NULL,
                0);
}

NTSTATUS STDCALL
MyOpenFile(PHANDLE FileHandle,
        ACCESS_MASK DesiredAccess,
        POBJECT_ATTRIBUTES ObjectAttributes,
        PIO_STATUS_BLOCK IoStatusBlock,
        ULONG ShareAccess,
        ULONG OpenOptions)
{
  return MypCreateFile(FileHandle,
                DesiredAccess,
                ObjectAttributes,
                IoStatusBlock,
                NULL,
                0,
                ShareAccess,
                FILE_OPEN,
                OpenOptions,
                NULL,
                0,
                CreateFileTypeNone,
                NULL,
                0);
}

NTSTATUS STDCALL
MyReadFile (IN HANDLE FileHandle,
        IN HANDLE Event OPTIONAL,
        IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
        IN PVOID ApcContext OPTIONAL,
        OUT PIO_STATUS_BLOCK IoStatusBlock,
        OUT PVOID Buffer,
        IN ULONG Length,
        IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
        IN PULONG Key OPTIONAL)
{
NTSTATUS Status;
PFILE_OBJECT FileObject;
PIRP Irp;
PIO_STACK_LOCATION StackPtr;
KPROCESSOR_MODE PreviousMode;
PKEVENT EventObject = NULL;

if (IoStatusBlock == NULL)
  return STATUS_ACCESS_VIOLATION;

PreviousMode = ExGetPreviousMode();

Status = ObReferenceObjectByHandle(FileHandle,
                          FILE_READ_DATA,
                          IoFileObjectType,
                          PreviousMode,
                          (PVOID*)&FileObject,
                          NULL);
if (!NT_SUCCESS(Status))
  {
    return(Status);
  }
 
if (ByteOffset == NULL)
{
  /* a valid ByteOffset is required if asynch. op. */
  if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
  {
    ObDereferenceObject(FileObject);
    return STATUS_INVALID_PARAMETER;
  }

  ByteOffset = &FileObject->CurrentByteOffset;
}

if (Event != NULL)
{
    Status = ObReferenceObjectByHandle(Event,
                              SYNCHRONIZE,
                              ExEventObjectType,
                              PreviousMode,
                              (PVOID*)&EventObject,
                              NULL);
    if (!NT_SUCCESS(Status))
     {
      ObDereferenceObject(FileObject);
      return(Status);
     }
  KeClearEvent(EventObject);
}

KeClearEvent(&FileObject->Event);

Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
                          FileObject->DeviceObject,
                          Buffer,
                          Length,
                          ByteOffset,
                          EventObject,
                          IoStatusBlock);

/* Trigger FileObject/Event dereferencing */
Irp->Tail.Overlay.OriginalFileObject = FileObject;

Irp->RequestorMode = PreviousMode;

Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;

StackPtr = IoGetNextIrpStackLocation(Irp);
StackPtr->FileObject = FileObject;
StackPtr->Parameters.Read.Key = Key ? *Key : 0;

Status = MyIoCallDriver(FileObject->DeviceObject, Irp);
if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
{
    Status = KeWaitForSingleObject (&FileObject->Event,
                            Executive,
                            PreviousMode,
                            FileObject->Flags & FO_ALERTABLE_IO,
                            NULL);

  if (Status != STATUS_WAIT_0)
  {
    /* Wait failed. */
    return(Status);
  }

  Status = IoStatusBlock->Status;
}

return Status;
}

NTSTATUS STDCALL
MyWriteFile (IN HANDLE FileHandle,
        IN HANDLE Event OPTIONAL,
        IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
        IN PVOID ApcContext OPTIONAL,
        OUT PIO_STATUS_BLOCK IoStatusBlock,
        IN PVOID Buffer,
        IN ULONG Length,
        IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
        IN PULONG Key OPTIONAL)
{
NTSTATUS Status;
PFILE_OBJECT FileObject;
PIRP Irp;
PIO_STACK_LOCATION StackPtr;
KPROCESSOR_MODE PreviousMode;
PKEVENT EventObject = NULL;
if (IoStatusBlock == NULL)
  return STATUS_ACCESS_VIOLATION;

PreviousMode = ExGetPreviousMode();

Status = ObReferenceObjectByHandle(FileHandle,
                          FILE_WRITE_DATA,
                          IoFileObjectType,
                          PreviousMode,
                          (PVOID*)&FileObject,
                          NULL);
if (!NT_SUCCESS(Status))
  {
    return(Status);
  }

if (ByteOffset == NULL)
{
  /* a valid ByteOffset is required if asynch. op. */
  if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
  {
    ObDereferenceObject(FileObject);
    return STATUS_INVALID_PARAMETER;
  }

  ByteOffset = &FileObject->CurrentByteOffset;
}

if (Event != NULL)
{
    Status = ObReferenceObjectByHandle(Event,
                              SYNCHRONIZE,
                              ExEventObjectType,
                              PreviousMode,
                              (PVOID*)&EventObject,
                              NULL);
 
  if (!NT_SUCCESS(Status))
  {
    ObDereferenceObject(FileObject);
    return(Status);
  }
 
  KeClearEvent(EventObject);
}

KeClearEvent(&FileObject->Event);

Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
                          FileObject->DeviceObject,
                          Buffer,
                          Length,
                          ByteOffset,
                          EventObject,
                          IoStatusBlock);

/* Trigger FileObject/Event dereferencing */
Irp->Tail.Overlay.OriginalFileObject = FileObject;

Irp->RequestorMode = PreviousMode;

Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;

StackPtr = IoGetNextIrpStackLocation(Irp);
StackPtr->FileObject = FileObject;
StackPtr->Parameters.Write.Key = Key ? *Key : 0;

Status = MyIoCallDriver(FileObject->DeviceObject, Irp);
if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
  {
    Status = KeWaitForSingleObject (&FileObject->Event,
                            Executive,
                            PreviousMode,
                            FileObject->Flags & FO_ALERTABLE_IO,
                            NULL);
    if (Status != STATUS_WAIT_0)
     {
      /* Wait failed. */
      return(Status);
     }

    Status = IoStatusBlock->Status;
  }

return Status;
}
int __cdecl _open(const char*FileName,int oflag, int pmode)
{    
  HANDLE hFile=0;
  IO_STATUS_BLOCK   ioStatus;
  UNICODE_STRING     unicodeFullName;
  OBJECT_ATTRIBUTES   objectAttributes;
  ANSI_STRING       as;

  RtlInitAnsiString(&as, FileName);
  RtlAnsiStringToUnicodeString(&unicodeFullName, &as, TRUE);

  InitializeObjectAttributes( &objectAttributes,
          &unicodeFullName,
          OBJ_CASE_INSENSITIVE,
          NULL,
          NULL);

  NTSTATUS ntStatus = MyOpenFile( &hFile,
          GENERIC_READ │ GENERIC_WRITE │ SYNCHRONIZE,
          &objectAttributes,
          &ioStatus,
          FILE_SHARE_READ │ FILE_SHARE_WRITE,
          FILE_SYNCHRONOUS_IO_NONALERT);

  if(!NT_SUCCESS(ntStatus))   // if error - try to open for reading
  {
    ntStatus = MyOpenFile( &hFile,
          GENERIC_READ │ SYNCHRONIZE,
          &objectAttributes,
          &ioStatus,
          FILE_SHARE_READ │ FILE_SHARE_WRITE,
          FILE_SYNCHRONOUS_IO_NONALERT);

    if(!NT_SUCCESS(ntStatus))    
    {
        return 0;
    }
  }

  return (int)hFile;
}

int __cdecl open(const char*FileName,int oflag, int pmode)
{
  return _open(FileName,oflag,pmode);
}

int __cdecl _creat(const char*FileName, int pmode)
{    
  HANDLE hFile=0;
  IO_STATUS_BLOCK   ioStatus;
  UNICODE_STRING     unicodeFullName;
  OBJECT_ATTRIBUTES   objectAttributes;
  ANSI_STRING       as;

  RtlInitAnsiString(&as, FileName);
  RtlAnsiStringToUnicodeString(&unicodeFullName, &as, TRUE);

  InitializeObjectAttributes( &objectAttributes,
          &unicodeFullName,
          OBJ_CASE_INSENSITIVE,
          NULL,
          NULL);

  NTSTATUS ntStatus = MyCreateFile( &hFile,
          GENERIC_READ │ GENERIC_WRITE │ SYNCHRONIZE,
          &objectAttributes,
          &ioStatus, 0, pmode,
          FILE_SHARE_READ │ FILE_SHARE_WRITE,
          FILE_OVERWRITE_IF,
          FILE_SYNCHRONOUS_IO_NONALERT,0,0);

  if(!NT_SUCCESS(ntStatus))   // if error - try to open for reading
  {

    return 0;
  }

  return (int)hFile;
}

void __cdecl _close(int hFile)
{
  if(hFile)
    ZwClose((HANDLE)hFile);
}

void __cdecl close(int hFile)
{
  _close(hFile);
}

int __cdecl _read( int handle, void *buffer, unsigned int count )
{
  IO_STATUS_BLOCK   ioStatus;
  NTSTATUS ntStatus;

  if(!NT_SUCCESS(ntStatus=MyReadFile((HANDLE)handle,0,0,0,&ioStatus,(void*)buffer,count,0,0)))
  {
    return 0;
  } else
    return ioStatus.Information;
}

int __cdecl _write( int handle, const void *buffer, unsigned int count )
{
  IO_STATUS_BLOCK   ioStatus;
  NTSTATUS ntStatus;

  if(!NT_SUCCESS(ntStatus=MyWriteFile((HANDLE)handle,0,0,0,&ioStatus,(void*)buffer,count,0,0)))
  {
    return 0;
  } else
    return ioStatus.Information;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值