diff --git a/src/sys/driver.h b/src/sys/driver.h index 8b7af81f..5eb3385f 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -417,6 +417,12 @@ BOOLEAN FspExpirationTimeValid(UINT64 ExpirationTime) return 1 >= ExpirationTime + 1 ? (0 != ExpirationTime) : (KeQueryInterruptTime() < ExpirationTime); } static inline +BOOLEAN FspExpirationTimeValidEx(UINT64 ExpirationTime, UINT64 CurrentTime) +{ + /* if ExpirationTime is 0 or -1 then ExpirationTime else CurrentTime < ExpirationTime */ + return 1 >= ExpirationTime + 1 ? (0 != ExpirationTime) : (CurrentTime < ExpirationTime); +} +static inline BOOLEAN FspExpirationTimeValid2(UINT64 ExpirationTime, UINT64 CurrentTime) { return CurrentTime < ExpirationTime; @@ -919,14 +925,14 @@ typedef struct FSP_FILE_NODE UNICODE_STRING FileName; PWSTR ExternalFileName; /* locked under Header.Resource */ - UINT64 InfoExpirationTime; + UINT64 FileInfoExpirationTime, BasicInfoExpirationTime; UINT32 FileAttributes; UINT32 ReparseTag; UINT64 CreationTime; UINT64 LastAccessTime; UINT64 LastWriteTime; UINT64 ChangeTime; - ULONG InfoChangeNumber; + ULONG FileInfoChangeNumber; UINT64 Security; ULONG SecurityChangeNumber; ULONG DirInfoChangeNumber; @@ -1013,7 +1019,11 @@ BOOLEAN FspFileNodeTrySetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileOb static inline ULONG FspFileNodeFileInfoChangeNumber(FSP_FILE_NODE *FileNode) { - return FileNode->InfoChangeNumber; + if (0 != FileNode->MainFileNode) + return (FileNode->MainFileNode->FileInfoChangeNumber & 0xfffff) | + ((FileNode->FileInfoChangeNumber & 0xfff) << 20); + else + return FileNode->FileInfoChangeNumber & 0xfffff; } BOOLEAN FspFileNodeReferenceSecurity(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize); VOID FspFileNodeSetSecurity(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size); @@ -1024,7 +1034,6 @@ ULONG FspFileNodeSecurityChangeNumber(FSP_FILE_NODE *FileNode) { if (0 != FileNode->MainFileNode) FileNode = FileNode->MainFileNode; - return FileNode->SecurityChangeNumber; } BOOLEAN FspFileNodeReferenceDirInfo(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize); diff --git a/src/sys/file.c b/src/sys/file.c index 57487a58..13b12da4 100644 --- a/src/sys/file.c +++ b/src/sys/file.c @@ -855,7 +855,14 @@ VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileIn FileInfo->AllocationSize = FileNode->Header.AllocationSize.QuadPart; FileInfo->FileSize = FileNode->Header.FileSize.QuadPart; - FileInfo->FileAttributes = FileNode->FileAttributes; + UINT32 FileAttributesMask = ~(UINT32)0; + if (0 != FileNode->MainFileNode) + { + FileAttributesMask = ~(UINT32)FILE_ATTRIBUTE_DIRECTORY; + FileNode = FileNode->MainFileNode; + } + + FileInfo->FileAttributes = FileNode->FileAttributes & FileAttributesMask; FileInfo->ReparseTag = FileNode->ReparseTag; FileInfo->CreationTime = FileNode->CreationTime; FileInfo->LastAccessTime = FileNode->LastAccessTime; @@ -867,25 +874,20 @@ BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO * { PAGED_CODE(); - BOOLEAN Result; + UINT64 CurrentTime = KeQueryInterruptTime(); - if (FspExpirationTimeValid(FileNode->InfoExpirationTime)) + if (0 != FileNode->MainFileNode) { - FileInfo->AllocationSize = FileNode->Header.AllocationSize.QuadPart; - FileInfo->FileSize = FileNode->Header.FileSize.QuadPart; - - FileInfo->FileAttributes = FileNode->FileAttributes; - FileInfo->ReparseTag = FileNode->ReparseTag; - FileInfo->CreationTime = FileNode->CreationTime; - FileInfo->LastAccessTime = FileNode->LastAccessTime; - FileInfo->LastWriteTime = FileNode->LastWriteTime; - FileInfo->ChangeTime = FileNode->ChangeTime; - Result = TRUE; + /* if this is a stream the main file basic info must have not expired as well! */ + if (!FspExpirationTimeValidEx(FileNode->MainFileNode->BasicInfoExpirationTime, CurrentTime)) + return FALSE; } - else - Result = FALSE; - return Result; + if (!FspExpirationTimeValidEx(FileNode->FileInfoExpirationTime, CurrentTime)) + return FALSE; + + FspFileNodeGetFileInfo(FileNode, FileInfo); + return TRUE; } VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, @@ -906,15 +908,29 @@ VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, FileNode->Header.AllocationSize.QuadPart = AllocationSize; FileNode->Header.FileSize.QuadPart = FileInfo->FileSize; - FileNode->FileAttributes = FileInfo->FileAttributes; - FileNode->ReparseTag = FileInfo->ReparseTag; - FileNode->CreationTime = FileInfo->CreationTime; - FileNode->LastAccessTime = FileInfo->LastAccessTime; - FileNode->LastWriteTime = FileInfo->LastWriteTime; - FileNode->ChangeTime = FileInfo->ChangeTime; - FileNode->InfoExpirationTime = FspExpirationTimeFromMillis( - FsvolDeviceExtension->VolumeParams.FileInfoTimeout); - FileNode->InfoChangeNumber++; + FileNode->FileInfoExpirationTime = FileNode->BasicInfoExpirationTime = + FspExpirationTimeFromMillis(FsvolDeviceExtension->VolumeParams.FileInfoTimeout); + FileNode->FileInfoChangeNumber++; + + FSP_FILE_NODE *MainFileNode = FileNode; + UINT32 FileAttributesMask = ~(UINT32)0; + if (0 != FileNode->MainFileNode) + { + FileAttributesMask = ~(UINT32)FILE_ATTRIBUTE_DIRECTORY; + MainFileNode = FileNode->MainFileNode; + + MainFileNode->BasicInfoExpirationTime = FileNode->BasicInfoExpirationTime; + MainFileNode->FileInfoChangeNumber++; + } + + MainFileNode->FileAttributes = + (MainFileNode->FileAttributes & ~FileAttributesMask) | + (FileInfo->FileAttributes & FileAttributesMask); + MainFileNode->ReparseTag = FileInfo->ReparseTag; + MainFileNode->CreationTime = FileInfo->CreationTime; + MainFileNode->LastAccessTime = FileInfo->LastAccessTime; + MainFileNode->LastWriteTime = FileInfo->LastWriteTime; + MainFileNode->ChangeTime = FileInfo->ChangeTime; if (0 != CcFileObject) { @@ -934,7 +950,7 @@ BOOLEAN FspFileNodeTrySetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileOb { PAGED_CODE(); - if (FileNode->InfoChangeNumber != InfoChangeNumber) + if (FspFileNodeFileInfoChangeNumber(FileNode) != InfoChangeNumber) return FALSE; FspFileNodeSetFileInfo(FileNode, CcFileObject, FileInfo);