Something went wrong. Try again.
Reactos
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042////////////////////////////////////////////////////////////////////// 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 */LONGLONGUDFTimeToNT( 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 */VOIDUDFTimeToUDF( 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()
/* */ULONGUDFAttributesToNT( 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()
/* */VOIDUDFAttributesToUDF( 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) */NTSTATUSUDFFileDirInfoToNT( 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 */VOIDUDFSetFileXTime( 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 */VOIDUDFGetFileXTime( 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()
VOIDUDFNormalizeFileName( 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__fastcallUDFDOSNameOsNative( 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
/*VOIDUDFNormalizeFileName( 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_INFOUDFAllocFileInfo( return ExAllocateFromZone(&(UDFGlobalData.FileInfoZoneHeader));)*/
#define STRING_BUFFER_ALIGNMENT (32)#define STRING_BUFFER_ALIGN(sz) (((sz)+STRING_BUFFER_ALIGNMENT)&(~((ULONG)(STRING_BUFFER_ALIGNMENT-1))))
NTSTATUSMyAppendUnicodeStringToString_( 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()
NTSTATUSMyAppendUnicodeToString_( 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,Str2Scan_1: __asm cmp [word ptr esi+ebx],0 __asm je EO_Scan __asm add ebx,2 __asm jmp Scan_1EO_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_()
NTSTATUSMyInitUnicodeString( 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,Str2Scan_1: __asm cmp [word ptr esi+ebx],0 __asm je EO_Scan __asm add ebx,2 __asm jmp Scan_1EO_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()
NTSTATUSMyCloneUnicodeString( 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 */BOOLEANUDFIsDirInfoCached( 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_BUILDNTSTATUSUDFDoesOSAllowFileToBeTargetForRename__( 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__()
NTSTATUSUDFDoesOSAllowFileToBeUnlinked__( 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__()
NTSTATUSUDFDoesOSAllowFilePretendDeleted__( 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