📄 namesup.c
字号:
/* and no extension was found. */
extLen = 0;
nameLen = udfNameLen;
}
else {
/* A DOS extension was found, process it first. */
extLen = udfNameLen - index - 1;
nameLen = index;
targetIndex = 0;
bytesLeft = DOS_EXT_LEN;
while (++index < udfNameLen && bytesLeft > 0) {
/* Get the current character and convert it to upper */
/* case. */
current = UnicodeToUpper(udfName[index]);
if (current == SPACE) {
/* If a space is found, a CRC must be appended to */
/* the mangled file name. */
needsCRC = TRUE;
}
else {
/* Determine if this is a valid file name char and */
/* calculate its corresponding BCS character byte */
/* length (zero if the char is not legal or */
/* undisplayable on this system). */
charLen = (IsFileNameCharLegal(current)) ?
NativeDosCharLength(current) : 0;
/* If the char is larger than the available space */
/* in the buffer, pretend it is undisplayable. */
if (charLen > bytesLeft)
charLen = 0;
if (charLen == 0) {
/* Undisplayable or illegal characters are */
/* substituted with an underscore ("_"), and */
/* required a CRC code appended to the mangled */
/* file name. */
needsCRC = TRUE;
charLen = 1;
current = ILLEGAL_CHAR_MARK;
/* Skip over any following undiplayable or */
/* illegal chars. */
while (index + 1 < udfNameLen &&
(!IsFileNameCharLegal(udfName[index + 1]) ||
NativeDosCharLength(udfName[index + 1]) == 0))
index++;
}
/* Assign the resulting char to the next index in */
/* the extension buffer and determine how many BCS */
/* bytes are left. */
ext[targetIndex++] = current;
bytesLeft -= charLen;
}
}
/* Save the number of Unicode characters in the extension */
extLen = targetIndex;
/* If the extension was too large, or it was zero length */
/* (i.e. the name ended in a period), a CRC code must be */
/* appended to the mangled name. */
if (index < udfNameLen || extLen == 0)
needsCRC = TRUE;
}
/* Now process the actual file name. */
index = 0;
targetIndex = 0;
crcIndex = 0;
overlayBytes = -1;
bytesLeft = DOS_NAME_LEN;
while (index < nameLen && bytesLeft > 0) {
/* Get the current character and convert it to upper case. */
current = UnicodeToUpper(udfName[index]);
if (current == SPACE || current == PERIOD) {
/* Spaces and periods are just skipped, a CRC code */
/* must be added to the mangled file name. */
needsCRC = TRUE;
}
else {
/* Determine if this is a valid file name char and */
/* calculate its corresponding BCS character byte */
/* length (zero if the char is not legal or */
/* undisplayable on this system). */
charLen = (IsFileNameCharLegal(current)) ?
NativeDosCharLength(current) : 0;
/* If the char is larger than the available space in */
/* the buffer, pretend it is undisplayable. */
if (charLen > bytesLeft)
charLen = 0;
if (charLen == 0) {
/* Undisplayable or illegal characters are */
/* substituted with an underscore ("_"), and */
/* required a CRC code appended to the mangled */
/* file name. */
needsCRC = TRUE;
charLen = 1;
current = ILLEGAL_CHAR_MARK;
/* Skip over any following undiplayable or illegal */
/* chars. */
while (index + 1 < nameLen &&
(!IsFileNameCharLegal(udfName[index + 1]) ||
NativeDosCharLength(udfName[index + 1]) == 0))
index++;
/* Terminate loop if at the end of the file name. */
if (index >= nameLen)
break;
}
/* Assign the resulting char to the next index in the */
/* file name buffer and determine how many BCS bytes */
/* are left. */
dosName[targetIndex++] = current;
bytesLeft -= charLen;
/* This figures out where the CRC code needs to start */
/* in the file name buffer. */
if (bytesLeft >= DOS_CRC_LEN) {
/* If there is enough space left, just tack it */
/* onto the end. */
crcIndex = targetIndex;
}
else {
/* If there is not enough space left, the CRC */
/* must overlay a character already in the file */
/* name buffer. Once this condition has been */
/* met, the value will not change. */
if (overlayBytes < 0) {
/* Determine the index and save the length of */
/* the BCS character that is overlayed. It */
/* is possible that the CRC might overlay */
/* half of a two-byte BCS character depending */
/* upon how the character boundaries line up. */
overlayBytes = (bytesLeft + charLen > DOS_CRC_LEN)
? 1 : 0;
crcIndex = targetIndex - 1;
}
}
}
/* Advance to the next character. */
index++;
}
/* If the scan did not reach the end of the file name, or the */
/* length of the file name is zero, a CRC code is needed. */
if (index < nameLen || index == 0)
needsCRC = TRUE;
/* If the name has illegal characters or and extension, it */
/* is not a DOS device name. */
if (needsCRC == FALSE && extLen == 0) {
/* If this is the name of a DOS device, a CRC code should */
/* be appended to the file name. */
if (IsDeviceName(udfName, udfNameLen))
needsCRC = TRUE;
}
/* Append the CRC code to the file name, if needed. */
if (needsCRC) {
/* Get the CRC value for the original Unicode string */
UINT16 udfCRCValue;
UINT16 modulus;
//
// In UDF 2.00, the sample code changed to take the CRC
// from the UNICODE expansion of the CS0 as opposed to
// the CS0 itself. In UDF 2.01, the wording of the spec
// will actually match this.
//
// Additionally, the checksum changes to be byte-order
// independent.
//
udfCRCValue = UdfComputeCrc16Uni(udfName, udfNameLen);
/* Determine the character index where the CRC should */
/* begin. */
targetIndex = crcIndex;
/* If the character being overlayed is a two-byte BCS */
/* character, replace the first byte with an underscore. */
if (overlayBytes > 0)
dosName[targetIndex++] = ILLEGAL_CHAR_MARK;
//
// UDF 2.01 changes to a base 41 encoding. UDF 1.50 and
// UDF 2.00 exchanged the # delimeter with the high 4bits
// of the CRC.
//
dosName[targetIndex++] = CRC_MARK;
dosName[targetIndex++] =
UdfCrcChar[udfCRCValue / (41 * 41)];
udfCRCValue %= (41 * 41);
dosName[targetIndex++] =
UdfCrcChar[udfCRCValue / 41];
udfCRCValue %= 41;
dosName[targetIndex++] =
UdfCrcChar[udfCRCValue];
}
/* Append the extension, if any. */
if (extLen > 0) {
/* Tack on a period and each successive byte in the */
/* extension buffer. */
dosName[targetIndex++] = PERIOD;
for (index = 0; index < extLen; index++)
dosName[targetIndex++] = ext[index];
}
ASSERT( (targetIndex * sizeof(WCHAR)) <= ShortFileName->MaximumLength );
ShortFileName->Length = (USHORT) (targetIndex * sizeof(WCHAR));
//
// Now we upcase the whole name at once.
//
UdfUpcaseName( IrpContext,
ShortFileName,
ShortFileName );
}
VOID
UdfConvertCS0DstringToUnicode (
IN PIRP_CONTEXT IrpContext,
IN PUCHAR Dstring,
IN UCHAR Length OPTIONAL,
IN UCHAR FieldLength OPTIONAL,
IN OUT PUNICODE_STRING Name
)
/*++
Routine Description:
This routine will convert the CS0 input dstring (1/7.2.12) to Unicode. We assume that
the length is sane.
This "compression" in CS0 is really just a special case hack for ASCII.
Arguments:
Dstring - the input dstring field
Length - length of the dstring. If unspecified, we assume that the characters come
from a proper 1/7.2.12 dstring that specifies length in the last character of the
field.
FieldLength - length of the dstring field. If unspecified, we assume that the characters
come from an uncounted length of CS0 characters and that the Length parameter is
specified.
Name - the output Unicode string
Return Value:
None.
--*/
{
ULONG CompressID;
ULONG UnicodeIndex, ByteIndex;
PWCHAR Unicode = Name->Buffer;
UCHAR NameLength;
ULONG CopyNameLength;
PAGED_CODE();
//
// Check input.
//
ASSERT_IRP_CONTEXT( IrpContext );
CompressID = *Dstring;
//
// If the length is unspecified, this is a real 1/7.2.12 dstring and the length is in
// the last character of the field.
//
ASSERT( Length || FieldLength );
if (Length) {
NameLength = FieldLength = Length;
} else {
NameLength = *(Dstring + FieldLength - 1);
}
//
// If the caller specified a size, they should have made sure the buffer is big enough.
// Otherwise, we will trim to fit.
//
ASSERT( Length == 0 || Name->MaximumLength >= UdfCS0DstringUnicodeSize( IrpContext, Dstring, NameLength ) );
//
// Decide how many UNICODE bytes to "copy".
//
CopyNameLength = Min( Name->MaximumLength, UdfCS0DstringUnicodeSize( IrpContext, Dstring, NameLength ));
//
// Reset the name length and advance over the compression ID in the dstring.
//
Name->Length = 0;
Dstring++;
//
// Loop through all the bytes.
//
while (CopyNameLength > Name->Length) {
if (CompressID == 16) {
//
// We're little endian, and this is the single place in the entire UDF/ISO standard
// where they use big endian.
//
// Thank you. Thank you very much.
//
// Do an unaligned swapcopy of this 16bit value.
//
SwapCopyUchar2( Unicode, Dstring );
Dstring += sizeof(WCHAR);
} else {
//
// Drop the byte into the low bits.
//
*Unicode = *Dstring;
Dstring += sizeof(CHAR);
}
Name->Length += sizeof(WCHAR);
Unicode++;
}
return;
}
BOOLEAN
UdfCheckLegalCS0Dstring (
PIRP_CONTEXT IrpContext,
PUCHAR Dstring,
UCHAR Length OPTIONAL,
UCHAR FieldLength OPTIONAL,
BOOLEAN ReturnOnError
)
/*++
Routine Description:
This routine inspects a CS0 Dstring for conformance.
Arguments:
Dstring - a dstring to check
Length - length of the dstring. If unspecified, we assume that the characters come
from a proper 1/7.2.12 dstring that specifies length in the last character of the
field.
FieldLength - length of the dstring field. If unspecified, we assume that the characters
come from an uncounted length of CS0 characters and that the Length parameter is
specified.
ReturnOnError - whether to return or raise on a discovered error
Return Value:
None. Raised status if corruption is found.
--*/
{
UCHAR NameLength;
//
// Check input.
//
ASSERT_IRP_CONTEXT( IrpContext );
//
// If the length is unspecified, this is a real 1/7.2.12 dstring and the length is in
// the last character of the field.
//
ASSERT( Length || FieldLength );
if (Length) {
NameLength = FieldLength = Length;
} else {
NameLength = *(Dstring + FieldLength - 1);
}
DebugTrace(( +1, Dbg,
"UdfCheckLegalCS0Dstring, Dstring %08x Length %02x FieldLength %02x (NameLength %02x)\n",
Dstring,
Length,
FieldLength,
NameLength ));
//
// The string must be "compressed" in 8bit or 16bit chunks. If it
// is in 16bit chunks, we better have an integral number of them -
// remember we have the compression ID, so the length will be odd.
//
if ((NameLength <= 1 &&
DebugTrace(( 0, Dbg,
"UdfCheckLegalCS0Dstring, NameLength is too small!\n" ))) ||
(NameLength > FieldLength &&
DebugTrace(( 0, Dbg,
"UdfCheckLegalCS0Dstring, NameLength is bigger than the field itself!\n" ))) ||
((*Dstring != 8 && *Dstring != 16) &&
DebugTrace(( 0, Dbg,
"UdfCheckLegalCS0Dstring, claims encoding %02x, unknown! (not 0x8 or 0x10)\n",
*Dstring ))) ||
((*Dstring == 16 && !FlagOn( NameLength, 1)) &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -