294 lines
7.6 KiB
C
294 lines
7.6 KiB
C
/*++
|
|
|
|
Copyright (c) 2000-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
fsrtl.c
|
|
|
|
Abstract:
|
|
|
|
This module implements shared file system driver routines.
|
|
|
|
--*/
|
|
|
|
#include "iop.h"
|
|
|
|
BOOLEAN
|
|
IopCopyTemplateFileName(
|
|
IN POBJECT_STRING TargetTemplateFileName,
|
|
OUT POBJECT_STRING SourceTemplateFileName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine copies the template file name from the source to the
|
|
destination and validates that the template string is valid (for example,
|
|
an asterisk must be followed by the end of the string or a period).
|
|
|
|
Arguments:
|
|
|
|
TargetTemplateFileName - Specifies the target template file name.
|
|
|
|
SourceTemplateFileName - Specifies the source template file name.
|
|
|
|
Return Value:
|
|
|
|
Returns TRUE if the source template file name is valid, else FALSE.
|
|
|
|
--*/
|
|
{
|
|
BOOLEAN SeenAsterisk;
|
|
POSTR SourceTemplateFileNameCurrent;
|
|
POSTR SourceTemplateFileNameEnd;
|
|
POSTR TargetTemplateFileNameCurrent;
|
|
OCHAR Char;
|
|
|
|
SeenAsterisk = FALSE;
|
|
|
|
SourceTemplateFileNameCurrent = SourceTemplateFileName->Buffer;
|
|
SourceTemplateFileNameEnd = (POSTR)((PUCHAR)SourceTemplateFileNameCurrent +
|
|
SourceTemplateFileName->Length);
|
|
TargetTemplateFileNameCurrent = TargetTemplateFileName->Buffer;
|
|
|
|
while (SourceTemplateFileNameCurrent < SourceTemplateFileNameEnd) {
|
|
|
|
Char = *SourceTemplateFileNameCurrent++;
|
|
|
|
//
|
|
// Force an asterisk to be followed by a period.
|
|
//
|
|
|
|
if (SeenAsterisk) {
|
|
|
|
if (Char != OTEXT('.')) {
|
|
return FALSE;
|
|
}
|
|
|
|
SeenAsterisk = FALSE;
|
|
}
|
|
|
|
if (Char == OTEXT('*')) {
|
|
SeenAsterisk = TRUE;
|
|
} else if (Char >= OTEXT('a') && Char <= OTEXT('z')) {
|
|
Char = (OCHAR)(Char - (OTEXT('a') - OTEXT('A')));
|
|
}
|
|
|
|
*TargetTemplateFileNameCurrent++ = Char;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
NTSTATUS
|
|
IoCreateDirectoryEnumContext(
|
|
IN POBJECT_STRING TemplateFileName,
|
|
OUT PDIRECTORY_ENUM_CONTEXT *ReturnedDirectoryEnumContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine allocates and prepares a directory enumeration context given
|
|
the supplied template file name. The template file name is also validated.
|
|
|
|
Arguments:
|
|
|
|
TemplateFileName - Specifies the template file name for the enumeration.
|
|
|
|
ReturnedDirectoryEnumContext - Specifies the location to receive the
|
|
allocated directory enumeration context.
|
|
|
|
Return Value:
|
|
|
|
Status of operation.
|
|
|
|
--*/
|
|
{
|
|
ULONG TemplateFileNameLength;
|
|
PDIRECTORY_ENUM_CONTEXT DirectoryEnumContext;
|
|
|
|
if ((TemplateFileName == NULL) || (TemplateFileName->Length == 0) ||
|
|
(TemplateFileName->Length == sizeof(OCHAR)) &&
|
|
(TemplateFileName->Buffer[0] == OTEXT('*'))) {
|
|
|
|
//
|
|
// No template name was specified or else "*" was specified, so we'll
|
|
// match all file names.
|
|
//
|
|
|
|
TemplateFileNameLength = 0;
|
|
|
|
} else {
|
|
TemplateFileNameLength = TemplateFileName->Length;
|
|
}
|
|
|
|
//
|
|
// Allocate and zero initialize the directory enumeration context.
|
|
//
|
|
|
|
DirectoryEnumContext = (PDIRECTORY_ENUM_CONTEXT)ExAllocatePoolWithTag(
|
|
sizeof(DIRECTORY_ENUM_CONTEXT) + TemplateFileNameLength, 'eDoI');
|
|
|
|
if (DirectoryEnumContext == NULL) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(DirectoryEnumContext, sizeof(DIRECTORY_ENUM_CONTEXT));
|
|
|
|
if (TemplateFileNameLength != 0) {
|
|
|
|
//
|
|
// A template name was specified. Convert the name to uppercase and
|
|
// store it in the directory enumeration context.
|
|
//
|
|
|
|
DirectoryEnumContext->TemplateFileName.Length =
|
|
(USHORT)TemplateFileNameLength;
|
|
DirectoryEnumContext->TemplateFileName.MaximumLength =
|
|
(USHORT)TemplateFileNameLength;
|
|
DirectoryEnumContext->TemplateFileName.Buffer =
|
|
(POSTR)((PUCHAR)DirectoryEnumContext +
|
|
sizeof(DIRECTORY_ENUM_CONTEXT));
|
|
|
|
if (!IopCopyTemplateFileName(&DirectoryEnumContext->TemplateFileName,
|
|
TemplateFileName)) {
|
|
ExFreePool(DirectoryEnumContext);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
*ReturnedDirectoryEnumContext = DirectoryEnumContext;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
BOOLEAN
|
|
IoIsNameInExpression(
|
|
IN POBJECT_STRING TemplateFileName,
|
|
IN POBJECT_STRING FileName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine checks if the supplied file name matches the supplied search
|
|
specification template.
|
|
|
|
Arguments:
|
|
|
|
TemplateFileName - Specifies the search specification.
|
|
|
|
FileName - Specifies the file name to match against the template.
|
|
|
|
Return Value:
|
|
|
|
Returns TRUE if the file name matches the template file name, else FALSE.
|
|
|
|
--*/
|
|
{
|
|
POSTR TemplateFileNameCurrent;
|
|
POSTR TemplateFileNameEnd;
|
|
POSTR FileNameCurrent;
|
|
POSTR FileNameEnd;
|
|
OCHAR Char;
|
|
OCHAR TemplateChar;
|
|
|
|
ASSERT(TemplateFileName->Length > 0);
|
|
|
|
//
|
|
// If we somehow get a name with no characters in it, reject it.
|
|
//
|
|
|
|
if (FileName->Length == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
TemplateFileNameCurrent = TemplateFileName->Buffer;
|
|
TemplateFileNameEnd = (POSTR)((PUCHAR)TemplateFileNameCurrent +
|
|
TemplateFileName->Length);
|
|
FileNameCurrent = FileName->Buffer;
|
|
FileNameEnd = (POSTR)((PUCHAR)FileNameCurrent + FileName->Length);
|
|
|
|
while (TemplateFileNameCurrent < TemplateFileNameEnd) {
|
|
|
|
TemplateChar = *TemplateFileNameCurrent++;
|
|
|
|
if (TemplateChar == OTEXT('*')) {
|
|
|
|
//
|
|
// If the asterisk is the last character in the string, then consume
|
|
// the rest of the file name.
|
|
//
|
|
|
|
if (TemplateFileNameCurrent == TemplateFileNameEnd) {
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Only allow an asterisk to be followed by the start of an
|
|
// extension. This has already been verified by
|
|
// IoCopyTemplateFileName.
|
|
//
|
|
|
|
ASSERT(*TemplateFileNameCurrent == OTEXT('.'));
|
|
TemplateFileNameCurrent++;
|
|
|
|
//
|
|
// Consume characters from the file name until we find the start of
|
|
// an extension or the end of the string.
|
|
//
|
|
|
|
do {
|
|
|
|
if (FileNameCurrent == FileNameEnd) {
|
|
break;
|
|
}
|
|
|
|
Char = *FileNameCurrent++;
|
|
|
|
} while (Char != OTEXT('.'));
|
|
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// If we're out of characters to match in the file name, then the
|
|
// template is longer than the name, so fail the match.
|
|
//
|
|
|
|
if (FileNameCurrent == FileNameEnd) {
|
|
return FALSE;
|
|
}
|
|
|
|
Char = *FileNameCurrent++;
|
|
|
|
if (TemplateChar != OTEXT('?')) {
|
|
|
|
//
|
|
// Upcase the character if necessary.
|
|
//
|
|
|
|
if (Char >= OTEXT('a') && Char <= OTEXT('z')) {
|
|
Char = (OCHAR)(Char - (OTEXT('a') - OTEXT('A')));
|
|
}
|
|
|
|
//
|
|
// If the character doesn't match the template, then we're done.
|
|
//
|
|
|
|
if (Char != TemplateChar) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// We ran out of characters in the template. If we consumed the entire
|
|
// file name, then this is a match.
|
|
//
|
|
|
|
return (BOOLEAN)(FileNameCurrent == FileNameEnd);
|
|
}
|