📄 fileinfo.c
字号:
// up the UNICODE conversion and append it.
//
if (TrimLength != 0) {
UNICODE_STRING ShortName;
WCHAR ShortNameBuffer[12];
NTSTATUS Status;
//
// Convert the short name to UNICODE and figure out how much
// of it can fit. Again, we always bump the returned length
// to indicate how much is available even if we can't return it.
//
ShortName.Length = 0;
ShortName.MaximumLength = sizeof(ShortNameBuffer);
ShortName.Buffer = ShortNameBuffer;
Status = RtlOemStringToCountedUnicodeString( &ShortName,
&Fcb->ShortName.Name.Oem,
FALSE );
ASSERT( Status == STATUS_SUCCESS );
if (!Overflow) {
if (*Length < ShortName.Length) {
BytesToCopy = *Length;
Overflow = TRUE;
} else {
BytesToCopy = ShortName.Length;
*Length -= BytesToCopy;
}
RtlCopyMemory( (PUCHAR)&Buffer->FileName[0] + Buffer->FileNameLength,
ShortName.Buffer,
BytesToCopy );
}
Buffer->FileNameLength += ShortName.Length;
}
if (Overflow) {
*Length = -1;
}
//
// Return to caller
//
DebugTrace( 0, Dbg, "*Length = %08lx\n", *Length);
DebugTrace(-1, Dbg, "FatQueryNameInfo -> VOID\n", 0);
UNREFERENCED_PARAMETER( IrpContext );
return;
}
//
// Internal Support Routine
//
VOID
FatQueryShortNameInfo (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN OUT PFILE_NAME_INFORMATION Buffer,
IN OUT PLONG Length
)
/*++
Routine Description:
This routine queries the short name of the file.
Arguments:
Fcb - Supplies the Fcb being queried, it has been verified
Buffer - Supplies a pointer to the buffer where the information is to
be returned
Length - Supplies the length of the buffer in bytes, and receives the
remaining bytes free in the buffer upon return.
Return Value:
None
--*/
{
NTSTATUS Status;
ULONG BytesToCopy;
WCHAR ShortNameBuffer[12];
UNICODE_STRING ShortName;
DebugTrace(+1, Dbg, "FatQueryNameInfo...\n", 0);
//
// Convert the name to UNICODE
//
ShortName.Length = 0;
ShortName.MaximumLength = sizeof(ShortNameBuffer);
ShortName.Buffer = ShortNameBuffer;
*Length -= FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]);
Status = RtlOemStringToCountedUnicodeString( &ShortName,
&Fcb->ShortName.Name.Oem,
FALSE );
ASSERT( Status == STATUS_SUCCESS );
//
// If we overflow, set *Length to -1 as a flag.
//
if (*Length < ShortName.Length) {
BytesToCopy = *Length;
*Length = -1;
} else {
BytesToCopy = ShortName.Length;
*Length -= ShortName.Length;
}
RtlCopyMemory( &Buffer->FileName[0],
&ShortName.Buffer[0],
BytesToCopy );
Buffer->FileNameLength = ShortName.Length;
//
// Return to caller
//
DebugTrace( 0, Dbg, "*Length = %08lx\n", *Length);
DebugTrace(-1, Dbg, "FatQueryNameInfo -> VOID\n", 0);
UNREFERENCED_PARAMETER( IrpContext );
return;
}
//
// Internal Support Routine
//
VOID
FatQueryNetworkInfo (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PFILE_OBJECT FileObject,
IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
IN OUT PLONG Length
)
/*++
Description:
This routine performs the query network open information function for fat.
Arguments:
Fcb - Supplies the Fcb being queried, it has been verified
FileObject - Supplies the flag bit that indicates the file was modified.
Buffer - Supplies a pointer to the buffer where the information is to
be returned
Length - Supplies the length of the buffer in bytes, and receives the
remaining bytes free in the buffer upon return.
Return Value:
None
--*/
{
DebugTrace(+1, Dbg, "FatQueryNetworkInfo...\n", 0);
//
// Zero out the output buffer, and set it to indicate that
// the query is a normal file. Later we might overwrite the
// attribute.
//
RtlZeroMemory( Buffer, sizeof(FILE_NETWORK_OPEN_INFORMATION) );
//
// Extract the data and fill in the non zero fields of the output
// buffer
//
if (Fcb->Header.NodeTypeCode == FAT_NTC_ROOT_DCB) {
//
// We have to munge a lie on the fly. Every time we have to
// use 1/1/80 we need to convert to GMT since the TZ may have
// changed on us.
//
ExLocalTimeToSystemTime( &FatJanOne1980,
&Buffer->LastWriteTime );
Buffer->CreationTime = Buffer->LastAccessTime = Buffer->LastWriteTime;
} else {
Buffer->LastWriteTime.QuadPart = Fcb->LastWriteTime.QuadPart;
Buffer->CreationTime.QuadPart = Fcb->CreationTime.QuadPart;
Buffer->LastAccessTime.QuadPart = Fcb->LastAccessTime.QuadPart;
}
Buffer->FileAttributes = Fcb->DirentFatFlags;
//
// If the temporary flag is set, then set it in the buffer.
//
if (FlagOn( Fcb->FcbState, FCB_STATE_TEMPORARY )) {
SetFlag( Buffer->FileAttributes, FILE_ATTRIBUTE_TEMPORARY );
}
//
// If no attributes were set, set the normal bit.
//
if (Buffer->FileAttributes == 0) {
Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
}
//
// Case on whether this is a file or a directory, and extract
// the information and fill in the fcb/dcb specific parts
// of the output buffer
//
if (NodeType(Fcb) == FAT_NTC_FCB) {
if (Fcb->Header.AllocationSize.QuadPart == FCB_LOOKUP_ALLOCATIONSIZE_HINT) {
FatLookupFileAllocationSize( IrpContext, Fcb );
}
Buffer->AllocationSize.QuadPart = Fcb->Header.AllocationSize.QuadPart;
Buffer->EndOfFile.QuadPart = Fcb->Header.FileSize.QuadPart;
}
//
// Update the length and status output variables
//
*Length -= sizeof( FILE_NETWORK_OPEN_INFORMATION );
DebugTrace( 0, Dbg, "*Length = %08lx\n", *Length);
DebugTrace(-1, Dbg, "FatQueryNetworkInfo -> VOID\n", 0);
return;
}
//
// Internal Support routine
//
NTSTATUS
FatSetBasicInfo (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp,
IN PFCB Fcb,
IN PCCB Ccb
)
/*++
Routine Description:
This routine performs the set basic information for fat. It either
completes the request or enqueues it off to the fsp.
Arguments:
Irp - Supplies the irp being processed
Fcb - Supplies the Fcb or Dcb being processed, already known not to
be the root dcb
Ccb - Supplies the flag bit that control updating the last modify
time on cleanup.
Return Value:
NTSTATUS - The result of this operation if it completes without
an exception.
--*/
{
NTSTATUS Status;
PFILE_BASIC_INFORMATION Buffer;
PDIRENT Dirent;
PBCB DirentBcb;
FAT_TIME_STAMP CreationTime;
UCHAR CreationMSec;
FAT_TIME_STAMP LastWriteTime;
FAT_TIME_STAMP LastAccessTime;
FAT_DATE LastAccessDate;
UCHAR Attributes;
BOOLEAN ModifyCreation = FALSE;
BOOLEAN ModifyLastWrite = FALSE;
BOOLEAN ModifyLastAccess = FALSE;
LARGE_INTEGER LargeCreationTime;
LARGE_INTEGER LargeLastWriteTime;
LARGE_INTEGER LargeLastAccessTime;
ULONG NotifyFilter = 0;
DebugTrace(+1, Dbg, "FatSetBasicInfo...\n", 0);
Buffer = Irp->AssociatedIrp.SystemBuffer;
//
// If the user is specifying -1 for a field, that means
// we should leave that field unchanged, even if we might
// have otherwise set it ourselves. We'll set the Ccb flag
// saying that the user set the field so that we
// don't do our default updating.
//
// We set the field to 0 then so we know not to actually
// set the field to the user-specified (and in this case,
// illegal) value.
//
if (Buffer->LastWriteTime.QuadPart == -1) {
SetFlag( Ccb->Flags, CCB_FLAG_USER_SET_LAST_WRITE );
Buffer->LastWriteTime.QuadPart = 0;
}
if (Buffer->LastAccessTime.QuadPart == -1) {
SetFlag( Ccb->Flags, CCB_FLAG_USER_SET_LAST_ACCESS );
Buffer->LastAccessTime.QuadPart = 0;
}
if (Buffer->CreationTime.QuadPart == -1) {
SetFlag( Ccb->Flags, CCB_FLAG_USER_SET_CREATION );
Buffer->CreationTime.QuadPart = 0;
}
DirentBcb = NULL;
Status = STATUS_SUCCESS;
try {
LARGE_INTEGER FatLocalDecThirtyOne1979;
LARGE_INTEGER FatLocalJanOne1980;
ExLocalTimeToSystemTime( &FatDecThirtyOne1979,
&FatLocalDecThirtyOne1979 );
ExLocalTimeToSystemTime( &FatJanOne1980,
&FatLocalJanOne1980 );
//
// Get a pointer to the dirent
//
ASSERT( Fcb->FcbCondition == FcbGood );
FatGetDirentFromFcbOrDcb( IrpContext,
Fcb,
FALSE,
&Dirent,
&DirentBcb );
//
// Check if the user specified a non-zero creation time
//
if (FatData.ChicagoMode && (Buffer->CreationTime.QuadPart != 0)) {
LargeCreationTime = Buffer->CreationTime;
//
// Convert the Nt time to a Fat time
//
if ( !FatNtTimeToFatTime( IrpContext,
&LargeCreationTime,
FALSE,
&CreationTime,
&CreationMSec )) {
//
// Special case the value 12/31/79 and treat this as 1/1/80.
// This '79 value can happen because of time zone issues.
//
if ((LargeCreationTime.QuadPart >= FatLocalDecThirtyOne1979.QuadPart) &&
(LargeCreationTime.QuadPart < FatLocalJanOne1980.QuadPart)) {
CreationTime = FatTimeJanOne1980;
LargeCreationTime = FatLocalJanOne1980;
} else {
DebugTrace(0, Dbg, "Invalid CreationTime\n", 0);
try_return( Status = STATUS_INVALID_PARAMETER );
}
//
// Don't worry about CreationMSec
//
CreationMSec = 0;
}
ModifyCreation = TRUE;
}
//
// Check if the user specified a non-zero last access time
//
if (FatData.ChicagoMode && (Buffer->LastAccessTime.QuadPart != 0)) {
LargeLastAccessTime = Buffer->LastAccessTime;
//
// Convert the Nt time to a Fat time
//
if ( !FatNtTimeToFatTime( IrpContext,
&LargeLastAccessTime,
TRUE,
&LastAccessTime,
NULL )) {
//
// Special case the value 12/31/79 and treat this as 1/1/80.
// This '79 value can happen because of time zone issues.
//
if ((LargeLastAccessTime.QuadPart >= FatLocalDecThirtyOne1979.QuadPart) &&
(LargeLastAccessTime.QuadPart < FatLocalJanOne1980.QuadPart)) {
LastAccessTime = FatTimeJanOne1980;
LargeLastAccessTime = FatLocalJanOne1980;
} else {
DebugTrace(0, Dbg, "Invalid LastAccessTime\n", 0);
try_return( Status = STATUS_INVALID_PARAMETER );
}
}
LastAccessDate = LastAccessTime.Date;
ModifyLastAccess = TRUE;
}
//
// Check if the user specified a non-zero last write time
//
if (Buffer->LastWriteTime.QuadPart != 0) {
//
// First do a quick check here if the this time is the same
// time as LastAccessTime.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -