mirror of
https://github.com/reactos/reactos.git
synced 2024-09-10 04:42:00 +00:00
1042 lines
34 KiB
C++
1042 lines
34 KiB
C++
////////////////////////////////////////////////////////////////////
|
|
// Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
|
|
// All rights reserved
|
|
// This file was released under the GPLv2 on June 2015.
|
|
////////////////////////////////////////////////////////////////////
|
|
/*************************************************************************
|
|
*
|
|
* File: Sys_Spec.cpp
|
|
*
|
|
* Module: UDF File System Driver
|
|
* (both User and Kernel mode execution)
|
|
*
|
|
* Description:
|
|
* Contains system-secific code
|
|
*
|
|
*************************************************************************/
|
|
|
|
|
|
/*
|
|
This routine converts UDF timestamp to NT time
|
|
*/
|
|
LONGLONG
|
|
UDFTimeToNT(
|
|
IN PUDF_TIME_STAMP UdfTime
|
|
)
|
|
{
|
|
LONGLONG NtTime;
|
|
TIME_FIELDS TimeFields;
|
|
|
|
TimeFields.Milliseconds = (USHORT)(UdfTime->centiseconds * 10 + UdfTime->hundredsOfMicroseconds / 100);
|
|
TimeFields.Second = (USHORT)(UdfTime->second);
|
|
TimeFields.Minute = (USHORT)(UdfTime->minute);
|
|
TimeFields.Hour = (USHORT)(UdfTime->hour);
|
|
TimeFields.Day = (USHORT)(UdfTime->day);
|
|
TimeFields.Month = (USHORT)(UdfTime->month);
|
|
TimeFields.Year = (USHORT)((UdfTime->year < 1601) ? 1601 : UdfTime->year);
|
|
|
|
if (!RtlTimeFieldsToTime(&TimeFields, (PLARGE_INTEGER)&NtTime)) {
|
|
NtTime = 0;
|
|
} else {
|
|
ExLocalTimeToSystemTime( (PLARGE_INTEGER)&NtTime, (PLARGE_INTEGER)&NtTime );
|
|
}
|
|
|
|
return NtTime;
|
|
} // end UDFTimeToNT()
|
|
|
|
|
|
/*
|
|
This routine converts NT time to UDF timestamp
|
|
*/
|
|
VOID
|
|
UDFTimeToUDF(
|
|
IN LONGLONG NtTime,
|
|
OUT PUDF_TIME_STAMP UdfTime
|
|
)
|
|
{
|
|
if(!NtTime) return;
|
|
LONGLONG LocalTime;
|
|
|
|
TIME_FIELDS TimeFields;
|
|
|
|
ExSystemTimeToLocalTime( (PLARGE_INTEGER)&NtTime, (PLARGE_INTEGER)&LocalTime );
|
|
RtlTimeToTimeFields( (PLARGE_INTEGER)&LocalTime, &TimeFields );
|
|
|
|
LocalTime /= 10; // microseconds
|
|
UdfTime->microseconds = (UCHAR)(NtTime % 100);
|
|
LocalTime /= 100; // hundreds of microseconds
|
|
UdfTime->hundredsOfMicroseconds = (UCHAR)(NtTime % 100);
|
|
LocalTime /= 100; // centiseconds
|
|
UdfTime->centiseconds = (UCHAR)(TimeFields.Milliseconds / 10);
|
|
UdfTime->second = (UCHAR)(TimeFields.Second);
|
|
UdfTime->minute = (UCHAR)(TimeFields.Minute);
|
|
UdfTime->hour = (UCHAR)(TimeFields.Hour);
|
|
UdfTime->day = (UCHAR)(TimeFields.Day);
|
|
UdfTime->month = (UCHAR)(TimeFields.Month);
|
|
UdfTime->year = (USHORT)(TimeFields.Year);
|
|
UdfTime->typeAndTimezone = (TIMESTAMP_TYPE_LOCAL << 14);
|
|
} // end UDFTimeToUDF()
|
|
|
|
/*
|
|
*/
|
|
ULONG
|
|
UDFAttributesToNT(
|
|
IN PDIR_INDEX_ITEM FileDirNdx,
|
|
IN tag* FileEntry
|
|
)
|
|
{
|
|
ASSERT(FileDirNdx);
|
|
if( (FileDirNdx->FI_Flags & UDF_FI_FLAG_SYS_ATTR) &&
|
|
!(FileDirNdx->FI_Flags & UDF_FI_FLAG_LINKED))
|
|
return FileDirNdx->SysAttr;
|
|
|
|
ULONG NTAttr = 0;
|
|
ULONG attr = 0; //permissions
|
|
USHORT Flags = 0;
|
|
USHORT Type = 0;
|
|
UCHAR FCharact = 0;
|
|
|
|
if(!FileEntry) {
|
|
if(!FileDirNdx->FileInfo)
|
|
return 0;
|
|
ValidateFileInfo(FileDirNdx->FileInfo);
|
|
FileEntry = FileDirNdx->FileInfo->Dloc->FileEntry;
|
|
}
|
|
if(FileEntry->tagIdent == TID_FILE_ENTRY) {
|
|
attr = ((PFILE_ENTRY)FileEntry)->permissions;
|
|
Flags = ((PFILE_ENTRY)FileEntry)->icbTag.flags;
|
|
Type = ((PFILE_ENTRY)FileEntry)->icbTag.fileType;
|
|
if(((PFILE_ENTRY)FileEntry)->fileLinkCount > 1)
|
|
FileDirNdx->FI_Flags |= UDF_FI_FLAG_LINKED;
|
|
} else {
|
|
attr = ((PEXTENDED_FILE_ENTRY)FileEntry)->permissions;
|
|
Flags = ((PEXTENDED_FILE_ENTRY)FileEntry)->icbTag.flags;
|
|
Type = ((PEXTENDED_FILE_ENTRY)FileEntry)->icbTag.fileType;
|
|
if(((PEXTENDED_FILE_ENTRY)FileEntry)->fileLinkCount > 1)
|
|
FileDirNdx->FI_Flags |= UDF_FI_FLAG_LINKED;
|
|
}
|
|
FCharact = FileDirNdx->FileCharacteristics;
|
|
|
|
if(Flags & ICB_FLAG_SYSTEM) NTAttr |= FILE_ATTRIBUTE_SYSTEM;
|
|
if(Flags & ICB_FLAG_ARCHIVE) NTAttr |= FILE_ATTRIBUTE_ARCHIVE;
|
|
if((Type == UDF_FILE_TYPE_DIRECTORY) ||
|
|
(Type == UDF_FILE_TYPE_STREAMDIR) ||
|
|
(FCharact & FILE_DIRECTORY)) {
|
|
NTAttr |= FILE_ATTRIBUTE_DIRECTORY;
|
|
#ifdef UDF_DBG
|
|
} else {
|
|
//NTAttr |= FILE_ATTRIBUTE_NORMAL;
|
|
#endif
|
|
}
|
|
if(FCharact & FILE_HIDDEN) NTAttr |= FILE_ATTRIBUTE_HIDDEN;
|
|
if( !(attr & PERM_O_WRITE) &&
|
|
!(attr & PERM_G_WRITE) &&
|
|
!(attr & PERM_U_WRITE) &&
|
|
!(attr & PERM_O_DELETE) &&
|
|
!(attr & PERM_G_DELETE) &&
|
|
!(attr & PERM_U_DELETE) ) {
|
|
NTAttr |= FILE_ATTRIBUTE_READONLY;
|
|
}
|
|
FileDirNdx->SysAttr = NTAttr;
|
|
return NTAttr;
|
|
} // end UDFAttributesToNT()
|
|
|
|
/*
|
|
*/
|
|
VOID
|
|
UDFAttributesToUDF(
|
|
IN PDIR_INDEX_ITEM FileDirNdx,
|
|
IN tag* FileEntry,
|
|
IN ULONG NTAttr
|
|
)
|
|
{
|
|
PULONG attr; //permissions
|
|
PUSHORT Flags;
|
|
PUCHAR Type;
|
|
PUCHAR FCharact;
|
|
|
|
NTAttr &= UDF_VALID_FILE_ATTRIBUTES;
|
|
|
|
if(!FileEntry) {
|
|
ASSERT(FileDirNdx);
|
|
if(!FileDirNdx->FileInfo)
|
|
return;
|
|
ValidateFileInfo(FileDirNdx->FileInfo);
|
|
FileEntry = FileDirNdx->FileInfo->Dloc->FileEntry;
|
|
FileDirNdx->FileInfo->Dloc->FE_Flags |= UDF_FE_FLAG_FE_MODIFIED;
|
|
}
|
|
if(FileEntry->tagIdent == TID_FILE_ENTRY) {
|
|
attr = &((PFILE_ENTRY)FileEntry)->permissions;
|
|
Flags = &((PFILE_ENTRY)FileEntry)->icbTag.flags;
|
|
Type = &((PFILE_ENTRY)FileEntry)->icbTag.fileType;
|
|
} else {
|
|
attr = &((PEXTENDED_FILE_ENTRY)FileEntry)->permissions;
|
|
Flags = &((PEXTENDED_FILE_ENTRY)FileEntry)->icbTag.flags;
|
|
Type = &((PEXTENDED_FILE_ENTRY)FileEntry)->icbTag.fileType;
|
|
}
|
|
FCharact = &(FileDirNdx->FileCharacteristics);
|
|
|
|
if((*FCharact & FILE_DIRECTORY) ||
|
|
(*Type == UDF_FILE_TYPE_STREAMDIR) ||
|
|
(*Type == UDF_FILE_TYPE_DIRECTORY)) {
|
|
*FCharact |= FILE_DIRECTORY;
|
|
if(*Type != UDF_FILE_TYPE_STREAMDIR)
|
|
*Type = UDF_FILE_TYPE_DIRECTORY;
|
|
*attr |= (PERM_O_EXEC | PERM_G_EXEC | PERM_U_EXEC);
|
|
NTAttr |= FILE_ATTRIBUTE_DIRECTORY;
|
|
NTAttr &= ~FILE_ATTRIBUTE_NORMAL;
|
|
} else {
|
|
*FCharact &= ~FILE_DIRECTORY;
|
|
*Type = UDF_FILE_TYPE_REGULAR;
|
|
*attr &= ~(PERM_O_EXEC | PERM_G_EXEC | PERM_U_EXEC);
|
|
}
|
|
|
|
if(NTAttr & FILE_ATTRIBUTE_SYSTEM) {
|
|
*Flags |= ICB_FLAG_SYSTEM;
|
|
} else {
|
|
*Flags &= ~ICB_FLAG_SYSTEM;
|
|
}
|
|
if(NTAttr & FILE_ATTRIBUTE_ARCHIVE) {
|
|
*Flags |= ICB_FLAG_ARCHIVE;
|
|
} else {
|
|
*Flags &= ~ICB_FLAG_ARCHIVE;
|
|
}
|
|
if(NTAttr & FILE_ATTRIBUTE_HIDDEN) {
|
|
*FCharact |= FILE_HIDDEN;
|
|
} else {
|
|
*FCharact &= ~FILE_HIDDEN;
|
|
}
|
|
*attr |= (PERM_O_READ | PERM_G_READ | PERM_U_READ);
|
|
if(!(NTAttr & FILE_ATTRIBUTE_READONLY)) {
|
|
*attr |= (PERM_O_WRITE | PERM_G_WRITE | PERM_U_WRITE |
|
|
PERM_O_DELETE | PERM_G_DELETE | PERM_U_DELETE |
|
|
PERM_O_CHATTR | PERM_G_CHATTR | PERM_U_CHATTR);
|
|
} else {
|
|
*attr &= ~(PERM_O_WRITE | PERM_G_WRITE | PERM_U_WRITE |
|
|
PERM_O_DELETE | PERM_G_DELETE | PERM_U_DELETE |
|
|
PERM_O_CHATTR | PERM_G_CHATTR | PERM_U_CHATTR);
|
|
}
|
|
FileDirNdx->SysAttr = NTAttr;
|
|
if(FileDirNdx->FileInfo)
|
|
FileDirNdx->FileInfo->Dloc->FE_Flags |= UDF_FE_FLAG_FE_MODIFIED;
|
|
FileDirNdx->FI_Flags |= UDF_FI_FLAG_FI_MODIFIED;
|
|
return;
|
|
} // end UDFAttributesToUDF()
|
|
|
|
#ifndef _CONSOLE
|
|
/*
|
|
This routine fills PFILE_BOTH_DIR_INFORMATION structure (NT)
|
|
*/
|
|
NTSTATUS
|
|
UDFFileDirInfoToNT(
|
|
IN PVCB Vcb,
|
|
IN PDIR_INDEX_ITEM FileDirNdx,
|
|
OUT PFILE_BOTH_DIR_INFORMATION NTFileInfo
|
|
)
|
|
{
|
|
PFILE_ENTRY FileEntry;
|
|
UNICODE_STRING UdfName;
|
|
UNICODE_STRING DosName;
|
|
PEXTENDED_FILE_ENTRY ExFileEntry;
|
|
USHORT Ident;
|
|
BOOLEAN ReadSizes = FALSE;
|
|
NTSTATUS status;
|
|
PtrUDFNTRequiredFCB NtReqFcb;
|
|
|
|
UDFPrint(("@=%#x, FileDirNdx %x\n", &Vcb, FileDirNdx));
|
|
|
|
ASSERT((ULONG_PTR)NTFileInfo > 0x1000);
|
|
RtlZeroMemory(NTFileInfo, sizeof(FILE_BOTH_DIR_INFORMATION));
|
|
|
|
DosName.Buffer = (PWCHAR)&(NTFileInfo->ShortName);
|
|
DosName.MaximumLength = sizeof(NTFileInfo->ShortName); // 12*sizeof(WCHAR)
|
|
|
|
_SEH2_TRY {
|
|
UDFPrint((" DirInfoToNT: %*.*S\n", FileDirNdx->FName.Length/sizeof(WCHAR), FileDirNdx->FName.Length/sizeof(WCHAR), FileDirNdx->FName));
|
|
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
|
UDFPrint((" DirInfoToNT: exception when printing file name\n"));
|
|
} _SEH2_END;
|
|
|
|
if(FileDirNdx->FileInfo) {
|
|
UDFPrint((" FileInfo\n"));
|
|
// validate FileInfo
|
|
ValidateFileInfo(FileDirNdx->FileInfo);
|
|
if(UDFGetFileLinkCount(FileDirNdx->FileInfo) > 1)
|
|
FileDirNdx->FI_Flags |= UDF_FI_FLAG_LINKED;
|
|
FileEntry = (PFILE_ENTRY)(FileDirNdx->FileInfo->Dloc->FileEntry);
|
|
// read required sizes from Fcb (if any) if file is not linked
|
|
// otherwise we should read them from FileEntry
|
|
if(FileDirNdx->FileInfo->Fcb) {
|
|
UDFPrint((" Fcb\n"));
|
|
NtReqFcb = FileDirNdx->FileInfo->Fcb->NTRequiredFCB;
|
|
NTFileInfo->CreationTime.QuadPart = NtReqFcb->CreationTime.QuadPart;
|
|
NTFileInfo->LastWriteTime.QuadPart = NtReqFcb->LastWriteTime.QuadPart;
|
|
NTFileInfo->LastAccessTime.QuadPart = NtReqFcb->LastAccessTime.QuadPart;
|
|
NTFileInfo->ChangeTime.QuadPart = NtReqFcb->ChangeTime.QuadPart;
|
|
// NTFileInfo->AllocationSize.QuadPart = NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart;
|
|
NTFileInfo->AllocationSize.QuadPart = FileDirNdx->AllocationSize;
|
|
/* FileDirNdx->FileSize =
|
|
NTFileInfo->EndOfFile.QuadPart = NtReqFcb->CommonFCBHeader.FileSize.QuadPart;*/
|
|
NTFileInfo->EndOfFile.QuadPart = FileDirNdx->FileSize;
|
|
if(FileDirNdx->FI_Flags & UDF_FI_FLAG_SYS_ATTR) {
|
|
UDFPrint((" SYS_ATTR\n"));
|
|
NTFileInfo->FileAttributes = FileDirNdx->SysAttr;
|
|
goto get_name_only;
|
|
}
|
|
FileDirNdx->CreationTime = NTFileInfo->CreationTime.QuadPart;
|
|
FileDirNdx->LastWriteTime = NTFileInfo->LastWriteTime.QuadPart;
|
|
FileDirNdx->LastAccessTime = NTFileInfo->LastAccessTime.QuadPart;
|
|
FileDirNdx->ChangeTime = NTFileInfo->ChangeTime.QuadPart;
|
|
goto get_attr_only;
|
|
}
|
|
ASSERT(FileEntry);
|
|
} else if(!(FileDirNdx->FI_Flags & UDF_FI_FLAG_SYS_ATTR) ||
|
|
(FileDirNdx->FI_Flags & UDF_FI_FLAG_LINKED)) {
|
|
LONG_AD feloc;
|
|
|
|
UDFPrint((" !SYS_ATTR\n"));
|
|
FileEntry = (PFILE_ENTRY)MyAllocatePool__(NonPagedPool, Vcb->LBlockSize);
|
|
if(!FileEntry) return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
feloc.extLength = Vcb->LBlockSize;
|
|
feloc.extLocation = FileDirNdx->FileEntryLoc;
|
|
|
|
if(!NT_SUCCESS(status = UDFReadFileEntry(Vcb, &feloc, FileEntry, &Ident))) {
|
|
UDFPrint((" !UDFReadFileEntry\n"));
|
|
MyFreePool__(FileEntry);
|
|
FileEntry = NULL;
|
|
goto get_name_only;
|
|
}
|
|
ReadSizes = TRUE;
|
|
} else {
|
|
UDFPrint((" FileDirNdx\n"));
|
|
NTFileInfo->CreationTime.QuadPart = FileDirNdx->CreationTime;
|
|
NTFileInfo->LastWriteTime.QuadPart = FileDirNdx->LastWriteTime;
|
|
NTFileInfo->LastAccessTime.QuadPart = FileDirNdx->LastAccessTime;
|
|
NTFileInfo->ChangeTime.QuadPart = FileDirNdx->ChangeTime;
|
|
NTFileInfo->FileAttributes = FileDirNdx->SysAttr;
|
|
NTFileInfo->AllocationSize.QuadPart = FileDirNdx->AllocationSize;
|
|
NTFileInfo->EndOfFile.QuadPart = FileDirNdx->FileSize;
|
|
NTFileInfo->EaSize = 0;
|
|
FileEntry = NULL;
|
|
goto get_name_only;
|
|
}
|
|
|
|
if(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK)
|
|
goto get_name_only;
|
|
|
|
UDFPrint((" direct\n"));
|
|
if(FileEntry->descTag.tagIdent == TID_FILE_ENTRY) {
|
|
UDFPrint((" TID_FILE_ENTRY\n"));
|
|
if(ReadSizes) {
|
|
UDFPrint((" ReadSizes\n"));
|
|
// Times
|
|
FileDirNdx->CreationTime = NTFileInfo->CreationTime.QuadPart =
|
|
FileDirNdx->LastWriteTime = NTFileInfo->LastWriteTime.QuadPart = UDFTimeToNT(&(FileEntry->modificationTime));
|
|
FileDirNdx->LastAccessTime = NTFileInfo->LastAccessTime.QuadPart = UDFTimeToNT(&(FileEntry->accessTime));
|
|
FileDirNdx->ChangeTime = NTFileInfo->ChangeTime.QuadPart = UDFTimeToNT(&(FileEntry->attrTime));
|
|
// FileSize
|
|
FileDirNdx->FileSize =
|
|
NTFileInfo->EndOfFile.QuadPart =
|
|
FileEntry->informationLength;
|
|
UDFPrint((" informationLength=%I64x, lengthAllocDescs=%I64x\n",
|
|
FileEntry->informationLength,
|
|
FileEntry->lengthAllocDescs
|
|
));
|
|
// AllocSize
|
|
FileDirNdx->AllocationSize =
|
|
NTFileInfo->AllocationSize.QuadPart =
|
|
(FileEntry->informationLength + Vcb->LBlockSize - 1) & ~((LONGLONG)(Vcb->LBlockSize) - 1);
|
|
}
|
|
// NTFileInfo->EaSize = 0;//FileEntry->lengthExtendedAttr;
|
|
} else if(FileEntry->descTag.tagIdent == TID_EXTENDED_FILE_ENTRY) {
|
|
ExFileEntry = (PEXTENDED_FILE_ENTRY)FileEntry;
|
|
UDFPrint((" PEXTENDED_FILE_ENTRY\n"));
|
|
if(ReadSizes) {
|
|
UDFPrint((" ReadSizes\n"));
|
|
// Times
|
|
FileDirNdx->CreationTime = NTFileInfo->CreationTime.QuadPart = UDFTimeToNT(&(ExFileEntry->createTime));
|
|
FileDirNdx->LastWriteTime = NTFileInfo->LastWriteTime.QuadPart = UDFTimeToNT(&(ExFileEntry->modificationTime));
|
|
FileDirNdx->LastAccessTime = NTFileInfo->LastAccessTime.QuadPart = UDFTimeToNT(&(ExFileEntry->accessTime));
|
|
FileDirNdx->ChangeTime = NTFileInfo->ChangeTime.QuadPart = UDFTimeToNT(&(ExFileEntry->attrTime));
|
|
// FileSize
|
|
FileDirNdx->FileSize =
|
|
NTFileInfo->EndOfFile.QuadPart =
|
|
ExFileEntry->informationLength;
|
|
UDFPrint((" informationLength=%I64x, lengthAllocDescs=%I64x\n",
|
|
FileEntry->informationLength,
|
|
FileEntry->lengthAllocDescs
|
|
));
|
|
// AllocSize
|
|
FileDirNdx->AllocationSize =
|
|
NTFileInfo->AllocationSize.QuadPart =
|
|
(ExFileEntry->informationLength + Vcb->LBlockSize - 1) & ~((LONGLONG)(Vcb->LBlockSize) - 1);
|
|
}
|
|
// NTFileInfo->EaSize = 0;//ExFileEntry->lengthExtendedAttr;
|
|
} else {
|
|
UDFPrint((" ???\n"));
|
|
goto get_name_only;
|
|
}
|
|
|
|
get_attr_only:
|
|
|
|
UDFPrint((" get_attr"));
|
|
// do some substitutions
|
|
if(!FileDirNdx->CreationTime) {
|
|
FileDirNdx->CreationTime = NTFileInfo->CreationTime.QuadPart = Vcb->VolCreationTime;
|
|
}
|
|
if(!FileDirNdx->LastAccessTime) {
|
|
FileDirNdx->LastAccessTime = NTFileInfo->LastAccessTime.QuadPart = FileDirNdx->CreationTime;
|
|
}
|
|
if(!FileDirNdx->LastWriteTime) {
|
|
FileDirNdx->LastWriteTime = NTFileInfo->LastWriteTime.QuadPart = FileDirNdx->CreationTime;
|
|
}
|
|
if(!FileDirNdx->ChangeTime) {
|
|
FileDirNdx->ChangeTime = NTFileInfo->ChangeTime.QuadPart = FileDirNdx->CreationTime;
|
|
}
|
|
|
|
FileDirNdx->SysAttr =
|
|
NTFileInfo->FileAttributes = UDFAttributesToNT(FileDirNdx, (tag*)FileEntry);
|
|
FileDirNdx->FI_Flags |= UDF_FI_FLAG_SYS_ATTR;
|
|
|
|
get_name_only:
|
|
// get filename in standard Unicode format
|
|
UdfName = FileDirNdx->FName;
|
|
NTFileInfo->FileNameLength = UdfName.Length;
|
|
RtlCopyMemory((PCHAR)&(NTFileInfo->FileName), (PCHAR)(UdfName.Buffer), UdfName.MaximumLength);
|
|
if(!(FileDirNdx->FI_Flags & UDF_FI_FLAG_DOS)) {
|
|
UDFPrint((" !UDF_FI_FLAG_DOS"));
|
|
UDFDOSName(Vcb, &DosName, &UdfName,
|
|
(FileDirNdx->FI_Flags & UDF_FI_FLAG_KEEP_NAME) ? TRUE : FALSE);
|
|
NTFileInfo->ShortNameLength = (UCHAR)DosName.Length;
|
|
}
|
|
// report zero EOF & AllocSize for Dirs
|
|
if(FileDirNdx->FileCharacteristics & FILE_DIRECTORY) {
|
|
UDFPrint((" FILE_DIRECTORY"));
|
|
NTFileInfo->AllocationSize.QuadPart =
|
|
NTFileInfo->EndOfFile.QuadPart = 0;
|
|
}
|
|
UDFPrint((" AllocationSize=%I64x, NTFileInfo->EndOfFile=%I64x", NTFileInfo->AllocationSize.QuadPart, NTFileInfo->EndOfFile.QuadPart));
|
|
// free tmp buffer (if any)
|
|
UDFPrint(("\n"));
|
|
if(FileEntry && !FileDirNdx->FileInfo)
|
|
MyFreePool__(FileEntry);
|
|
return STATUS_SUCCESS;
|
|
} // end UDFFileDirInfoToNT()
|
|
|
|
#endif //_CONSOLE
|
|
|
|
#ifndef UDF_READ_ONLY_BUILD
|
|
/*
|
|
This routine changes xxxTime field(s) in (Ext)FileEntry
|
|
*/
|
|
VOID
|
|
UDFSetFileXTime(
|
|
IN PUDF_FILE_INFO FileInfo,
|
|
IN LONGLONG* CrtTime,
|
|
IN LONGLONG* AccTime,
|
|
IN LONGLONG* AttrTime,
|
|
IN LONGLONG* ChgTime
|
|
)
|
|
{
|
|
USHORT Ident;
|
|
PDIR_INDEX_ITEM DirNdx;
|
|
|
|
ValidateFileInfo(FileInfo);
|
|
|
|
FileInfo->Dloc->FE_Flags |= UDF_FE_FLAG_FE_MODIFIED;
|
|
DirNdx = UDFDirIndex(UDFGetDirIndexByFileInfo(FileInfo), FileInfo->Index);
|
|
Ident = FileInfo->Dloc->FileEntry->tagIdent;
|
|
|
|
if(Ident == TID_FILE_ENTRY) {
|
|
PFILE_ENTRY fe = (PFILE_ENTRY)(FileInfo->Dloc->FileEntry);
|
|
|
|
if(AccTime) {
|
|
if(DirNdx && *AccTime) DirNdx->LastAccessTime = *AccTime;
|
|
UDFTimeToUDF(*AccTime, &(fe->accessTime));
|
|
}
|
|
if(AttrTime) {
|
|
if(DirNdx && *AttrTime) DirNdx->ChangeTime = *AttrTime;
|
|
UDFTimeToUDF(*AttrTime, &(fe->attrTime));
|
|
}
|
|
if(ChgTime) {
|
|
if(DirNdx && *ChgTime) DirNdx->CreationTime =
|
|
DirNdx->LastWriteTime = *ChgTime;
|
|
UDFTimeToUDF(*ChgTime, &(fe->modificationTime));
|
|
} else
|
|
if(CrtTime) {
|
|
if(DirNdx && *CrtTime) DirNdx->CreationTime =
|
|
DirNdx->LastWriteTime = *CrtTime;
|
|
UDFTimeToUDF(*CrtTime, &(fe->modificationTime));
|
|
}
|
|
|
|
} else if(Ident == TID_EXTENDED_FILE_ENTRY) {
|
|
PEXTENDED_FILE_ENTRY fe = (PEXTENDED_FILE_ENTRY)(FileInfo->Dloc->FileEntry);
|
|
|
|
if(AccTime) {
|
|
if(DirNdx && *AccTime) DirNdx->LastAccessTime = *AccTime;
|
|
UDFTimeToUDF(*AccTime, &(fe->accessTime));
|
|
}
|
|
if(AttrTime) {
|
|
if(DirNdx && *AttrTime) DirNdx->ChangeTime = *AttrTime;
|
|
UDFTimeToUDF(*AttrTime, &(fe->attrTime));
|
|
}
|
|
if(ChgTime) {
|
|
if(DirNdx && *ChgTime) DirNdx->LastWriteTime = *ChgTime;
|
|
UDFTimeToUDF(*ChgTime, &(fe->modificationTime));
|
|
}
|
|
if(CrtTime) {
|
|
if(DirNdx && *CrtTime) DirNdx->CreationTime = *CrtTime;
|
|
UDFTimeToUDF(*CrtTime, &(fe->createTime));
|
|
}
|
|
|
|
}
|
|
} // end UDFSetFileXTime()
|
|
#endif //UDF_READ_ONLY_BUILD
|
|
|
|
/*
|
|
This routine gets xxxTime field(s) in (Ext)FileEntry
|
|
*/
|
|
VOID
|
|
UDFGetFileXTime(
|
|
IN PUDF_FILE_INFO FileInfo,
|
|
OUT LONGLONG* CrtTime,
|
|
OUT LONGLONG* AccTime,
|
|
OUT LONGLONG* AttrTime,
|
|
OUT LONGLONG* ChgTime
|
|
)
|
|
{
|
|
USHORT Ident;
|
|
|
|
ValidateFileInfo(FileInfo);
|
|
|
|
Ident = FileInfo->Dloc->FileEntry->tagIdent;
|
|
|
|
if(Ident == TID_FILE_ENTRY) {
|
|
PFILE_ENTRY fe = (PFILE_ENTRY)(FileInfo->Dloc->FileEntry);
|
|
|
|
if(AccTime) *AccTime = UDFTimeToNT(&(fe->accessTime));
|
|
if(AttrTime) *AttrTime = UDFTimeToNT(&(fe->attrTime));
|
|
if(ChgTime) *ChgTime = UDFTimeToNT(&(fe->modificationTime));
|
|
if(CrtTime) {
|
|
(*CrtTime) = *ChgTime;
|
|
}
|
|
|
|
} else if(Ident == TID_EXTENDED_FILE_ENTRY) {
|
|
PEXTENDED_FILE_ENTRY fe = (PEXTENDED_FILE_ENTRY)(FileInfo->Dloc->FileEntry);
|
|
|
|
if(AccTime) *AccTime = UDFTimeToNT(&(fe->accessTime));
|
|
if(AttrTime) *AttrTime = UDFTimeToNT(&(fe->attrTime));
|
|
if(ChgTime) *ChgTime = UDFTimeToNT(&(fe->modificationTime));
|
|
if(CrtTime) *CrtTime = UDFTimeToNT(&(fe->createTime));
|
|
|
|
}
|
|
if(CrtTime) {
|
|
if(!(*CrtTime))
|
|
KeQuerySystemTime((PLARGE_INTEGER)CrtTime);
|
|
if(AccTime && !(*AccTime)) (*AccTime) = *CrtTime;
|
|
if(AttrTime && !(*AttrTime)) (*AttrTime) = *CrtTime;
|
|
if(AccTime && !(*AccTime)) (*AccTime) = *CrtTime;
|
|
}
|
|
} // end UDFGetFileXTime()
|
|
|
|
VOID
|
|
UDFNormalizeFileName(
|
|
IN PUNICODE_STRING FName,
|
|
IN USHORT valueCRC
|
|
)
|
|
{
|
|
PWCHAR buffer;
|
|
USHORT len;
|
|
|
|
len = FName->Length/sizeof(WCHAR);
|
|
buffer = FName->Buffer;
|
|
|
|
// check for '', '.' & '..'
|
|
if(!len) return;
|
|
if(!buffer[len-1]) {
|
|
FName->Length-=sizeof(WCHAR);
|
|
len--;
|
|
}
|
|
if(!len) return;
|
|
if(buffer[0] == UNICODE_PERIOD) {
|
|
if(len == 1) return;
|
|
if((buffer[1] == UNICODE_PERIOD) && (len == 2)) return;
|
|
}
|
|
|
|
// check for trailing '.'
|
|
for(len--;len;len--) {
|
|
if( ((buffer[len] == UNICODE_PERIOD) || (buffer[len] == UNICODE_SPACE)) ) {
|
|
FName->Length-=sizeof(WCHAR);
|
|
buffer[len] = 0;
|
|
} else
|
|
break;
|
|
}
|
|
} // end UDFNormalizeFileName()
|
|
|
|
#ifndef _CONSOLE
|
|
|
|
void
|
|
__fastcall
|
|
UDFDOSNameOsNative(
|
|
IN OUT PUNICODE_STRING DosName,
|
|
IN PUNICODE_STRING UdfName,
|
|
IN BOOLEAN KeepIntact
|
|
)
|
|
{
|
|
PWCHAR dosName = DosName->Buffer;
|
|
PWCHAR udfName = UdfName->Buffer;
|
|
uint32 udfLen = UdfName->Length / sizeof(WCHAR);
|
|
GENERATE_NAME_CONTEXT Ctx;
|
|
|
|
if(KeepIntact &&
|
|
(udfLen <= 2) && (udfName[0] == UNICODE_PERIOD)) {
|
|
if((udfLen != 2) || (udfName[1] == UNICODE_PERIOD)) {
|
|
RtlCopyMemory(dosName, udfName, UdfName->Length);
|
|
DosName->Length = UdfName->Length;
|
|
return;
|
|
}
|
|
}
|
|
RtlZeroMemory(&Ctx, sizeof(GENERATE_NAME_CONTEXT));
|
|
RtlGenerate8dot3Name(UdfName, FALSE, &Ctx, DosName);
|
|
|
|
} // UDFDOSNameOsNative()
|
|
|
|
#endif //_CONSOLE
|
|
|
|
/*VOID
|
|
UDFNormalizeFileName(
|
|
IN PUNICODE_STRING FName,
|
|
IN USHORT valueCRC
|
|
)
|
|
{
|
|
WCHAR _newName[UDF_NAME_LEN+5];
|
|
PWCHAR newName = (PWCHAR)(&_newName);
|
|
PWCHAR udfName = FName->Buffer;
|
|
LONG udfLen = FName->Length >> 1;
|
|
|
|
LONG index, newIndex = 0, extIndex = 0, newExtIndex = 0, trailIndex = 0;
|
|
BOOLEAN needsCRC = FALSE, hasExt = FALSE;
|
|
WCHAR ext[UDF_EXT_SIZE], current;
|
|
|
|
// handle CurrentDir ('.') and ParentDir ('..') cases
|
|
if((udfLen <= 2) && (udfName[0] == UNICODE_PERIOD)) {
|
|
if((udfLen != 2) || (udfName[1] == UNICODE_PERIOD))
|
|
return;
|
|
}
|
|
|
|
for (index = 0 ; index < udfLen ; index++) {
|
|
current = udfName[index];
|
|
|
|
// Look for illegal or unprintable characters.
|
|
if (UDFIsIllegalChar(current) || !UnicodeIsPrint(current)) {
|
|
needsCRC = TRUE;
|
|
current = ILLEGAL_CHAR_MARK;
|
|
// Skip Illegal characters(even spaces),
|
|
// but not periods.
|
|
while(index+1 < udfLen &&
|
|
(UDFIsIllegalChar(udfName[index+1]) ||
|
|
!UnicodeIsPrint(udfName[index+1])) &&
|
|
udfName[index+1] != UNICODE_PERIOD)
|
|
index++;
|
|
}
|
|
|
|
// Record position of extension, if one is found.
|
|
if ((current == UNICODE_PERIOD) && ((udfLen - index -1) <= UDF_EXT_SIZE)) {
|
|
if (udfLen == index + 1) {
|
|
// A trailing period is NOT an extension.
|
|
hasExt = FALSE;
|
|
} else {
|
|
hasExt = TRUE;
|
|
extIndex = index;
|
|
newExtIndex = newIndex;
|
|
}
|
|
} else if((current != UNICODE_PERIOD) && (current != UNICODE_SPACE)) {
|
|
trailIndex = index;
|
|
}
|
|
|
|
// if (newIndex < MAXLEN) // tshi is always TRUE for WINNT
|
|
newName[newIndex] = current;
|
|
newIndex++;
|
|
|
|
// For OS2, 95 & NT, truncate any trailing periods and\or spaces.
|
|
if (trailIndex != (newIndex - 1)) {
|
|
newIndex = trailIndex + 1;
|
|
needsCRC = TRUE;
|
|
hasExt = FALSE; // Trailing period does not make an extension.
|
|
}
|
|
}
|
|
|
|
if (needsCRC) {
|
|
int localExtIndex = 0;
|
|
if (hasExt) {
|
|
int maxFilenameLen;
|
|
// Translate extension, and store it in ext.
|
|
for(index = 0; index<UDF_EXT_SIZE && extIndex + index +1 < udfLen; index++ ) {
|
|
current = udfName[extIndex + index + 1];
|
|
if (UDFIsIllegalChar(current) //|| !UnicodeIsPrint(current)) {
|
|
needsCRC = TRUE;
|
|
// Replace Illegal and non-displayable chars
|
|
// with underscore.
|
|
current = ILLEGAL_CHAR_MARK;
|
|
// Skip any other illegal or non-displayable
|
|
// characters.
|
|
while(index + 1 < UDF_EXT_SIZE &&
|
|
(UDFIsIllegalChar(udfName[extIndex + index + 2]) ||
|
|
!UnicodeIsPrint(udfName[extIndex + index + 2])) )
|
|
index++;
|
|
}
|
|
ext[localExtIndex++] = current;
|
|
}
|
|
// Truncate filename to leave room for extension and CRC.
|
|
maxFilenameLen = ((UDF_NAME_LEN - 4) - localExtIndex - 1);
|
|
if (newIndex > maxFilenameLen) {
|
|
newIndex = maxFilenameLen;
|
|
} else {
|
|
newIndex = newExtIndex;
|
|
}
|
|
} else if (newIndex > UDF_NAME_LEN - 5) {
|
|
//If no extension, make sure to leave room for CRC.
|
|
newIndex = UDF_NAME_LEN - 5;
|
|
}
|
|
newName[newIndex++] = UNICODE_CRC_MARK; // Add mark for CRC.
|
|
//Calculate CRC from original filename from FileIdentifier.
|
|
// valueCRC = UDFUnicodeCksum(fidName, fidNameLen);
|
|
// / Convert 16-bits of CRC to hex characters.
|
|
newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12];
|
|
newName[newIndex++] = hexChar[(valueCRC & 0x0f00) >> 8];
|
|
newName[newIndex++] = hexChar[(valueCRC & 0x00f0) >> 4];
|
|
newName[newIndex++] = hexChar[(valueCRC & 0x000f)];
|
|
// Place a translated extension at end, if found.
|
|
if (hasExt) {
|
|
newName[newIndex++] = UNICODE_PERIOD;
|
|
for (index = 0;index < localExtIndex ;index++ ) {
|
|
newName[newIndex++] = ext[index];
|
|
}
|
|
}
|
|
}
|
|
|
|
if(FName->Length == (USHORT)newIndex*sizeof(WCHAR)) {
|
|
RtlCopyMemory(FName->Buffer, newName, newIndex*sizeof(WCHAR));
|
|
return;
|
|
}
|
|
MyFreePool__(FName->Buffer);
|
|
FName->Buffer = (PWCHAR)MyAllocatePool__(UDF_FILENAME_MT, (newIndex+1)*sizeof(WCHAR));
|
|
if(FName->Buffer) {
|
|
FName->Buffer[newIndex] = 0;
|
|
RtlCopyMemory(FName->Buffer, newName, newIndex*sizeof(WCHAR));
|
|
}
|
|
FName->Length = (USHORT)newIndex*sizeof(WCHAR);
|
|
FName->MaximumLength = (USHORT)(newIndex+1)*sizeof(WCHAR);
|
|
}*/
|
|
|
|
/*PUDF_FILE_INFO
|
|
UDFAllocFileInfo(
|
|
return ExAllocateFromZone(&(UDFGlobalData.FileInfoZoneHeader));
|
|
)*/
|
|
|
|
#define STRING_BUFFER_ALIGNMENT (32)
|
|
#define STRING_BUFFER_ALIGN(sz) (((sz)+STRING_BUFFER_ALIGNMENT)&(~((ULONG)(STRING_BUFFER_ALIGNMENT-1))))
|
|
|
|
NTSTATUS
|
|
MyAppendUnicodeStringToString_(
|
|
IN PUNICODE_STRING Str1,
|
|
IN PUNICODE_STRING Str2
|
|
#ifdef UDF_TRACK_UNICODE_STR
|
|
,IN PCHAR Tag
|
|
#endif
|
|
)
|
|
{
|
|
PWCHAR tmp;
|
|
USHORT i;
|
|
|
|
#ifdef UDF_TRACK_UNICODE_STR
|
|
#define UDF_UNC_STR_TAG Tag
|
|
#else
|
|
#define UDF_UNC_STR_TAG "AppUStr"
|
|
#endif
|
|
|
|
tmp = Str1->Buffer;
|
|
i = Str1->Length + Str2->Length + sizeof(WCHAR);
|
|
ASSERT(Str1->MaximumLength);
|
|
if(i > Str1->MaximumLength) {
|
|
if(!MyReallocPool__((PCHAR)tmp, Str1->MaximumLength,
|
|
(PCHAR*)&tmp, STRING_BUFFER_ALIGN(i)*2) ) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
Str1->MaximumLength = i*2;
|
|
Str1->Buffer = tmp;
|
|
}
|
|
RtlCopyMemory(((PCHAR)tmp)+Str1->Length, Str2->Buffer, Str2->Length);
|
|
|
|
/* tmp = (PWCHAR)MyAllocatePoolTag__(NonPagedPool, i = Str1->Length + Str2->Length + sizeof(WCHAR), UDF_UNC_STR_TAG);
|
|
if(!tmp)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
RtlCopyMemory(tmp, Str1->Buffer, Str1->Length);
|
|
RtlCopyMemory(((PCHAR)tmp)+Str1->Length, Str2->Buffer, Str2->Length);*/
|
|
tmp[(i / sizeof(WCHAR)) - 1] = 0;
|
|
Str1->Length = i - sizeof(WCHAR);
|
|
//MyFreePool__(Str1->Buffer);
|
|
#ifdef UDF_DBG
|
|
if(Str1->Buffer && (Str1->Length >= 2*sizeof(WCHAR))) {
|
|
ASSERT((Str1->Buffer[0] != L'\\') || (Str1->Buffer[1] != L'\\'));
|
|
}
|
|
#endif // UDF_DBG
|
|
return STATUS_SUCCESS;
|
|
|
|
#undef UDF_UNC_STR_TAG
|
|
|
|
} // end MyAppendUnicodeStringToString()
|
|
|
|
NTSTATUS
|
|
MyAppendUnicodeToString_(
|
|
IN PUNICODE_STRING Str1,
|
|
IN PCWSTR Str2
|
|
#ifdef UDF_TRACK_UNICODE_STR
|
|
,IN PCHAR Tag
|
|
#endif
|
|
)
|
|
{
|
|
PWCHAR tmp;
|
|
USHORT i;
|
|
|
|
#ifdef UDF_TRACK_UNICODE_STR
|
|
#define UDF_UNC_STR_TAG Tag
|
|
#else
|
|
#define UDF_UNC_STR_TAG "AppStr"
|
|
#endif
|
|
|
|
#if defined(_X86_) && defined(_MSC_VER) && !defined(__clang__)
|
|
|
|
__asm push ebx
|
|
__asm push esi
|
|
|
|
__asm xor ebx,ebx
|
|
__asm mov esi,Str2
|
|
Scan_1:
|
|
__asm cmp [word ptr esi+ebx],0
|
|
__asm je EO_Scan
|
|
__asm add ebx,2
|
|
__asm jmp Scan_1
|
|
EO_Scan:
|
|
__asm mov i,bx
|
|
|
|
__asm pop esi
|
|
__asm pop ebx
|
|
|
|
#else // NO X86 optimization, use generic C/C++
|
|
|
|
i=0;
|
|
while(Str2[i]) {
|
|
i++;
|
|
}
|
|
i *= sizeof(WCHAR);
|
|
|
|
#endif // _X86_
|
|
|
|
tmp = Str1->Buffer;
|
|
ASSERT(Str1->MaximumLength);
|
|
if((Str1->Length+i+sizeof(WCHAR)) > Str1->MaximumLength) {
|
|
if(!MyReallocPool__((PCHAR)tmp, Str1->MaximumLength,
|
|
(PCHAR*)&tmp, STRING_BUFFER_ALIGN(i + Str1->Length + sizeof(WCHAR))*2 ) ) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
Str1->MaximumLength = STRING_BUFFER_ALIGN(i + sizeof(WCHAR))*2;
|
|
Str1->Buffer = tmp;
|
|
}
|
|
RtlCopyMemory(((PCHAR)tmp)+Str1->Length, Str2, i);
|
|
i+=Str1->Length;
|
|
tmp[(i / sizeof(WCHAR))] = 0;
|
|
Str1->Length = i;
|
|
#ifdef UDF_DBG
|
|
/* if(Str1->Buffer && (Str1->Length >= 2*sizeof(WCHAR))) {
|
|
ASSERT((Str1->Buffer[0] != L'\\') || (Str1->Buffer[1] != L'\\'));
|
|
}*/
|
|
#endif // UDF_DBG
|
|
return STATUS_SUCCESS;
|
|
|
|
#undef UDF_UNC_STR_TAG
|
|
|
|
} // end MyAppendUnicodeToString_()
|
|
|
|
NTSTATUS
|
|
MyInitUnicodeString(
|
|
IN PUNICODE_STRING Str1,
|
|
IN PCWSTR Str2
|
|
)
|
|
{
|
|
|
|
USHORT i;
|
|
|
|
#if defined(_X86_) && defined(_MSC_VER) && !defined(__clang__)
|
|
|
|
__asm push ebx
|
|
__asm push esi
|
|
|
|
__asm xor ebx,ebx
|
|
__asm mov esi,Str2
|
|
Scan_1:
|
|
__asm cmp [word ptr esi+ebx],0
|
|
__asm je EO_Scan
|
|
__asm add ebx,2
|
|
__asm jmp Scan_1
|
|
EO_Scan:
|
|
__asm mov i,bx
|
|
|
|
__asm pop esi
|
|
__asm pop ebx
|
|
|
|
#else // NO X86 optimization, use generic C/C++
|
|
|
|
i=0;
|
|
while(Str2[i]) {
|
|
i++;
|
|
}
|
|
i *= sizeof(WCHAR);
|
|
|
|
#endif // _X86_
|
|
|
|
Str1->MaximumLength = STRING_BUFFER_ALIGN((Str1->Length = i) + sizeof(WCHAR));
|
|
Str1->Buffer = (PWCHAR)MyAllocatePool__(NonPagedPool, Str1->MaximumLength);
|
|
if(!Str1->Buffer)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
RtlCopyMemory(Str1->Buffer, Str2, i);
|
|
Str1->Buffer[i/sizeof(WCHAR)] = 0;
|
|
return STATUS_SUCCESS;
|
|
|
|
} // end MyInitUnicodeString()
|
|
|
|
NTSTATUS
|
|
MyCloneUnicodeString(
|
|
IN PUNICODE_STRING Str1,
|
|
IN PUNICODE_STRING Str2
|
|
)
|
|
{
|
|
Str1->MaximumLength = STRING_BUFFER_ALIGN((Str1->Length = Str2->Length) + sizeof(WCHAR));
|
|
Str1->Buffer = (PWCHAR)MyAllocatePool__(NonPagedPool, Str1->MaximumLength);
|
|
if(!Str1->Buffer)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
ASSERT(Str2->Buffer);
|
|
RtlCopyMemory(Str1->Buffer, Str2->Buffer, Str2->Length);
|
|
Str1->Buffer[Str1->Length/sizeof(WCHAR)] = 0;
|
|
return STATUS_SUCCESS;
|
|
|
|
} // end MyCloneUnicodeString()
|
|
|
|
/*
|
|
This routine checks do we needn't read something from disk to
|
|
obtain Attributes & so on
|
|
*/
|
|
BOOLEAN
|
|
UDFIsDirInfoCached(
|
|
IN PVCB Vcb,
|
|
IN PUDF_FILE_INFO DirInfo
|
|
)
|
|
{
|
|
PDIR_INDEX_HDR hDirNdx = DirInfo->Dloc->DirIndex;
|
|
PDIR_INDEX_ITEM DirNdx;
|
|
for(uint_di i=2; (DirNdx = UDFDirIndex(hDirNdx,i)); i++) {
|
|
if(!(DirNdx->FI_Flags & UDF_FI_FLAG_SYS_ATTR) ||
|
|
(DirNdx->FI_Flags & UDF_FI_FLAG_LINKED)) return FALSE;
|
|
}
|
|
return TRUE;
|
|
} // end UDFIsDirInfoCached()
|
|
|
|
#ifndef UDF_READ_ONLY_BUILD
|
|
NTSTATUS
|
|
UDFDoesOSAllowFileToBeTargetForRename__(
|
|
IN PUDF_FILE_INFO FileInfo
|
|
)
|
|
{
|
|
#ifndef _CONSOLE
|
|
NTSTATUS RC;
|
|
#endif //_CONSOLE
|
|
|
|
if(UDFIsADirectory(FileInfo))
|
|
return STATUS_ACCESS_DENIED;
|
|
if(!FileInfo->ParentFile)
|
|
return STATUS_ACCESS_DENIED;
|
|
|
|
if(UDFAttributesToNT(UDFDirIndex(UDFGetDirIndexByFileInfo(FileInfo),FileInfo->Index),
|
|
FileInfo->Dloc->FileEntry) & FILE_ATTRIBUTE_READONLY)
|
|
return STATUS_ACCESS_DENIED;
|
|
|
|
if(!FileInfo->Fcb)
|
|
return STATUS_SUCCESS;
|
|
#ifndef _CONSOLE
|
|
RC = UDFCheckAccessRights(NULL, NULL, FileInfo->Fcb, NULL, DELETE, 0);
|
|
if(!NT_SUCCESS(RC))
|
|
return RC;
|
|
#endif //_CONSOLE
|
|
if(!FileInfo->Fcb)
|
|
return STATUS_SUCCESS;
|
|
// RC = UDFMarkStreamsForDeletion(FileInfo->Fcb->Vcb, FileInfo->Fcb, TRUE); // Delete
|
|
/* RC = UDFSetDispositionInformation(FileInfo->Fcb, NULL,
|
|
FileInfo->Fcb->Vcb, NULL, TRUE);
|
|
if(NT_SUCCESS(RC)) {
|
|
FileInfo->Fcb->FCBFlags |= UDF_FCB_DELETED;
|
|
if(UDFGetFileLinkCount(FileInfo) <= 1) {
|
|
FileInfo->Fcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_DELETED;
|
|
}
|
|
}
|
|
return RC;*/
|
|
return STATUS_ACCESS_DENIED;
|
|
|
|
} // end UDFDoesOSAllowFileToBeTargetForRename__()
|
|
|
|
NTSTATUS
|
|
UDFDoesOSAllowFileToBeUnlinked__(
|
|
IN PUDF_FILE_INFO FileInfo
|
|
)
|
|
{
|
|
PDIR_INDEX_HDR hCurDirNdx;
|
|
PDIR_INDEX_ITEM CurDirNdx;
|
|
uint_di i;
|
|
// IO_STATUS_BLOCK IoStatus;
|
|
|
|
ASSERT(FileInfo->Dloc);
|
|
|
|
if(!FileInfo->ParentFile)
|
|
return STATUS_CANNOT_DELETE;
|
|
if(FileInfo->Dloc->SDirInfo)
|
|
return STATUS_CANNOT_DELETE;
|
|
if(!UDFIsADirectory(FileInfo))
|
|
return STATUS_SUCCESS;
|
|
|
|
// UDFFlushAFile(FileInfo->Fcb, NULL, &IoStatus, 0);
|
|
hCurDirNdx = FileInfo->Dloc->DirIndex;
|
|
// check if we can delete all files
|
|
for(i=2; (CurDirNdx = UDFDirIndex(hCurDirNdx,i)); i++) {
|
|
// try to open Stream
|
|
if(CurDirNdx->FileInfo)
|
|
return STATUS_CANNOT_DELETE;
|
|
}
|
|
// return UDFCheckAccessRights(NULL, NULL, FileInfo->Fcb, NULL, DELETE, 0);
|
|
return STATUS_SUCCESS;
|
|
} // end UDFDoesOSAllowFileToBeUnlinked__()
|
|
|
|
NTSTATUS
|
|
UDFDoesOSAllowFilePretendDeleted__(
|
|
IN PUDF_FILE_INFO FileInfo
|
|
)
|
|
{
|
|
PDIR_INDEX_HDR hDirNdx = UDFGetDirIndexByFileInfo(FileInfo);
|
|
if(!hDirNdx) return STATUS_CANNOT_DELETE;
|
|
PDIR_INDEX_ITEM DirNdx = UDFDirIndex(hDirNdx, FileInfo->Index);
|
|
if(!DirNdx) return STATUS_CANNOT_DELETE;
|
|
// we can't hide file that is not marked as deleted
|
|
if(!(DirNdx->FileCharacteristics & FILE_DELETED)) {
|
|
BrutePoint();
|
|
|
|
#ifndef _CONSOLE
|
|
if(!(FileInfo->Fcb->FCBFlags & (UDF_FCB_DELETE_ON_CLOSE |
|
|
UDF_FCB_DELETED) ))
|
|
#endif //_CONSOLE
|
|
|
|
return STATUS_CANNOT_DELETE;
|
|
}
|
|
return STATUS_SUCCESS;
|
|
}
|
|
#endif //UDF_READ_ONLY_BUILD
|
|
|