📄 irp_mj_directory.c
字号:
/*
* Clandestine File System Driver
* Copyright (C) 2005 Jason Todd
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*
* Dispatch/Completion functions for IRP_MJ_DIRECTORY_CONTROL
*
*
* REFERENCE for this code :
* swapbuffers.c - DDK
* OSR ListServer Discussion Groups - http://www.osronline.com/page.cfm?name=search
*
*/
#include "IRP_MJ_directory.h"
#include "CompareFilters.h"
#include "base.h"
#if FILTER_IRP_MJ_DIRECTORY_CONTROL
/*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= **
*
* This is equal to a dispatch function in the legacy model
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= **
*/
FLT_PREOP_CALLBACK_STATUS
PreDirectoryControl( IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
OUT PVOID *CompletionContext )
{
return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
/*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= **
*
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= **
*/
FLT_POSTOP_CALLBACK_STATUS
PostDirectoryControl( IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
IN PVOID CompletionContext,
IN FLT_POST_OPERATION_FLAGS Flags )
{
PVOID DirectoryBuffer = NULL;
FLT_POSTOP_CALLBACK_STATUS ReturnStatus = FLT_POSTOP_FINISHED_PROCESSING;
// If we are draining we have no reason to process. This flag could have been set
// and we have been called before a lower filter driver of the filesystem has completed. So we have
// no real way to know if our data is correct/valid/or even there, and we are unloading anyways so
// just exit with no furthur processing.
// NOTE When Draining* DDK : "Data parameter points to a copy of the original callback
// data structure for the operation, not the original callback data structure"
if ( FlagOn( FLTFL_POST_OPERATION_DRAINING, Flags ) )
{
DBG_PRINT( DbgOutput, DBG_IRP_MJ_DIRECTORY, (PRINT_TAG_DIRECTORY "POST OPERATION DRAINING - Exiting fPostOperationDirectoryControl()\n") );
return ReturnStatus;
}
// If the operation failed or there is no data we have no reason to continue so exit
// *NOTE* Seem to see this spam alot, need to look into why this calls alot
if ( !NT_SUCCESS( Data->IoStatus.Status ) || ( Data->IoStatus.Information == 0 ) )
{
#if DBG
if ( !NT_SUCCESS( Data->IoStatus.Status ) )
{
DBG_PRINT( DbgOutput, DBG_IRP_MJ_DIRECTORY, (PRINT_TAG_DIRECTORY "IoStatus.Status = 0x%x - Exiting fPostOperationDirectoryControl()\n",Data->IoStatus.Status ) );
}
if ( ( Data->IoStatus.Information == 0 ) )
{
DBG_PRINT( DbgOutput, DBG_IRP_MJ_DIRECTORY, (PRINT_TAG_DIRECTORY "Information = [%d] - Exiting fPostOperationDirectoryControl()\n",Data->IoStatus.Information ) );
}
#endif
return ReturnStatus;
}
// We attempt to get to a safe IRQL for processing. If we can not then we just fail and exit
// without and processing. Odds are we are going to have a user buffer and need to call this
// anyways, odds also favor that our processing we want to do cannot be done at DPC
if ( !FltDoCompletionProcessingWhenSafe( Data, // Data
FltObjects, // FltObjects
CompletionContext, // CompletionContext
Flags, // Flags
PostDirectoryControlSafe,// SafePostCallback
&ReturnStatus ) ) // RetPostOperationsStatus
{
// If cannot get to a safe IRQL we just fail
Data->IoStatus.Status = STATUS_UNSUCCESSFUL;
Data->IoStatus.Information = 0;
}
return ReturnStatus;
}
/*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= **
*
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= **
*/
FLT_POSTOP_CALLBACK_STATUS
PostDirectoryControlSafe ( IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
IN PVOID CompletionContext,
IN FLT_POST_OPERATION_FLAGS Flags )
{
PVOID SafeBuffer;
NTSTATUS Status;
NTSTATUS ReturnStatus = FLT_POSTOP_FINISHED_PROCESSING;
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( CompletionContext );
UNREFERENCED_PARAMETER( Flags );
// Lock the buffer so we can access it safely
Status = FltLockUserBuffer( Data );
if ( !NT_SUCCESS( Status ) )
{
// If we can't lock the buffer, fail the operation
Data->IoStatus.Status = Status;
Data->IoStatus.Information = 0;
}
else
{
// Get a system address for this buffer.
SafeBuffer = MmGetSystemAddressForMdlSafe( Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress,
NormalPagePriority );
if ( SafeBuffer == NULL )
{
// If we couldn not get a SYSTEM buffer address fail and exit
Data->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Data->IoStatus.Information = 0;
}
else
{
// Determine which IRP_MN_XXX we have and direct control accordingly
if ( Data->Iopb->MinorFunction == IRP_MN_QUERY_DIRECTORY )
{
// Multiplex which FileInformationClass type we are going to be processing and direct it
// to the proper processing function
switch ( Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass )
{
case FileBothDirectoryInformation:
{
ReturnStatus = ProcessFileBothDirectoryInformation( Data, SafeBuffer );
break;
}
case FileDirectoryInformation:
{
ProcessFileDirectoryInformation( Data );
break;
}
case FileFullDirectoryInformation:
{
ProcessFileFullDirectoryInformation( Data );
break;
}
case FileIdBothDirectoryInformation:
{
ProcessFileIdBothDirectoryInformation( Data );
break;
}
case FileIdFullDirectoryInformation:
{
ProcessFileIdFullDirectoryInformation( Data );
break;
}
case FileNamesInformation:
{
ReturnStatus = ProcessFileNamesInformation( FltObjects, Data, SafeBuffer );
break;
}
case FileObjectIdInformation:
{
ProcessFileObjectIdInformation( Data );
break;
}
case FileReparsePointInformation:
{
ProcessFileReparsePointInformation( Data );
break;
}
default : // Default Security catch
{
KdPrint( (PRINT_TAG "BAD MOJO") );
break;
}
} // End switch ( iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass )
}
else if ( Data->Iopb->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY )
{
ProcessMNNotifyChangeDirectory( Data );
}
else // Default Security catch
{
DBG_PRINT( DbgOutput, DBG_IRP_MJ_DIRECTORY, (PRINT_TAG_DIRECTORY "BAD MOJO\n") );
}
} // End if ( SafeBuffer == NULL)
} // End if (!NT_SUCCESS(status))
return ReturnStatus;
}
/*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= **
*
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= **
*/
FLT_POSTOP_CALLBACK_STATUS
ProcessMNNotifyChangeDirectory( IN OUT PFLT_CALLBACK_DATA Data )
{
//FltNotifyFilterChangeDirectory()
/*
FILE_NOTIFY_CHANGE_FILE_NAME A file has been added, deleted, or renamed in this directory.
FILE_NOTIFY_CHANGE_DIR_NAME A subdirectory has been created, removed, or renamed.
FILE_NOTIFY_CHANGE_NAME This directory's name has changed.
FILE_NOTIFY_CHANGE_ATTRIBUTES The value of an attribute of this file, such as last access time, has changed.
FILE_NOTIFY_CHANGE_SIZE This file's size has changed.
FILE_NOTIFY_CHANGE_LAST_WRITE This file's last modification time has changed.
FILE_NOTIFY_CHANGE_LAST_ACCESS This file's last access time has changed.
FILE_NOTIFY_CHANGE_CREATION This file's creation time has changed.
FILE_NOTIFY_CHANGE_EA This file's extended attributes have been modified.
FILE_NOTIFY_CHANGE_SECURITY This file's security information has changed.
FILE_NOTIFY_CHANGE_STREAM_NAME A file stream has been added, deleted, or renamed in this directory.
FILE_NOTIFY_CHANGE_STREAM_SIZE This file stream's size has changed.
FILE_NOTIFY_CHANGE_STREAM_WRITE This file stream's data has changed.
*/
return FLT_POSTOP_FINISHED_PROCESSING;
}
/*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= **
*
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= **
*/
FLT_POSTOP_CALLBACK_STATUS
ProcessFileBothDirectoryInformation( IN OUT PFLT_CALLBACK_DATA Data,
IN OUT PVOID SafeBuffer )
{
/*
** Other possible flag settings in bitmask iopb->OperationFlags **
SL_INDEX_SPECIFIED - Used for IRP_MJ_DIRECTORY_CONTROL, IRP_MJ_QUERY_EA, and IRP_MJ_SET_QUOTA.
If this flag is set, the scan for directory, quota, or extended-attribute information should
begin at the entry in the list whose index is specified.
SL_OVERRIDE_VERIFY_VOLUME - Used for IRP_MJ_DIRECTORY_CONTROL, IRP_MJ_READ, and IRP_MJ_WRITE.
If this flag is set, the I/O operation should be performed even if the DO_VERIFY_VOLUME flag
is set on the volume's device object
SL_RESTART_SCAN - Used for IRP_MJ_DIRECTORY_CONTROL, IRP_MJ_QUERY_EA, and IRP_MJ_SET_QUOTA.
If this flag is set, the scan for directory, quota, or extended-attribute information should
begin at the first entry in the directory or list. Otherwise, the scan should be resumed from the previous scan.
SL_WATCH_TREE - Used for IRP_MJ_DIRECTORY_CONTROL. If this flag is set, all subdirectories of this directory
should also be watched. Otherwise, only the directory itself is to be watched.
SL_RETURN_SINGLE_ENTRY Return only the first entry that is found.
*/
PFILE_BOTH_DIR_INFORMATION DirectoryBuffer = NULL;
PFILE_BOTH_DIR_INFORMATION NextDirectoryBuffer = NULL;
PVOID TemporaryBuffer = NULL;
ULONG BufferPosition = 0;
ULONG ModifiedLength = 0;
//////////////////////
PFLT_FILE_NAME_INFORMATION nameInfo;
NTSTATUS Status;
// Parse out our info for matching volume, path, share, and stream
Status = FltGetFileNameInformation( Data,
FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT,
&nameInfo );
/////////////////////////////////////////
/*
KdPrint( (PRINT_TAG "Query Name (%wZ) DirectoryBuffer Size [%d]",Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileName,
Data->Iopb->Parameters.DirectoryControl.QueryDirectory.Length) );
KdPrint( (PRINT_TAG "IOStatus Info %d\n", Data->IoStatus.Information) );
*/
// Overlay our buffer onto a structure for processing
DirectoryBuffer = ( PFILE_BOTH_DIR_INFORMATION ) SafeBuffer;
do {
// Incrament our buffer position to match the next entry
BufferPosition += DirectoryBuffer->NextEntryOffset;
// Check to see if this file matches our template
#if FILTER_BY_NAME
DBG_PRINT( DbgOutput, DBG_IRP_MJ_DIRECTORY, (PRINT_TAG_DIRECTORY "CompareFileName()\n") );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -