Пример #1
0
VOID
NcSetNextEntryOffset (
    _Inout_ PVOID Buffer,
    _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets,
    _In_ BOOLEAN ForceLast
    )
/*++

Routine Description:

    Sets the Next Entry Offset to Value.

Arguments:

    Buffer - Pointer to the start of this entry.

    Offsets - Offsets structure for the information class.

    ForceLast - If true, the size of the next entry is set to zero.
                Otherwise, the size will be set to the size of the 
                information class + the file name's length.

--*/
{
    //
    //  Get pointer to NextEntryOffset value.
    //
    
    PULONG NextEntry = Add2Ptr( Buffer, Offsets->NextEntryOffsetDist );
    PAGED_CODE();
 
    //
    //  Get length of name.
    //
    
    if (ForceLast) {

        //
        //  This is the last entry, so we need to make sure 0 is in the 
        //  next entry offset.
        //

        *NextEntry = 0;

    } else {

        //
        //  Next entry offset is the distance to the name
        //  plus the length of the name.
        //
        
        ULONG NameLength = NcGetFileNameLength( Buffer, Offsets );
        *NextEntry = Offsets->FileNameDist + NameLength;
    }
}
Пример #2
0
ULONG
NcGetEntrySize (
    _In_ CONST PVOID Buffer,
    _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets
    )
/*++

Routine Description:

    Returns the size of this entry in bytes.

Arguments:

    Buffer - Pointer to the start of the entry.

    Offsets - Offsets structure for the information class.

Return Value:

    Returns the size of this entry in bytes.

--*/
{
    ULONG EntrySize = NcGetNextEntryOffset(Buffer, Offsets);
    PAGED_CODE();

    if (EntrySize == 0) {

        //
        //  We are at last entry, so we need to calculate this ourselves.
        //

        EntrySize = NcGetFileNameLength( Buffer, Offsets );
        EntrySize += Offsets->FileNameDist;
    }

    return EntrySize;
}
Пример #3
0
PNC_CACHE_ENTRY
NcDirEnumSelectNextEntry( 
    _Inout_ PNC_DIR_QRY_CONTEXT Context, 
    _In_ PDIRECTORY_CONTROL_OFFSETS Offsets,
    _In_ BOOLEAN IgnoreCase
    )
/*++

Routine Description:

    This routine determines whether the cached entry (returned from the
    filesystem) should be returned now or whether the injected entry (as a
    result of our mapping) should be returned now.

Arguments:

    Context - The enumeration context of this handle.

    Offsets - Information describing the offsets for this enumeration class.

    IgnoreCase - TRUE if we are case insensitive, FALSE if case sensitive.

Return Value:

    A pointer to the entry we should return, or NULL if there is nothing
    remaining to return.

--*/
{
    PNC_CACHE_ENTRY NextEntry;
    UNICODE_STRING CacheString;
    UNICODE_STRING InsertString;
    PVOID CacheEntry;
    PVOID InjectEntry;

    PAGED_CODE();

    //
    //  Figure out which name comes first
    //

    if ((Context->Cache.Buffer == NULL) && 
        (Context->InjectionEntry.Buffer == NULL)) {

        //
        //  There are no names left, return STATUS_NO_MORE_FILES
        //

        NextEntry = NULL;

    } else if (Context->Cache.Buffer == NULL) {

        //
        //  The cache is empty, so inject.
        //

        NextEntry = &Context->InjectionEntry;

    } else if (Context->InjectionEntry.Buffer == NULL) {

        //
        //  The injection entry is empty, drain the cache.
        //

        NextEntry = &Context->Cache;

    } else {

        //
        //  We have to seek in the entry buffer to the current entry within the buffer.
        //

        CacheEntry = Add2Ptr( Context->Cache.Buffer, Context->Cache.CurrentOffset );
        InjectEntry = Add2Ptr( Context->InjectionEntry.Buffer, Context->InjectionEntry.CurrentOffset );

        //
        //  Find names within the entries.
        //

        CacheString.Buffer = NcGetFileName( CacheEntry, Offsets );
        CacheString.Length = (USHORT) NcGetFileNameLength( CacheEntry, Offsets );
        CacheString.MaximumLength = CacheString.Length;

        InsertString.Buffer = NcGetFileName( InjectEntry, Offsets );
        InsertString.Length = (USHORT) NcGetFileNameLength( InjectEntry, Offsets );
        InsertString.MaximumLength = InsertString.Length;

        //
        //  Compare the names
        //

        if (RtlCompareUnicodeString( &CacheString,
                                     &InsertString,
                                     IgnoreCase ) < 0) {

            //
            //  Cache string comes first
            //

            NextEntry = &Context->Cache;

        } else {

            //
            //  insert string comes first
            //

            NextEntry = &Context->InjectionEntry;
        }
    }
    return NextEntry;
}
Пример #4
0
BOOLEAN
NcSkipName (
    _In_ PDIRECTORY_CONTROL_OFFSETS Offsets,
    _In_ PNC_DIR_QRY_CONTEXT Context, 
    _In_ NC_PATH_OVERLAP RealOverlap,
    _In_ PNC_MAPPING Mapping,
    _In_ BOOLEAN IgnoreCase
    )
/*++

Routine Description:

    Determines if the next entry is for the real mapping.  If it is, we want
    to "skip" returning this entry and proceed to the next.

Arguments:

    Offsets - Offset information for this enumeration class.

    Context - Pointer to directory query context (on the stream handle.)
        This is used to obtain the entry we are contemplating returning.

    RealOverlap - Relationship of the object that enumeration is being
        requested on to the real mapping.  This routine will only skip
        entries if we are enumerating the parent of the real mapping.

Return Value:

    TRUE if this entry should be skipped/suppressed; FALSE if it should be
    returned to the user.

--*/
{
    BOOLEAN Result = FALSE;
    PVOID CacheEntry;
    UNICODE_STRING CacheString;
    PUNICODE_STRING IgnoreString = &Mapping->RealMapping.LongNamePath.FinalComponentName;
    ULONG ElementSize;
    BOOLEAN LastElement;

    PAGED_CODE();

    if (RealOverlap.Parent) {

        //
        //  We have to check for a match.
        //

        CacheEntry = Add2Ptr( Context->Cache.Buffer, Context->Cache.CurrentOffset);
        ElementSize = NcGetEntrySize( CacheEntry, Offsets );
        LastElement = (BOOLEAN)(NcGetNextEntryOffset( CacheEntry, Offsets ) == 0);

        CacheString.Buffer = NcGetFileName( CacheEntry, Offsets );
        CacheString.Length = (USHORT) NcGetFileNameLength( CacheEntry, Offsets );
        CacheString.MaximumLength = CacheString.Length;


        if (RtlCompareUnicodeString( &CacheString, 
                                     IgnoreString,
                                     IgnoreCase ) == 0) {

            //
            //  We need to ignore this name.
            //

            Result = TRUE;

            //
            //  skip
            //

            if (LastElement) {

                //
                //  This was the last element in the entry, so we should clean the entry.
                //

                ExFreePoolWithTag(Context->Cache.Buffer, NC_DIR_QRY_CACHE_TAG);
                Context->Cache.Buffer = NULL;
                Context->Cache.CurrentOffset = 0;

            } else {

                //
                //  Entry has more elements, update offset counter.
                //

                Context->Cache.CurrentOffset += ElementSize;
            }
        } 
    }

    return Result;
}