앨리스의 토끼

javahawk.egloos.com

포토로그 방명록


최근 포토로그


File System Filter Driver by Kircheis

근래 갑작스럽게 파일 시스템 필터 드라이버의 개발을 시작하게 되었다.
그냥 드라이버를 좀 하면 되지 않을 까 했는데, 생각보다 많은 부분에서 차이가 나더라..
일단 가볍게 책 두 권을 독파하는 것으로 시작해서 이 분야에 대한 참조 소스를 찾아 나섰다.

어딘가의 웹에서 떠돌아 다니던 File System Filter Driver Tutorial이라는 워드 문서를 발견했지만, 소스는 찾을 수가 없더라...

그러던 것이 구글에서 그대로 조회를 해 봤더니 Code project 사이트에서 해당 소스를 찾을 수 있었다.
 - 원본 소스의 이름은 FsFilter 이다.

이걸 이해도 못하고 그냥 쓸 수는 없어서 일단 문서를 기준으로 파일을 만들기 시작했다.

문서를 기준으로 만드는 것은 역시 수두룩한 에러를 뱉어 낸다.
이어서 해당 소스를 뒤져서 없는 부분들을 메워나갔다.
뭐 결국 원래 소스를 그대로 답습한 내용이지만, 이걸 하나의 파일로 만들었다.
여기에 H/W 드라이버를 제작할 때의 필요 함수와 구조체 정의가 몇개 추가되었다.
이 부분에 대해서는 "윈도우 디바이스 드라이버"라는 책에서 샘플로 제공된 소스를 참조했다.

어디까지나 나는 드라이버에 대해서는 초보자나 마찬가지이므로 새로 정의하거나 수정하는 작업은 좀 더 후의 일이 될 듯하다.

파일 시스템 필터 드라이브 제작 시 주의할 부분이 하나

A file system filter driver must have the fast-io dispatch table. If you've forgot to set up the fast-io dispatch table it will lead system to crash. Fast-io is an alternative way to initiate I/O operation (and it's faster than IRP). Fast-io operations are always synchronous. If fast-io handler returns FALSE then fast-io way is imposible and IRP will be created.

출처 :
 - File System Filter Driver Tutorial,
 - http://www.apriorit.com
 - Written by Sergey Podobry

결국 Fast-IO를 처리할 때는 BSOD가 발생할 수 있으니 언제나 IRP 처리를 동반해야 한다는...
뭐 실제 어떻게 동작하는 아직 테스트를 해보지 않아서 모르겠지만 말이지...

어디까지나 아직 테스트를 거치거나 다른 여러가지 것들을 확인하지 못했으니 설혹 보게 되더라도 딴지 걸지 말자.
괜히 이 파일들에 대해 왈가왈부하지 마시길...

아, 정말 싫다.



File_System_Filter_Driver_Tutorial.doc


원본 소스 출처 : http://www.codeproject.com/Articles/43586/File-System-Filter-Driver-Tutorial

#include <ntifs.h>

#define DELAY_ONE_MICROSECOND ( -10 )
#define DELAY_ONE_MILLISECOND ( DELAY_ONE_MICROSECOND * 1000 )
#define DELAY_ONE_SECOND  ( DELAY_ONE_MILLISECOND * 1000 )

#define DEVOBJ_LIST_SIZE        64

// Macro to test if FAST_IO_DISPATCH handling routine is valid
#define VALID_FAST_IO_DISPATCH_HANDLER( _FastIoDispatchPtr, _FieldName ) \
 ( ( ( _FastIoDispatchPtr ) != NULL ) && \
 ( ( ( _FastIoDispatchPtr )->SizeOfFastIoDispatch ) >= \
 ( FIELD_OFFSET( FAST_IO_DISPATCH, _FieldName ) + sizeof( void * ) ) ) && \
 ( ( _FastIoDispatchPtr )->_FieldName != NULL ) )

////////////////////////////////////////////////////////////////////
// Structures
typedef struct _FSFILTER_DEVICE_EXTENSION
{
 PDEVICE_OBJECT AttachedToDeviceObject;
} FSFILTER_DEVICE_EXTENSION, *PFSFILTER_DEVICE_EXTENSION;

// For H/W driver
typedef struct _DEVICE_EXTENSION
{
 PDEVICE_OBJECT NextLayerDeviceObject;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

////////////////////////////////////////////////////////////////////
// Functions - FsFilterFastIo~~~
BOOLEAN FsFilterFastIoCheckIfPossible(
 __in PFILE_OBJECT  pFileObject,
 __in PLARGE_INTEGER  pFileOffset,
 __in ULONG    ulLength,
 __in BOOLEAN   bWait,
 __in ULONG    ulLockKey,
 __in BOOLEAN   bCheckForReadOperation,
 __out PIO_STATUS_BLOCK pIoStatus,
 __in PDEVICE_OBJECT  pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoCheckIfPossible ) )
 {
  return ( fastIoDispatch->FastIoCheckIfPossible )(
   pFileObject,
   pFileOffset,
   ulLength,
   bWait,
   ulLockKey,
   bCheckForReadOperation,
   pIoStatus,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoRead(
 __in PFILE_OBJECT  pFileObject,
 __in PLARGE_INTEGER  pFileOffset,
 __in ULONG    ulLength,
 __in BOOLEAN   bWait,
 __in ULONG    ulLockKey,
 __out PVOID    pBuffer,
 __out PIO_STATUS_BLOCK pIoStatus,
 __in PDEVICE_OBJECT  pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoRead ) )
 {
  return ( fastIoDispatch->FastIoRead )(
   pFileObject,
   pFileOffset,
   ulLength,
   bWait,
   ulLockKey,
   pBuffer,
   pIoStatus,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoWrite(
 __in PFILE_OBJECT  pFileObject,
 __in PLARGE_INTEGER  pFileOffset,
 __in ULONG    ulLength,
 __in BOOLEAN   bWait,
 __in ULONG    ulLockKey,
 __in PVOID    pBuffer,
 __out PIO_STATUS_BLOCK pIoStatus,
 __in PDEVICE_OBJECT  pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoWrite ) )
 {
  return ( fastIoDispatch->FastIoWrite )(
   pFileObject,
   pFileOffset,
   ulLength,
   bWait,
   ulLockKey,
   pBuffer,
   pIoStatus,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoQueryBasicInfo(
 __in PFILE_OBJECT    pFileObject,
 __in BOOLEAN     bWait,
 __out PFILE_BASIC_INFORMATION pFileBasicInfo,
 __out PIO_STATUS_BLOCK   pIoStatus,
 __in PDEVICE_OBJECT    pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryBasicInfo ) )
 {
  return ( fastIoDispatch->FastIoQueryBasicInfo )(
   pFileObject,
   bWait,
   pFileBasicInfo,
   pIoStatus,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoQueryStandardInfo(
 __in PFILE_OBJECT     pFileObject,
 __in BOOLEAN      bWait,
 __out PFILE_STANDARD_INFORMATION pFileStandardInfo,
 __out PIO_STATUS_BLOCK    pIoStatus,
 __in PDEVICE_OBJECT     pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryStandardInfo ) )
 {
  return ( fastIoDispatch->FastIoQueryStandardInfo )(
   pFileObject,
   bWait,
   pFileStandardInfo,
   pIoStatus,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoLock(
 __in PFILE_OBJECT  pFileObject,
 __in PLARGE_INTEGER  pFileOffset,
 __in PLARGE_INTEGER  pLength,
 __in PEPROCESS   pProcessId,
 __in ULONG    ulKey,
 __in BOOLEAN   bFailImmediately,
 __in BOOLEAN   bExclusiveLock,
 __out PIO_STATUS_BLOCK pIoStatus,
 __in PDEVICE_OBJECT  pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoLock ) )
 {
  return ( fastIoDispatch->FastIoLock )(
   pFileObject,
   pFileOffset,
   pLength,
   pProcessId,
   ulKey,
   bFailImmediately,
   bExclusiveLock,
   pIoStatus,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoUnlockSingle(
 __in PFILE_OBJECT  pFileObject,
 __in PLARGE_INTEGER  pFileOffset,
 __in PLARGE_INTEGER  pLength,
 __in PEPROCESS   pProcessId,
 __in ULONG    ulKey,
 __out PIO_STATUS_BLOCK pIoStatus,
 __in PDEVICE_OBJECT  pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoUnlockSingle ) )
 {
  return ( fastIoDispatch->FastIoUnlockSingle )(
   pFileObject,
   pFileOffset,
   pLength,
   pProcessId,
   ulKey,
   pIoStatus,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoUnlockAll(
 __in PFILE_OBJECT  pFileObject,
 __in PEPROCESS   pProcessId,
 __out PIO_STATUS_BLOCK pIoStatus,
 __in PDEVICE_OBJECT  pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoUnlockAll ) )
 {
  return ( fastIoDispatch->FastIoUnlockAll )(
   pFileObject,
   pProcessId,
   pIoStatus,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoUnlockAllByKey(
 __in PFILE_OBJECT  pFileObject,
 __in PVOID    pProcessId,
 __in ULONG    ulKey,
 __out PIO_STATUS_BLOCK pIoStatus,
 __in PDEVICE_OBJECT  pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoUnlockAllByKey ) )
 {
  return ( fastIoDispatch->FastIoUnlockAllByKey )(
   pFileObject,
   pProcessId,
   ulKey,
   pIoStatus,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoDeviceControl(
 __in PFILE_OBJECT  pFileObject,
 __in BOOLEAN   bWait,
 __in_opt PVOID   pInputBuffer,
 __in ULONG    ulInputBuffer,
 __out_opt PVOID   pOutputBuffer,
 __in ULONG    ulOutputBuffer,
 __in ULONG    ulIoControlCode,
 __out PIO_STATUS_BLOCK pIoStatus,
 __in PDEVICE_OBJECT  pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoDeviceControl ) )
 {
  return ( fastIoDispatch->FastIoDeviceControl )(
   pFileObject,
   bWait,
   pInputBuffer,
   ulInputBuffer,
   pOutputBuffer,
   ulOutputBuffer,
   ulIoControlCode,
   pIoStatus,
   nextDeviceObject );
 }

 return FALSE;
}

VOID FsFilterFastIoDetachDevice(
 __in PDEVICE_OBJECT  SourceDevice,
 __in PDEVICE_OBJECT  TargetDevice
 )
{
 // Detach from the file system's volume device object.
 IoDetachDevice( TargetDevice );
 IoDeleteDevice( SourceDevice );
}

BOOLEAN FsFilterFastIoQueryNetworkOpenInfo(
 __in PFILE_OBJECT      pFileObject,
 __in BOOLEAN       bWait,
 __out PFILE_NETWORK_OPEN_INFORMATION pfNetworkOpenInfo,
 __out PIO_STATUS_BLOCK     pIoStatus,
 __in PDEVICE_OBJECT      pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryNetworkOpenInfo ) )
 {
  return ( fastIoDispatch->FastIoQueryNetworkOpenInfo )(
   pFileObject,
   bWait,
   pfNetworkOpenInfo,
   pIoStatus,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoMdlRead(
 __in PFILE_OBJECT  pFileObject,
 __in PLARGE_INTEGER  pFileOffset,
 __in ULONG    ulLength,
 __in ULONG    ulLockKey,
 __out PMDL *   pMdlChain,
 __out PIO_STATUS_BLOCK pIoStatus,
 __in PDEVICE_OBJECT  pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlRead ) )
 {
  return ( fastIoDispatch->MdlRead )(
   pFileObject,
   pFileOffset,
   ulLength,
   ulLockKey,
   pMdlChain,
   pIoStatus,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoMdlReadComplete(
 __in PFILE_OBJECT  pFileObject,
 __out PMDL    pMdlChain,
 __in PDEVICE_OBJECT  pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlReadComplete ) )
 {
  return ( fastIoDispatch->MdlReadComplete )(
   pFileObject,
   pMdlChain,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoPrepareMdlWrite(
 __in PFILE_OBJECT  pFileObject,
 __in PLARGE_INTEGER  pFileOffset,
 __in ULONG    ulLength,
 __in ULONG    ulLockKey,
 __out PMDL *   pMdlChain,
 __out PIO_STATUS_BLOCK pIoStatus,
 __in PDEVICE_OBJECT  pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, PrepareMdlWrite ) )
 {
  return ( fastIoDispatch->PrepareMdlWrite )(
   pFileObject,
   pFileOffset,
   ulLength,
   ulLockKey,
   pMdlChain,
   pIoStatus,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoMdlWriteComplete(
 __in PFILE_OBJECT  pFileObject,
 __in PLARGE_INTEGER  pFileOffset,
 __out PMDL    pMdlChain,
 __in PDEVICE_OBJECT  pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlWriteComplete ) )
 {
  return ( fastIoDispatch->MdlWriteComplete )(
   pFileObject,
   pFileOffset,
   pMdlChain,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoReadCompressed(
 __in PFILE_OBJECT      pFileObject,
 __in PLARGE_INTEGER      pFileOffset,
 __in ULONG        ulLength,
 __in ULONG        ulLockKey,
 __out PVOID        pBuffer,
 __out PMDL *       pMdlChain,
 __out PIO_STATUS_BLOCK     pIoStatus,
 __out struct _COMPRESSED_DATA_INFO * pCompDataInfo,
 __in ULONG        ulCompDataInfoLen,
 __in PDEVICE_OBJECT      pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoReadCompressed ) )
 {
  return ( fastIoDispatch->FastIoReadCompressed )(
   pFileObject,
   pFileOffset,
   ulLength,
   ulLockKey,
   pBuffer,
   pMdlChain,
   pIoStatus,
   pCompDataInfo,
   ulCompDataInfoLen,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoWriteCompressed(
 __in PFILE_OBJECT      pFileObject,
 __in PLARGE_INTEGER      pFileOffset,
 __in ULONG        ulLength,
 __in ULONG        ulLockKey,
 __out PVOID        pBuffer,
 __out PMDL *       pMdlChain,
 __out PIO_STATUS_BLOCK     pIoStatus,
 __out struct _COMPRESSED_DATA_INFO * pCompDataInfo,
 __in ULONG        ulCompDataInfoLen,
 __in PDEVICE_OBJECT      pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoWriteCompressed ) )
 {
  return ( fastIoDispatch->FastIoWriteCompressed )(
   pFileObject,
   pFileOffset,
   ulLength,
   ulLockKey,
   pBuffer,
   pMdlChain,
   pIoStatus,
   pCompDataInfo,
   ulCompDataInfoLen,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoMdlReadCompleteCompressed(
 __in PFILE_OBJECT   pFileObject,
 __in PMDL     pMdlChain,
 __in PDEVICE_OBJECT   pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlReadCompleteCompressed ) )
 {
  return ( fastIoDispatch->MdlReadCompleteCompressed )(
   pFileObject,
   pMdlChain,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoMdlWriteCompleteCompressed(
 __in PFILE_OBJECT   pFileObject,
 __in PLARGE_INTEGER   pFileOffset,
 __in PMDL     pMdlChain,
 __in PDEVICE_OBJECT   pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlWriteCompleteCompressed ) )
 {
  return ( fastIoDispatch->MdlWriteCompleteCompressed )(
   pFileObject,
   pFileOffset,
   pMdlChain,
   nextDeviceObject );
 }

 return FALSE;
}

BOOLEAN FsFilterFastIoQueryOpen(
 __in PIRP        pIrp,
 __out PFILE_NETWORK_OPEN_INFORMATION pfNetOpenInfo,
 __in PDEVICE_OBJECT      pDeviceObject
 )
{
 // Pass through logic for this type of Fast I/O
 PDEVICE_OBJECT  nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
 PFAST_IO_DISPATCH fastIoDispatch  = nextDeviceObject->DriverObject->FastIoDispatch;

 if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryOpen ) )
 {
  BOOLEAN bResult;
  PIO_STACK_LOCATION pIoStackLocation = IoGetCurrentIrpStackLocation( pIrp );

  // Before calling the next filter, we must make sure their device
  // object is in the current stack entry for the given IRP
  pIoStackLocation->DeviceObject = nextDeviceObject;

  bResult = ( fastIoDispatch->FastIoQueryOpen )(
   pIrp,
   pfNetOpenInfo,
   nextDeviceObject );

  // Always restore the IRP back to our device object
  pIoStackLocation->DeviceObject = pDeviceObject;

  return bResult;
 }

 return FALSE;
}

////////////////////////////////////////////////////////////////////
// Global data
PDRIVER_OBJECT g_fsFilterDriverObject = NULL;

FAST_IO_DISPATCH g_fastIoDispatch =
{
 sizeof( FAST_IO_DISPATCH ),
 FsFilterFastIoCheckIfPossible,
 FsFilterFastIoRead,
 FsFilterFastIoWrite,
 FsFilterFastIoQueryBasicInfo,
 FsFilterFastIoQueryStandardInfo,
 FsFilterFastIoLock,
 FsFilterFastIoUnlockSingle,
 FsFilterFastIoUnlockAll,
 FsFilterFastIoUnlockAllByKey,
 FsFilterFastIoDeviceControl,
 NULL,
 NULL,
 FsFilterFastIoDetachDevice,
 FsFilterFastIoQueryNetworkOpenInfo,
 NULL,
 FsFilterFastIoMdlRead,
 FsFilterFastIoMdlReadComplete,
 FsFilterFastIoPrepareMdlWrite,
 FsFilterFastIoMdlWriteComplete,
 FsFilterFastIoReadCompressed,
 FsFilterFastIoWriteCompressed,
 FsFilterFastIoMdlReadCompleteCompressed,
 FsFilterFastIoMdlWriteCompleteCompressed,
 FsFilterFastIoQueryOpen,
 NULL,
 NULL,
 NULL,
};

////////////////////////////////////////////////////////////////////
// Misc
BOOLEAN FsFilterIsMyDeviceObject(
 __in PDEVICE_OBJECT DeviceObject
 )
{
 return DeviceObject->DriverObject == g_fsFilterDriverObject;
}

////////////////////////////////////////////////////////////////////
// This determines whether we are attached to the given device
BOOLEAN FsFilterIsAttachedToDevice(
 __in PDEVICE_OBJECT  pDeviceObject
 )
{
 PDEVICE_OBJECT nextDevObj  = NULL;
 PDEVICE_OBJECT currentDevObj = IoGetAttachedDeviceReference( pDeviceObject );

 // Scan down the list to find our device object
 do
 {
  if( FsFilterIsMyDeviceObject( currentDevObj ) )
  {
   ObDereferenceObject( currentDevObj );

   return TRUE;
  }

  // Get the next attached object.
  nextDevObj = IoGetLowerDeviceObject( currentDevObj );

  // Dereference our current device object, before moving to the next one.
  ObDereferenceObject( currentDevObj );
  currentDevObj = nextDevObj;
 }
 while( NULL != currentDevObj );

 return FALSE;
}

/////////////////////////////////////////////////////////////////////
// This will attach to a DeviceObject that represents a mounted volume
NTSTATUS FsFilterAttachToDevice(
 __in PDEVICE_OBJECT    pDeviceObject,
 __out_opt PDEVICE_OBJECT * pFilterDeviceObject
 )
{
 NTSTATUS     ntStatus   = STATUS_SUCCESS;
 PDEVICE_OBJECT    filterDeviceObject = NULL;
 PFSFILTER_DEVICE_EXTENSION pDevExt    = NULL;
 ULONG      i     = 0;

 ASSERT( !FsFilterIsAttachedToDevice( pDeviceObject ) );

 // Create a new devcie object we can attach with.
 ntStatus = IoCreateDevice(
  g_fsFilterDriverObject,
  sizeof( FSFILTER_DEVICE_EXTENSION ),
  NULL,
  pDeviceObject->DeviceType,
  0,
  FALSE,
  &filterDeviceObject );

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

 pDevExt = ( PFSFILTER_DEVICE_EXTENSION )filterDeviceObject->DeviceExtension;

 // Propagate flags from the Device Object we are trying to attach to.
 if( FlagOn( pDeviceObject->Flags, DO_BUFFERED_IO ) )
 {
  SetFlag( filterDeviceObject->Flags, DO_BUFFERED_IO );
 }

 if( FlagOn( pDeviceObject->Characteristics, FILE_DEVICE_SECURE_OPEN ) )
 {
  SetFlag( filterDeviceObject->Characteristics, FILE_DEVICE_SECURE_OPEN );
 }

 // Do the attachment.
 // Is is possible for this attachment request to fail because this device
 // object has not finished initializing. This can occur if this filter
 // loaded just as this volume was being mounted.
 for( i = 0 ; i < 8 ; i ++ )
 {
  LARGE_INTEGER lnInterval;

  ntStatus = IoAttachDeviceToDeviceStackSafe(
   filterDeviceObject,
   pDeviceObject,
   &pDevExt->AttachedToDeviceObject );

  if( NT_SUCCESS( ntStatus ) )
  {
   break;
  }

  // Delay, giving the device object a chance to finish its
  // initialization so we can try again.
  lnInterval.QuadPart = ( 500 * DELAY_ONE_MILLISECOND );
  KeDelayExecutionThread( KernelMode, FALSE, &lnInterval );
 }

 if( !NT_SUCCESS( ntStatus ) )
 {
  // Clean up.
  IoDeleteDevice( filterDeviceObject );
  filterDeviceObject = NULL;
 }
 else
 {
  // Mark we are done initializing.
  ClearFlag( filterDeviceObject->Flags, DO_DEVICE_INITIALIZING );

  if( NULL != pFilterDeviceObject )
  {
   * pFilterDeviceObject = filterDeviceObject;
  }
 }

 return ntStatus;
}

void FsFilterDetachFromDevice(
 __in PDEVICE_OBJECT  pDeviceObject
 )
{
 PFSFILTER_DEVICE_EXTENSION pDevExt = ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension;

 IoDetachDevice( pDevExt->AttachedToDeviceObject );
 IoDeleteDevice( pDeviceObject );
}

////////////////////////////////////////////////////////////////////
// Enumerate all the mounted devices that currently exist for
// the given file system and attach to them
NTSTATUS FsFilterEnumerateFileSystemVolumes(
 __in PDEVICE_OBJECT  pDeviceObject
 )
{
 NTSTATUS  ntStatus  = STATUS_SUCCESS;
 ULONG   ulNumbDevices = 0;
 ULONG   i    = 0;
 PDEVICE_OBJECT lstDevObj[DEVOBJ_LIST_SIZE];

 // Now get the list of devices.
 ntStatus = IoEnumerateDeviceObjectList(
  pDeviceObject->DriverObject,
  lstDevObj,
  sizeof( lstDevObj ),
  &ulNumbDevices );

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

 ulNumbDevices = min( ulNumbDevices, RTL_NUMBER_OF( lstDevObj ) );

 // Walk the given list of devices and attach to them if we should.
 for( i = 0 ; i < ulNumbDevices ; ++ i )
 {
  // Do not attach if:
  // - This is the control device object ( the one passed in )
  // - The device type does not match
  // - We are already attached to it.
  if( lstDevObj[i] != pDeviceObject &&
   lstDevObj[i]->DeviceType != pDeviceObject->DeviceType &&
   !FsFilterIsAttachedToDevice( lstDevObj[i] ) )
  {
   ntStatus = FsFilterAttachToDevice( lstDevObj[i], NULL );
  }

  ObDereferenceObject( lstDevObj[i] );
 }

 return STATUS_SUCCESS;
}

////////////////////////////////////////////////////////////////////
// This will attach to the given file system device object
NTSTATUS FsFilterAttachToFileSystemDevice(
 __in PDEVICE_OBJECT  pDeviceObject
 )
{
 NTSTATUS  ntStatus    = STATUS_SUCCESS;
 PDEVICE_OBJECT pdoFilterDeviceObject = NULL;

 if( !FsFilterIsAttachedToDevice( pDeviceObject ) )
 {
  ntStatus = FsFilterAttachToDevice( pDeviceObject, &pdoFilterDeviceObject );

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

  // Enumerated all the mounted devices that currently exist for this file system and attach to them.
  ntStatus = FsFilterEnumerateFileSystemVolumes( pDeviceObject );

  if( !NT_SUCCESS( ntStatus ) )
  {
   FsFilterDetachFromDevice( pdoFilterDeviceObject );

   return ntStatus;
  }
 }

 return STATUS_SUCCESS;
}

////////////////////////////////////////////////////////////////////
// This will detach us from the chain
VOID FsFilterDetachFromFileSystemDevice(
 __in PDEVICE_OBJECT pDeviceObject
 )
{
 PDEVICE_OBJECT pDevObj = NULL;

 for( pDevObj = pDeviceObject->AttachedDevice ; NULL != pDevObj ; pDevObj = pDevObj->AttachedDevice )
 {
  if( FsFilterIsMyDeviceObject( pDevObj ) )
  {
   // Detach us from the object just below us. Cleanup and delete the object.
   FsFilterDetachFromDevice( pDevObj );

   break;
  }
 }
}

////////////////////////////////////////////////////////////////////
// This routine is invoked whenever a file system has either registered
// or unregistered itself as an active file system.
VOID FsFilterNotificationCallback(
 __in PDEVICE_OBJECT  DeviceObject,
 __in BOOLEAN   FsActive
 )
{
 // Handle attaching/detaching from the given file system.
 if( FsActive )
 {
  FsFilterAttachToFileSystemDevice( DeviceObject );
 }
 else
 {
  FsFilterDetachFromFileSystemDevice( DeviceObject );
 }
}

////////////////////////////////////////////////////////////////////
// PassThrough IRP Handler
NTSTATUS _DispatchPassThrough(
 __in PDEVICE_OBJECT DeviceObject,
 __in PIRP   Irp
 )
{
 PFSFILTER_DEVICE_EXTENSION pDevExt = ( PFSFILTER_DEVICE_EXTENSION )DeviceObject->DeviceExtension;
 IoSkipCurrentIrpStackLocation( Irp );

 return IoCallDriver( pDevExt->AttachedToDeviceObject, Irp );
}

////////////////////////////////////////////////////////////////////
// IRP_MJ_CREATE IRP Handler
NTSTATUS _DispatchCreate(
 __in PDEVICE_OBJECT DeviceObject,
 __in PIRP   Irp
 )
{
 PFILE_OBJECT pFileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject;
 DbgPrint( "%wZ\n", &pFileObject->FileName );

 return _DispatchPassThrough( DeviceObject, Irp );
}

////////////////////////////////////////////////////////////////////
// Unload routine
VOID FsFilterUnload(
 __in PDRIVER_OBJECT DriverObject
 )
{
 ULONG    ulDevices = 0;
 ULONG    i   = 0;
 LARGE_INTEGER  ulInterval;
 PDEVICE_OBJECT  lstDevObj[DEVOBJ_LIST_SIZE];

 ulInterval.QuadPart = ( 5 * DELAY_ONE_SECOND );

 // Unregistered callback routine for file system changes.
 IoUnregisterFsRegistrationChange( DriverObject, FsFilterNotificationCallback );

 for( ; ; )
 {
  IoEnumerateDeviceObjectList(
   DriverObject,
   lstDevObj,
   sizeof( lstDevObj ),
   &ulDevices );

  if( 0 == ulDevices )
  {
   break;
  }

  ulDevices = min( ulDevices, RTL_NUMBER_OF( lstDevObj ) );

  for( i = 0 ; i < ulDevices ; ++ i )
  {
   FsFilterDetachFromDevice( lstDevObj[i] );
   ObDereferenceObject( lstDevObj[i] );
  }

  KeDelayExecutionThread( KernelMode, FALSE, &ulInterval );
 }
}

////////////////////////////////////////////////////////////////////
// For H/W driver
NTSTATUS AddDevice(
 __in PDRIVER_OBJECT  pDriverObject,
 __in PDEVICE_OBJECT  pPhysicalDeviceObject
 )
{
 NTSTATUS    ntStatus  = STATUS_SUCCESS;
 PDEVICE_OBJECT   pDevObj   = NULL;
 PDEVICE_EXTENSION  pDevExtension;

 ntStatus = IoCreateDevice(
  pDriverObject,
  sizeof( DEVICE_EXTENSION ),
  NULL,
  FILE_DEVICE_UNKNOWN,
  0,    // FILE_AUTOGENERATED_DEVICE_NAME
  FALSE,
  &pDevObj );

 pDevExtension = ( PDEVICE_EXTENSION )pDevObj->DeviceExtension;
 pDevExtension->NextLayerDeviceObject = IoAttachDeviceToDeviceStack( pDevObj, pPhysicalDeviceObject );
 pDevObj->Flags &= ~DO_DEVICE_INITIALIZING;

 return ntStatus;
}

NTSTATUS PnpDispatch(
 __in PDEVICE_OBJECT  pDeviceObject,
 __in PIRP    pIrp
 )
{
 PIO_STACK_LOCATION pStack;
 PDEVICE_EXTENSION pDeviceExtension;
 NTSTATUS   ntStatus   = STATUS_SUCCESS;
 PDEVICE_OBJECT  nextLayerDevObj;

 pStack = IoGetCurrentIrpStackLocation( pIrp );
 pDeviceExtension = ( PDEVICE_EXTENSION )pDeviceObject->DeviceExtension;
 nextLayerDevObj = pDeviceExtension->NextLayerDeviceObject;

 switch( pStack->MinorFunction )
 {
 case IRP_MN_REMOVE_DEVICE:
  {
   IoDetachDevice( nextLayerDevObj );
   IoDeleteDevice( pDeviceObject );
  }

  break;
 }

 IoSkipCurrentIrpStackLocation( pIrp );
 ntStatus = IoCallDriver( nextLayerDevObj, pIrp );

 return ntStatus;
}

////////////////////////////////////////////////////////////////////
// DriverEntry - Entry point of the driver
extern "C"
NTSTATUS DriverEntry(
 __inout PDRIVER_OBJECT DriverObject,
 __in PUNICODE_STRING RegistryPath
 )
{
 NTSTATUS status = STATUS_SUCCESS;
 ULONG  i = 0;

// ASSERT( FALSE ); // This will break to debugger

 // Store our driver object
 g_fsFilterDriverObject = DriverObject;

 // Initialize the driver object dispatch table.
 for( i = 0 ; i <= IRP_MJ_MAXIMUM_FUNCTION ; ++ i )
 {
  DriverObject->MajorFunction[i] = _DispatchPassThrough;
 }

 DriverObject->MajorFunction[IRP_MJ_CREATE] = _DispatchCreate;

 // Set fast-io dispatch table.
 DriverObject->FastIoDispatch = &g_fastIoDispatch;

 // Registered callback routine for file system changes.
 status = IoRegisterFsRegistrationChange( DriverObject, FsFilterNotificationCallback );

 if( !NT_SUCCESS( status ) )
 {
  return status;
 }

 // Set driver unload routine ( debug purpose only ).
 DriverObject->DriverUnload = FsFilterUnload;

 // for H/W driver
 DriverObject->DriverExtension->AddDevice = AddDevice;

 // for PnP on H/W driver
 DriverObject->MajorFunction[IRP_MJ_PNP] = PnpDispatch;

 return STATUS_SUCCESS;
}





메모장