PART 2
Then I paste Query Handling:
FLT_PREOP_CALLBACK_STATUS
MyQueryPreOp (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__deref_out_opt PVOID *CompletionContext
)
{
NTSTATUS status;
FLT_PREOP_CALLBACK_STATUS FltOpStatus =
FLT_PREOP_SUCCESS_NO_CALLBACK ;
PMy_STREAM_CONTEXT pStreamCtx = NULL;
PFLT_CONTEXT pFltContext = NULL;
BOOLEAN bStreamCtxCreated = FALSE;
PUCHAR pBuffer = NULL;
ULONG SessionId = 0; //
0 is an Invalid session Id
PWCHAR oNamePointer = NULL;
FLT_PARAMETERS Params =
Data->Iopb->Parameters;
BOOLEAN bIsFastIO = FALSE;
ASSERT(Data->Iopb->MajorFunction == IRP_MJ_QUERY_INFORMATION);
if (FltObjects->FileObject == NULL) {
MyDrvTrace(My_TRACELEVEL_HIGH, (“FltObjects->FileObject is
NULL\n”));
goto Exit;
}
bIsFastIO = FLT_IS_FASTIO_OPERATION(Data);
// Now we try to locate a stream context for this Read Operation. A
stream context
// should have been allocated for a File of our interest in Create
Post-Op
status = MyFindOrCreateStreamContext(Data,
FALSE, // do
not create if one does not exist
&pStreamCtx,
&bStreamCtxCreated);
if (!NT_SUCCESS( status )) {
// This failure will most likely be because stream contexts are
not supported
// on the object we are trying to assign a context to or the
object is being
// deleted
MyDrvTrace(My_TRACELEVEL_HIGH,
(“Got %ws, Failed to find stream context (Data = 0x%p,
FileObject = 0x%p), Bypassing…\n”,
pQueryInfoClasses[Params.QueryFileInformation.FileInformationClass],
Data,
FltObjects->FileObject) );
goto Exit; // Fall back to Pass
through Mode
}
// Extract the File Name form the Stream Context
// Operation needs to be done under Lock
pStreamCtx->Resource.SoAcquireObject();
oNamePointer = (PWCHAR)MyMmAllocateMemory(NonPagedPool,
pStreamCtx->FileName.Length + sizeof(WCHAR),
MyLAT_QUERYOP_POOL_TAG);
if(oNamePointer == NULL) {
MyDrvTrace(My_TRACELEVEL_HIGH,(“Allocation Failed\n”));
Data->IoStatus.Status = STATUS_UNSUCCESSFUL;
Data->IoStatus.Information = 0;
FltSetCallbackDataDirty( Data );
pStreamCtx->Resource.SoReleaseObject();
goto Exit;
}
MyMmZeroMemory(oNamePointer, pStreamCtx->FileName.Length +
sizeof(WCHAR));
MyMmCopyMemory(oNamePointer, pStreamCtx->FileName.Buffer,
pStreamCtx->FileName.Length);
pStreamCtx->Resource.SoReleaseObject();
// Okay so we got a name, lets get the session for it
// At this place I have some code to test whether this file name
interests me or not, which is removed in the posting
if(bIsFastIO){
MyDrvTrace(My_TRACELEVEL_LOW, (“Disabling FastIO for File : %ws\n”,
oNamePointer));
FltOpStatus = FLT_PREOP_DISALLOW_FASTIO;
goto Exit;
}
LARGE_INTEGER EOFParams;
MyMmZeroMemory(&EOFParams, sizeof(LARGE_INTEGER));
g_MyData.GetEmulationSize(oNamePointer, &EOFParams);
if(EOFParams.QuadPart == 0 ){ // This would mean that the
Session doesn’t need any emulation
MyDrvTrace(My_TRACELEVEL_HIGH,
(“Got %ws for File : %ws, but size emulation has been
disabled. Bypassing…\n”,
pQueryInfoClasses[Params.QueryFileInformation.FileInformationClass],
oNamePointer));
goto Exit;
}
switch (Params.QueryFileInformation.FileInformationClass) {
case FileStandardInformation:
case FileAllInformation:
case FileNetworkOpenInformation: {
// We will partially fulfill this, in Post-Op, as the rest of
the Info needs to be fetched from the FS
MyDrvTrace(My_TRACELEVEL_HIGH,
(“Got %ws for File : %ws, we will Fulfill this
partially in Post-Op, rest will be done by FS\n”,
pQueryInfoClasses[Params.QueryFileInformation.FileInformationClass],
oNamePointer));
// So lets set the Post-Op callback trigger
FltOpStatus = FLT_PREOP_SUCCESS_WITH_CALLBACK;
// and a completion context for us to work with…
size_t NameLen = wcslen(oNamePointer) * sizeof(WCHAR); //
The size of the string in Bytes
size_t Len = sizeof(QUERY_CTX) +
// The size of the struct
sizeof(WCHAR) +
// space for NULL character
NameLen;
*CompletionContext = MyMmAllocateMemory(NonPagedPool,
Len,
MyLAT_QUERYOP_POOL_TAG);
if(*CompletionContext == NULL){
Data->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Data->IoStatus.Information = 0;
FltSetCallbackDataDirty( Data );
// Fail it by completing it…
FltOpStatus = FLT_PREOP_COMPLETE;
}
FltGetInstanceContext(FltObjects->Instance,
&pFltContext);
MyMmZeroMemory(*CompletionContext,
Len);
((PQUERY_CTX)(*CompletionContext))->EOFMarker = EOFParams;
if(pFltContext){
((PQUERY_CTX)(*CompletionContext))->AllocationSize.QuadPart
= ROUND_UP(EOFParams.QuadPart,
((PMy_INSTANCE_CONTEXT)pFltContext)->VolInfo.FSClusterSize);
}
MyMmCopyMemory(((PQUERY_CTX)(*CompletionContext))->Name,
oNamePointer,
NameLen);
break;
}
case FileEndOfFileInformation:{
// In our case the EOF would be the size of total File
Emulation
PFILE_END_OF_FILE_INFORMATION pEOFInfo =
(PFILE_END_OF_FILE_INFORMATION)Params.QueryFileInformation.InfoBuffer;
pEOFInfo->EndOfFile = EOFParams;
MyDrvTrace(My_TRACELEVEL_HIGH,
(“Got FileEndOfFileInformation for File : %ws.
EndOfFile = 0x%I64x\n”,
oNamePointer,
pEOFInfo->EndOfFile.QuadPart));
// We don’t want the FS to handle this so we will halt
processing and return from here
Data->IoStatus.Status = STATUS_SUCCESS;
Data->IoStatus.Information = 0;
FltSetCallbackDataDirty( Data );
FltOpStatus = FLT_PREOP_COMPLETE;
break;
}
case FilePositionInformation: {
PFILE_OBJECT pFO = FltObjects->FileObject;
PFILE_POSITION_INFORMATION pFPosInfo =
(PFILE_POSITION_INFORMATION)Params.QueryFileInformation.InfoBuffer;
// In MyRead We will be setting the Read Offset + Length as
FO.CurrentByteOffset, so just return that…
MyMmCopyMemory(&(pFPosInfo->CurrentByteOffset),
&pFO->CurrentByteOffset,
sizeof(LARGE_INTEGER));
MyDrvTrace(My_TRACELEVEL_MED,
(“Got FilePositionInformation for File : %ws.
CurrentByteOffset.Quadpart = 0x%I64x\n”,
oNamePointer,
pFO->CurrentByteOffset.QuadPart));
// We don’t want the FS to handle this so we will halt
processing and return from here
Data->IoStatus.Status = STATUS_SUCCESS;
Data->IoStatus.Information = 0;
FltSetCallbackDataDirty( Data );
FltOpStatus = FLT_PREOP_COMPLETE;
break;
}
default: {
MyDrvTrace(My_TRACELEVEL_HIGH,
(“Got %ws for File : %ws\n”,
pQueryInfoClasses[Params.QueryFileInformation.FileInformationClass],
oNamePointer));
break;
}
} //switch
(Data->Iopb->Parameters.QueryFileInformation.FileInformationClass)
Exit:
if(oNamePointer){
MyMmFreeMemory(oNamePointer, MyLAT_QUERYOP_POOL_TAG);
}
if (pStreamCtx != NULL) {
FltReleaseContext( pStreamCtx );
}
if (pFltContext != NULL) {
FltReleaseContext( pFltContext );
}
MyDrvTrace(My_TRACELEVEL_LOW, (“Exiting…\n”));
return FltOpStatus;
}
FLT_POSTOP_CALLBACK_STATUS
MyQueryPostOp (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__in PVOID CompletionContext,
__in FLT_POST_OPERATION_FLAGS Flags
)
{
FLT_PARAMETERS Params = Data->Iopb->Parameters;
if(CompletionContext == NULL){
MyDrvTrace(My_TRACELEVEL_HIGH, (“Invalid Parameter, Got NULL in
CompletionContext…\n”));
goto Exit;
}
PWCHAR oNamePointer = (PWCHAR)((PQUERY_CTX)(CompletionContext))->Name;
// Okay, so we will be only called when we have triggered this in Pre-Op
// so it would be for one of the Classes of Info which we need to swoof
and
// change some data, keeping the other parts intact, i.e, what ever the
FS
// returned for those fields…
LARGE_INTEGER MyEOF;
LARGE_INTEGER AllocationSize;
MyMmZeroMemory(&MyEOF, sizeof(LARGE_INTEGER));
MyMmZeroMemory(&AllocationSize, sizeof(LARGE_INTEGER));
MyEOF = ((PQUERY_CTX)(CompletionContext))->EOFMarker;
// we only get a call back for Post is Emulation is enabled
AllocationSize = ((PQUERY_CTX)(CompletionContext))->AllocationSize;
// we only get a call back for Post is Emulation is enabled
switch (Params.QueryFileInformation.FileInformationClass) {
case FileStandardInformation:{
// For standard Info, we need to change the EOF location to our
own…
PFILE_STANDARD_INFORMATION pStandardInfo =
(PFILE_STANDARD_INFORMATION)Params.QueryFileInformation.InfoBuffer;
pStandardInfo->EndOfFile = MyEOF;
pStandardInfo->AllocationSize = AllocationSize;
MyDrvTrace(My_TRACELEVEL_HIGH,
(“Got %ws for File : %ws. EndOfFile = 0x%I64x,
AllocSize = 0x%I64x\n”,
pQueryInfoClasses[Params.QueryFileInformation.FileInformationClass],
oNamePointer,
pStandardInfo->EndOfFile.QuadPart,
pStandardInfo->AllocationSize.QuadPart));
break;
}
case FileAllInformation:{
// For All Info, we need to change the following :
// 1. StandardInformation.EndOfFile
// 2. PositionInformation.CurrentByteOffset
PFILE_ALL_INFORMATION pAllInfo =
(PFILE_ALL_INFORMATION)Params.QueryFileInformation.InfoBuffer;
pAllInfo->StandardInformation.EndOfFile = MyEOF;
pAllInfo->StandardInformation.AllocationSize = AllocationSize;
PFILE_OBJECT pFO = FltObjects->FileObject;
pAllInfo->PositionInformation.CurrentByteOffset =
pFO->CurrentByteOffset;
MyDrvTrace(My_TRACELEVEL_HIGH,
(“Got %ws for File : %ws. Set EndOfFile = 0x%I64x,
AllocSize = 0x%I64x, CurrentByteOffset = 0x%I64x\n”,
pQueryInfoClasses[Params.QueryFileInformation.FileInformationClass],
oNamePointer,
pAllInfo->StandardInformation.EndOfFile.QuadPart,
pAllInfo->StandardInformation.AllocationSize.QuadPart,
pAllInfo->PositionInformation.CurrentByteOffset));
break;
}
case FileNetworkOpenInformation:{
// For Network Open Info, we need to change the EOF location to
our own…
PFILE_NETWORK_OPEN_INFORMATION pNwopenInfo =
(PFILE_NETWORK_OPEN_INFORMATION)Params.QueryFileInformation.InfoBuffer;
pNwopenInfo->EndOfFile = MyEOF;
pNwopenInfo->AllocationSize = AllocationSize;
MyDrvTrace(My_TRACELEVEL_HIGH,
(“Got %ws for File : %ws. EndOfFile = 0x%I64x,
AllocSize = 0x%I64x\n”,
pQueryInfoClasses[Params.QueryFileInformation.FileInformationClass],
oNamePointer,
pNwopenInfo->EndOfFile.QuadPart,
pNwopenInfo->AllocationSize.QuadPart));
break;
}
default: {
MyDrvTrace(My_TRACELEVEL_HIGH,
(“Got %ws for File : %ws\n”,
pQueryInfoClasses[Params.QueryFileInformation.FileInformationClass],
oNamePointer));
break;
}
}
Exit:
if(CompletionContext){
MyMmFreeMemory(CompletionContext, MyLAT_QUERYOP_POOL_TAG);
}
return FLT_POSTOP_FINISHED_PROCESSING;
}
next i paste Nw Query Open
FLT_PREOP_CALLBACK_STATUS
myNwQueryOpenPreOp (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__deref_out_opt PVOID *CompletionContext
)
{
UNREFERENCED_PARAMETER (Data);
UNREFERENCED_PARAMETER (FltObjects);
UNREFERENCED_PARAMETER (CompletionContext);
return FLT_PREOP_DISALLOW_FASTIO;
}