320 lines
7.2 KiB
C
320 lines
7.2 KiB
C
/*++
|
|
|
|
Copyright (c) 2000-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
udfsup.c
|
|
|
|
Abstract:
|
|
|
|
This module implements UDF file system utility routines.
|
|
|
|
--*/
|
|
|
|
#include "udfx.h"
|
|
|
|
BOOLEAN
|
|
UdfxVerifyDescriptor(
|
|
IN PDESTAG Descriptor,
|
|
IN ULONG DescriptorSize,
|
|
IN USHORT Ident,
|
|
IN ULONG LogicalSectorNumber
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine checks if the supplied descriptor tag is structurally correct.
|
|
|
|
Refer to ISO 13346 section 3/7.2.
|
|
|
|
Arguments:
|
|
|
|
Descriptor - Specifies the descriptor tag to verify.
|
|
|
|
DescriptorSize - Specifies the size in bytes of the descriptor.
|
|
|
|
Ident - Specifies the expected identifier of the tag.
|
|
|
|
LogicalSectorNumber - Specifies the expected sector number of the tag.
|
|
|
|
Return Value:
|
|
|
|
Returns TRUE if the descriptor is structurally correct, else FALSE.
|
|
|
|
--*/
|
|
{
|
|
if ((Descriptor->Version == DESTAG_VER_CURRENT) &&
|
|
(Descriptor->Ident == Ident) &&
|
|
(Descriptor->Lbn == LogicalSectorNumber)) {
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
BOOLEAN
|
|
UdfxEqualOSTACS0StringAndObjectString(
|
|
IN PUCHAR OSTACS0String,
|
|
IN SIZE_T OSTACS0StringLength,
|
|
IN POBJECT_STRING ObjectString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine does a case insensitive comparision of a OSTA CS0 string to an
|
|
object manager string.
|
|
|
|
Arguments:
|
|
|
|
OSTACS0String - Specifies the OSTA CS0 string to compare.
|
|
|
|
OSTACS0StringLength - Specifies the length of the OSTA CS0 string.
|
|
|
|
ObjectString - Specifies the object manager string to compare.
|
|
|
|
Return Value:
|
|
|
|
Returns TRUE if the strings are equal, else FALSE.
|
|
|
|
--*/
|
|
{
|
|
POSTR ObjectBuffer;
|
|
OCHAR c1;
|
|
OCHAR c2;
|
|
|
|
//
|
|
// The first byte of an OSTA Compressed Unicode string is the compression
|
|
// format, which is either going to be 8-bits per character or 16-bits per
|
|
// character. All other values are reserved and we'll treat as a failed
|
|
// compare.
|
|
//
|
|
|
|
if (*OSTACS0String != 8) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Advance past the compression code.
|
|
//
|
|
|
|
OSTACS0String++;
|
|
OSTACS0StringLength--;
|
|
|
|
//
|
|
// Check if the lengths of the strings match.
|
|
//
|
|
|
|
if (ObjectString->Length != OSTACS0StringLength * sizeof(OCHAR)) {
|
|
return FALSE;
|
|
}
|
|
|
|
ObjectBuffer = ObjectString->Buffer;
|
|
|
|
while (OSTACS0StringLength) {
|
|
|
|
c1 = *ObjectBuffer++;
|
|
c2 = (OCHAR)*OSTACS0String++;
|
|
|
|
if ((c1 != c2) && (RtlUpperChar(c1) != RtlUpperChar(c2))) {
|
|
return FALSE;
|
|
}
|
|
|
|
OSTACS0StringLength -= sizeof(CHAR);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
NTSTATUS
|
|
UdfxOSTACS0StringToObjectString(
|
|
IN PUCHAR OSTACS0String,
|
|
IN SIZE_T OSTACS0StringLength,
|
|
OUT POBJECT_STRING ObjectString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine converts a OSTA CS0 string to an object manager string.
|
|
|
|
Arguments:
|
|
|
|
OSTACS0String - Specifies the source string to convert.
|
|
|
|
OSTACS0StringLength - Specifies the length of the source string.
|
|
|
|
ObjectString - Specifies the buffer to receive the converted object manager
|
|
string.
|
|
|
|
Return Value:
|
|
|
|
Status of operation.
|
|
|
|
--*/
|
|
{
|
|
POSTR ObjectBuffer;
|
|
|
|
ObjectString->Buffer = NULL;
|
|
|
|
if (OSTACS0StringLength != 0) {
|
|
|
|
//
|
|
// The first byte of an OSTA Compressed Unicode string is the compression
|
|
// format, which is either going to be 8-bits per character or 16-bits
|
|
// per character.
|
|
//
|
|
|
|
if (*OSTACS0String == 8) {
|
|
|
|
//
|
|
// Advance past the compression code.
|
|
//
|
|
|
|
OSTACS0String++;
|
|
OSTACS0StringLength--;
|
|
|
|
//
|
|
// Allocate a buffer to receive the object manager string.
|
|
//
|
|
|
|
ObjectBuffer = ExAllocatePoolWithTag(OSTACS0StringLength *
|
|
sizeof(OCHAR), 'gSxU');
|
|
|
|
if (ObjectBuffer == NULL) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
ObjectString->Buffer = ObjectBuffer;
|
|
ObjectString->Length = (USHORT)(OSTACS0StringLength * sizeof(OCHAR));
|
|
ObjectString->MaximumLength = ObjectString->Length;
|
|
|
|
//
|
|
// Fill in the output buffer.
|
|
//
|
|
|
|
RtlCopyMemory(ObjectBuffer, OSTACS0String, OSTACS0StringLength);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
LARGE_INTEGER
|
|
UdfxUdfTimestampToTime(
|
|
IN PTIMESTAMP UdfTimestamp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine converts a UDF timestamp to a NT system time.
|
|
|
|
Arguments:
|
|
|
|
UdfTimestamp - Specifies the timestamp to convert to NT system time.
|
|
|
|
Return Value:
|
|
|
|
Conversion to NT system time.
|
|
|
|
--*/
|
|
{
|
|
LARGE_INTEGER SystemTime;
|
|
TIME_FIELDS TimeField;
|
|
|
|
TimeField.Year = UdfTimestamp->Year;
|
|
TimeField.Month = UdfTimestamp->Month;
|
|
TimeField.Day = UdfTimestamp->Day;
|
|
TimeField.Hour = UdfTimestamp->Hour;
|
|
TimeField.Minute = UdfTimestamp->Minute;
|
|
TimeField.Second = UdfTimestamp->Second;
|
|
TimeField.Milliseconds = 0;
|
|
|
|
//
|
|
// Validate the timestamp is valid and convert it to a system time.
|
|
//
|
|
|
|
if ((UdfTimestamp->Type <= TIMESTAMP_T_LOCAL) &&
|
|
((UdfTimestamp->Zone >= TIMESTAMP_Z_MIN && UdfTimestamp->Zone <= TIMESTAMP_Z_MAX) ||
|
|
(UdfTimestamp->Zone == TIMESTAMP_Z_NONE)) &&
|
|
RtlTimeFieldsToTime(&TimeField, &SystemTime)) {
|
|
|
|
//
|
|
// If necessary, convert to coordinated universal time.
|
|
//
|
|
|
|
if ((UdfTimestamp->Type == TIMESTAMP_T_LOCAL) &&
|
|
(UdfTimestamp->Zone != TIMESTAMP_Z_NONE)) {
|
|
SystemTime.QuadPart -= (ULONGLONG)UdfTimestamp->Zone * 60 * 10 * 1000 * 1000;
|
|
}
|
|
|
|
} else {
|
|
|
|
SystemTime.QuadPart = 0;
|
|
}
|
|
|
|
return SystemTime;
|
|
}
|
|
|
|
NTSTATUS
|
|
UdfxMapLogicalSector(
|
|
IN PUDF_VOLUME_EXTENSION VolumeExtension,
|
|
IN PIRP Irp,
|
|
IN ULONG LogicalSectorNumber,
|
|
OUT PVOID *CacheBuffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine maps the supplied logical sector number into the file system
|
|
cache.
|
|
|
|
Arguments:
|
|
|
|
VolumeExtension - Specifies the extension that the I/O request is for.
|
|
|
|
Irp - Specifies the packet that describes the I/O request.
|
|
|
|
LogicalSectorNumber - Specifies the number of the logical sector to map into
|
|
the cache.
|
|
|
|
CacheBuffer - Specifies the buffer to receive the address of the mapped
|
|
cache buffer.
|
|
|
|
Return Value:
|
|
|
|
Status of operation.
|
|
|
|
--*/
|
|
{
|
|
ULONGLONG ByteOffset;
|
|
|
|
//
|
|
// Verify that the logical sector resides inside the physical partition.
|
|
//
|
|
|
|
if (LogicalSectorNumber >= VolumeExtension->PartitionSectorCount) {
|
|
return STATUS_DISK_CORRUPT_ERROR;
|
|
}
|
|
|
|
//
|
|
// Convert the logical sector to the disk offset.
|
|
//
|
|
|
|
ByteOffset = ((ULONGLONG)VolumeExtension->PartitionSectorStart +
|
|
LogicalSectorNumber) << UDF_CD_SECTOR_SHIFT;
|
|
|
|
//
|
|
// Map the directory sector into the cache.
|
|
//
|
|
|
|
return FscMapBuffer(&VolumeExtension->CacheExtension, Irp, ByteOffset,
|
|
FALSE, CacheBuffer);
|
|
}
|