📄 dirsup.c
字号:
// It doesn't hurt to be pedantic about initialization, so do it all.
//
DirContext->PureObjectName.Length =
DirContext->CaseObjectName.Length =
DirContext->ObjectName.Length = UdfUnicodeDirectoryNames[SELF_ENTRY].Length;
DirContext->PureObjectName.MaximumLength =
DirContext->CaseObjectName.MaximumLength =
DirContext->ObjectName.MaximumLength = UdfUnicodeDirectoryNames[SELF_ENTRY].MaximumLength;
DirContext->PureObjectName.Buffer =
DirContext->CaseObjectName.Buffer =
DirContext->ObjectName.Buffer = UdfUnicodeDirectoryNames[SELF_ENTRY].Buffer;
//
// All done.
//
DebugTrace(( 0, Dbg, "Self Entry case\n" ));
DebugTrace(( -1, Dbg, "UdfUpdateDirNames -> VOID\n" ));
return;
}
//
// Handle the case of the parent directory entry.
//
if (FlagOn( DirContext->Fid->Flags, NSR_FID_F_PARENT )) {
//
// Parent entries must occur at the front of the directory and
// have a fid length of zero (13346 4/14.4.4).
//
if (FlagOn( DirContext->Flags, DIR_CONTEXT_FLAG_SEEN_NONCONSTANT ) ||
DirContext->Fid->FileIDLen != 0) {
UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
//
// Note that we have seen the parent entry.
//
SetFlag( DirContext->Flags, DIR_CONTEXT_FLAG_SEEN_PARENT );
//
// It doesn't hurt to be pedantic about initialization, so do it all.
//
DirContext->PureObjectName.Length =
DirContext->CaseObjectName.Length =
DirContext->ObjectName.Length = UdfUnicodeDirectoryNames[PARENT_ENTRY].Length;
DirContext->PureObjectName.MaximumLength =
DirContext->CaseObjectName.MaximumLength =
DirContext->ObjectName.MaximumLength = UdfUnicodeDirectoryNames[PARENT_ENTRY].MaximumLength;
DirContext->PureObjectName.Buffer =
DirContext->CaseObjectName.Buffer =
DirContext->ObjectName.Buffer = UdfUnicodeDirectoryNames[PARENT_ENTRY].Buffer;
//
// All done.
//
DebugTrace(( 0, Dbg, "Parent Entry case\n" ));
DebugTrace(( -1, Dbg, "UdfUpdateDirNames -> VOID\n" ));
return;
}
//
// We now know that we will need to convert the name in a real FID, so figure out where
// it sits in the descriptor.
//
NameDstring = Add2Ptr( DirContext->Fid, ISONsrFidConstantSize + DirContext->Fid->ImpUseLen, PUCHAR );
//
// Every directory must record a parent entry.
//
if (!FlagOn( DirContext->Flags, DIR_CONTEXT_FLAG_SEEN_PARENT)) {
UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
//
// Note that we are proceeding into the non-constant portion of a directory.
//
SetFlag( DirContext->Flags, DIR_CONTEXT_FLAG_SEEN_NONCONSTANT );
//
// Make sure the dstring is good CS0
//
UdfCheckLegalCS0Dstring( IrpContext,
NameDstring,
DirContext->Fid->FileIDLen,
0,
FALSE );
//
// Don't bother allocating tiny buffers - always make sure we get enough for an 8.3 name.
//
BufferLength =
NameLength = Max( BYTE_COUNT_8_DOT_3, UdfCS0DstringUnicodeSize( IrpContext,
NameDstring,
DirContext->Fid->FileIDLen) );
//
// Illegality is both actual illegal characters and too many characters.
//
ContainsIllegal = (!UdfCS0DstringContainsLegalCharacters( NameDstring, DirContext->Fid->FileIDLen ) ||
(NameLength / sizeof( WCHAR )) > MAX_LEN);
//
// If we're illegal, we will need more characters to hold the uniqifying stamp.
//
if (ContainsIllegal) {
BufferLength = (NameLength += (CRC_LEN * sizeof(WCHAR)));
}
//
// If we need to build a case insensitive name, need more space.
//
if (IgnoreCase) {
BufferLength += NameLength;
}
//
// If we need to render the names due to illegal characters, more space again.
//
if (ContainsIllegal) {
BufferLength += NameLength;
} else {
//
// Make sure the names aren't seperated. If more illegal names are found we can
// resplit the buffer but until then avoid the expense of having to copy bytes
// ... odds are that illegal characters are going to be a rarish occurance.
//
DirContext->PureObjectName.Buffer = DirContext->ObjectName.Buffer;
}
DebugTrace(( 0, Dbg,
"Ob %s%sneeds %d bytes (%d byte chunks), have %d\n",
(IgnoreCase? "Ic " : ""),
(ContainsIllegal? "Ci " : ""),
BufferLength,
NameLength,
DirContext->AllocLength ));
//
// Check if we need more space for the names. We will need more if the name size is greater
// than the maximum we can currently store, or if we have stumbled across illegal characters
// and the current Pure name is not seperated from the exposed Object name.
//
// Note that IgnoreCase remains constant across usage of a context so we don't have to wonder
// if it has been seperated from the ObjectName - it'll always be correct.
//
if ((NameLength > DirContext->ObjectName.MaximumLength) ||
(ContainsIllegal && DirContext->ObjectName.Buffer == DirContext->PureObjectName.Buffer)) {
DebugTrace(( 0, Dbg, "Resizing buffers\n" ));
//
// For some reason the sizing is not good for the current name we have to unroll. Figure
// out if we can break up the current allocation in a different way before falling back
// to a new allocation.
//
if (DirContext->AllocLength >= BufferLength) {
//
// So we can still use the current allocation. Chop it up into the required number
// of chunks.
//
DirContext->PureObjectName.MaximumLength =
DirContext->CaseObjectName.MaximumLength =
DirContext->ObjectName.MaximumLength = DirContext->AllocLength / (1 +
(IgnoreCase? 1 : 0) +
(ContainsIllegal? 1 : 0));
DebugTrace(( 0, Dbg,
"... by resplit into %d byte chunks\n",
DirContext->ObjectName.MaximumLength ));
//
// Set the buffer pointers up. Required adjustment will occur below.
//
DirContext->PureObjectName.Buffer =
DirContext->CaseObjectName.Buffer =
DirContext->ObjectName.Buffer = DirContext->NameBuffer;
} else {
DebugTrace(( 0, Dbg, "... by allocating new pool\n" ));
//
// Oh well, no choice but to fall back into the pool. Drop our previous hunk.
//
UdfFreePool( &DirContext->NameBuffer );
DirContext->AllocLength = 0;
//
// The names share an allocation for efficiency.
//
DirContext->PureObjectName.MaximumLength =
DirContext->CaseObjectName.MaximumLength =
DirContext->ObjectName.MaximumLength = NameLength;
DirContext->NameBuffer =
DirContext->PureObjectName.Buffer =
DirContext->CaseObjectName.Buffer =
DirContext->ObjectName.Buffer = FsRtlAllocatePoolWithTag( UdfPagedPool,
BufferLength,
TAG_FILE_NAME );
DirContext->AllocLength = BufferLength;
}
//
// In the presence of the "as appropriate" names, adjust the buffer locations. Note
// that ObjectName.Buffer is always the base of the allocated space.
//
if (IgnoreCase) {
DirContext->CaseObjectName.Buffer = Add2Ptr( DirContext->ObjectName.Buffer,
DirContext->ObjectName.MaximumLength,
PWCHAR );
}
if (ContainsIllegal) {
DirContext->PureObjectName.Buffer = Add2Ptr( DirContext->CaseObjectName.Buffer,
DirContext->CaseObjectName.MaximumLength,
PWCHAR );
}
}
ASSERT( BufferLength <= DirContext->AllocLength );
//
// Convert the dstring.
//
UdfConvertCS0DstringToUnicode( IrpContext,
NameDstring,
DirContext->Fid->FileIDLen,
0,
&DirContext->PureObjectName );
//
// If illegal characters were present, run the name through the UDF transmogrifier.
//
if (ContainsIllegal) {
UdfRenderNameToLegalUnicode( IrpContext,
&DirContext->PureObjectName,
&DirContext->ObjectName );
//
// The ObjectName is the same as the PureObjectName.
//
} else {
DirContext->ObjectName.Length = DirContext->PureObjectName.Length;
}
//
// Upcase the result if required.
//
if (IgnoreCase) {
UdfUpcaseName( IrpContext,
&DirContext->ObjectName,
&DirContext->CaseObjectName );
}
DebugTrace(( -1, Dbg, "UdfUpdateDirNames -> VOID\n" ));
return;
}
BOOLEAN
UdfFindDirEntry (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PUNICODE_STRING Name,
IN BOOLEAN IgnoreCase,
IN BOOLEAN ShortName,
IN PDIR_ENUM_CONTEXT DirContext
)
/*++
Routine Description:
This routine walks the directory specified for an entry which matches the input
criteria.
Arguments:
Fcb - the directory to search
Name - name to search for
IgnoreCase - whether this search should be case-insensitive (Name will already
be upcased)
ShortName - whether the name should be searched for according to short name rules
DirContext - context structure to use and return results in
Return Value:
BOOLEAN True if a matching directory entry is being returned, False otherwise.
--*/
{
PUNICODE_STRING MatchName;
PAGED_CODE();
//
// Check inputs.
//
ASSERT_IRP_CONTEXT( IrpContext );
ASSERT_FCB_INDEX( Fcb );
DebugTrace(( +1, Dbg,
"UdfFindDirEntry, Fcb=%08x Name=\"%wZ\" Ignore=%u Short=%u, DC=%08x\n",
Fcb,
Name,
IgnoreCase,
ShortName,
DirContext ));
//
// Depending on the kind of search we are performing a different flavor of the found name
// wil be used in the comparison.
//
if (ShortName) {
MatchName = &DirContext->ShortObjectName;
} else {
MatchName = &DirContext->CaseObjectName;
}
//
// Go get the first entry.
//
UdfLookupInitialDirEntry( IrpContext,
Fcb,
DirContext,
NULL );
//
// Now loop looking for a good match.
//
do {
//
// If it is deleted, we obviously aren't interested in it.
//
if (FlagOn( DirContext->Fid->Flags, NSR_FID_F_DELETED )) {
continue;
}
UdfUpdateDirNames( IrpContext,
DirContext,
IgnoreCase );
//
// If this is a constant entry, just keep going.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -