?? fspyctx.c
字號:
OUT PSPY_STREAM_CONTEXT *pRetContext
)
/*++
Routine Description:
Allocate and initialize a context structure including retrieving the name.
Arguments:
DeviceObject - Device to operate on
FileObject - The stream the context is being created for
LookupFlags - Flag telling how to do this create
pRetContext - Receives the created context
Return Value:
Status of the operation
--*/
{
PFILESPY_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
PSPY_STREAM_CONTEXT ctx;
ULONG contextSize;
PNAME_CONTROL fileName = NULL;
BOOLEAN cacheName;
NTSTATUS status;
PAGED_CODE();
ASSERT(IS_FILESPY_DEVICE_OBJECT(DeviceObject));
//
// Setup locals
//
*pRetContext = NULL;
//
// Get the filename string
//
status = NLAllocateNameControl( &fileName, &gFileSpyNameBufferLookasideList );
if (!NT_SUCCESS( status )) {
return status;
}
status = NLGetFullPathName( FileObject,
fileName,
&devExt->NLExtHeader,
LookupFlags | NLFL_USE_DOS_DEVICE_NAME,
&gFileSpyNameBufferLookasideList,
&cacheName );
if (!NT_SUCCESS( status )) {
NLFreeNameControl( fileName, &gFileSpyNameBufferLookasideList );
return status;
}
//
// Allocate the context structure with space for the name
// added to the end.
//
contextSize = sizeof(SPY_STREAM_CONTEXT);
contextSize += fileName->Name.Length;
ctx = ExAllocatePoolWithTag( NonPagedPool,
contextSize,
FILESPY_CONTEXT_TAG );
if (!ctx) {
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Init the context structure
//
RtlZeroMemory( ctx, sizeof(SPY_STREAM_CONTEXT) );
ctx->UseCount = 1;
//
// Insert the file name
//
RtlInitEmptyUnicodeString( &ctx->Name,
(PWCHAR)(ctx + 1),
(USHORT)(contextSize -
sizeof(SPY_STREAM_CONTEXT)) );
RtlCopyUnicodeString( &ctx->Name, &fileName->Name );
//
// If they don't want to keep this context, mark it temporary
//
if (!cacheName) {
SetFlag(ctx->Flags, CTXFL_Temporary);
INC_STATS(TotalContextTemporary);
}
//
// Return the object context
//
INC_STATS(TotalContextCreated);
*pRetContext = ctx;
//
// Cleanup the local NameControl structure
//
NLFreeNameControl( fileName, &gFileSpyNameBufferLookasideList );
return STATUS_SUCCESS;
}
NTSTATUS
SpyGetContext (
IN PDEVICE_OBJECT DeviceObject,
IN PFILE_OBJECT FileObject,
IN NAME_LOOKUP_FLAGS LookupFlags,
OUT PSPY_STREAM_CONTEXT *pRetContext
)
/*++
Routine Description:
This will see if a given context already exists. If not it will create
one and return it. Note: the return context pointer is NULL on a
failure.
This will also see if all contexts are to be temporary (global flag in
the extension). If so, a temporary context is always created. It also
sees if the found context is marked temporary (because it is being
renamed). If so, a temporary context is also created and returned.
Arguments:
DeviceObject - Device to operate on
FileObject - The stream the context is being looked up/created for
LookupFlags - State flags incase a context is created
pRetContext - Receives the found/created context
Return Value:
Status of the operation
--*/
{
PFILESPY_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
PSPY_STREAM_CONTEXT pContext;
PFSRTL_PER_STREAM_CONTEXT ctxCtrl;
NTSTATUS status;
BOOLEAN makeTemporary = FALSE;
ASSERT(IS_FILESPY_DEVICE_OBJECT(DeviceObject));
//
// Bump total search count
//
INC_STATS(TotalContextSearches);
//
// See if the all-contexts-temporary state is on. If not then do
// the normal search.
//
if (devExt->AllContextsTemporary != 0) {
//
// Mark that we want this context to be temporary
//
makeTemporary = TRUE;
} else {
//
// NOT-TEMPORARY
// Try and locate the context structure. We acquire the list lock
// so that we can guarantee that the context will not go away between
// the time when we find it and can increment the use count
//
SpyAcquireContextLockShared( devExt );
ctxCtrl = FsRtlLookupPerStreamContext( FsRtlGetPerStreamContextPointer(FileObject),
devExt,
NULL );
if (NULL != ctxCtrl) {
//
// A context was attached to the given stream
//
pContext = CONTAINING_RECORD( ctxCtrl,
SPY_STREAM_CONTEXT,
ContextCtrl );
ASSERT(pContext->Stream == FsRtlGetPerStreamContextPointer(FileObject));
ASSERT(FlagOn(pContext->Flags,CTXFL_InExtensionList));
ASSERT(!FlagOn(pContext->Flags,CTXFL_Temporary));
ASSERT(pContext->UseCount > 0);
//
// See if this is marked that we should not use it (happens when a
// file is being renamed).
//
if (FlagOn(pContext->Flags,CTXFL_DoNotUse)) {
//
// We should not use this context, unlock and set flag so we
// will create a temporary context.
//
SpyReleaseContextLock( devExt );
makeTemporary = TRUE;
} else {
//
// We want this context so bump the use count and release
// the lock
//
InterlockedIncrement( &pContext->UseCount );
SpyReleaseContextLock( devExt );
INC_STATS(TotalContextFound);
SPY_LOG_PRINT( SPYDEBUG_TRACE_CONTEXT_OPS,
("FileSpy!SpyGetContext: Found: (%p) Fl=%02x Use=%d \"%wZ\"\n",
pContext,
pContext->Flags,
pContext->UseCount,
&pContext->Name) );
//
// Return the found context
//
*pRetContext = pContext;
return STATUS_SUCCESS;
}
} else {
//
// We didn't find a context, release the lock
//
SpyReleaseContextLock( devExt );
}
}
//
// For whatever reason, we did not find a context.
// See if contexts are supported for this particular file. Note that
// NTFS does not presently support contexts on paging files.
//
if (!FsRtlSupportsPerStreamContexts(FileObject)) {
INC_STATS(TotalContextsNotSupported);
*pRetContext = NULL;
return STATUS_NOT_SUPPORTED;
}
//
// If we get here we need to create a context, do it
//
status = SpyCreateContext( DeviceObject,
FileObject,
LookupFlags,
&pContext );
if (!NT_SUCCESS( status )) {
*pRetContext = NULL;
return status;
}
//
// Mark context temporary (if requested)
//
if (makeTemporary) {
SetFlag(pContext->Flags,CTXFL_Temporary);
INC_STATS(TotalContextTemporary);
SPY_LOG_PRINT( SPYDEBUG_TRACE_CONTEXT_OPS,
("FileSpy!SpyGetContext: RenAllTmp: (%p) Fl=%02x Use=%d \"%wZ\"\n",
pContext,
pContext->Flags,
pContext->UseCount,
&pContext->Name) );
} else {
//
// Insert the context into the linked list. Note that the
// link routine will see if this entry has already been added to
// the list (could happen while we were building it). If so it
// will release the one we created and use the one it found in
// the list. It will return the new entry (if it was changed).
// The link routine properly handles temporary contexts.
//
SpyLinkContext( DeviceObject,
FileObject,
&pContext );
}
SPY_LOG_PRINT( SPYDEBUG_TRACE_CONTEXT_OPS,
("FileSpy!SrGetContext: Created%s (%p) Fl=%02x Use=%d \"%wZ\"\n",
(FlagOn(pContext->Flags,CTXFL_Temporary) ? "Tmp:" : ": "),
pContext,
pContext->Flags,
pContext->UseCount,
&pContext->Name) );
//
// Return the context
//
ASSERT(pContext->UseCount > 0);
*pRetContext = pContext;
return STATUS_SUCCESS;
}
PSPY_STREAM_CONTEXT
SpyFindExistingContext (
IN PDEVICE_OBJECT DeviceObject,
IN PFILE_OBJECT FileObject
)
/*++
Routine Description:
See if a context for the given stream already exists. If so it will
bump the reference count and return the context. If not, NULL
is returned.
Arguments:
DeviceObject - Device to operate on
FileObject - The stream the context is being looked up for
Return Value:
Returns the found context
--*/
{
PFILESPY_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
PSPY_STREAM_CONTEXT pContext;
PFSRTL_PER_STREAM_CONTEXT ctxCtrl;
PAGED_CODE();
ASSERT(IS_FILESPY_DEVICE_OBJECT(DeviceObject));
//
// Try and locate the context structure. We acquire the list lock
// so that we can guarantee that the context will not go away between
// the time when we find it and can increment the use count
//
INC_STATS(TotalContextSearches);
SpyAcquireContextLockShared( devExt );
ctxCtrl = FsRtlLookupPerStreamContext( FsRtlGetPerStreamContextPointer(FileObject),
devExt,
NULL );
if (NULL != ctxCtrl) {
//
// We found the entry, increment use count
//
pContext = CONTAINING_RECORD(ctxCtrl,SPY_STREAM_CONTEXT,ContextCtrl);
ASSERT(pContext->Stream == FsRtlGetPerStreamContextPointer(FileObject));
ASSERT(pContext->UseCount > 0);
InterlockedIncrement( &pContext->UseCount );
//
// Release the list lock
//
SpyReleaseContextLock( devExt );
INC_STATS(TotalContextFound);
SPY_LOG_PRINT( SPYDEBUG_TRACE_CONTEXT_OPS,
("FileSpy!SpyFindExistingContext:Found: (%p) Fl=%02x Use=%d \"%wZ\"\n",
pContext,
pContext->Flags,
pContext->UseCount,
&pContext->Name) );
} else {
//
// Release the list lock while we create the new context.
//
SpyReleaseContextLock( devExt );
pContext = NULL;
}
return pContext;
}
VOID
SpyReleaseContext (
IN PSPY_STREAM_CONTEXT pContext
)
/*++
Routine Description:
Decrement the use count for the given context. If it goes to zero, free it
Arguments:
pContext - The context to operate on
Return Value:
None.
--*/
{
PAGED_CODE();
SPY_LOG_PRINT( SPYDEBUG_TRACE_DETAILED_CONTEXT_OPS,
("FileSpy!SpyReleaseContext: Release (%p) Fl=%02x Use=%d \"%wZ\"\n",
pContext,
pContext->Flags,
pContext->UseCount,
&pContext->Name) );
//
// Decrement USE count, free context if zero
//
ASSERT(pContext->UseCount > 0);
if (InterlockedDecrement( &pContext->UseCount ) <= 0) {
ASSERT(!FlagOn(pContext->Flags,CTXFL_InExtensionList));
//
// Free the memory
//
SPY_LOG_PRINT( SPYDEBUG_TRACE_CONTEXT_OPS,
("FileSpy!SpyReleaseContext: Freeing (%p) Fl=%02x Use=%d \"%wZ\"\n",
pContext,
pContext->Flags,
pContext->UseCount,
&pContext->Name) );
INC_STATS(TotalContextDeferredFrees);
SpyFreeContext( pContext );
}
}
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -