1c2c66affSColin Finck //////////////////////////////////////////////////////////////////// 2c2c66affSColin Finck // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine 3c2c66affSColin Finck // All rights reserved 4c2c66affSColin Finck // This file was released under the GPLv2 on June 2015. 5c2c66affSColin Finck //////////////////////////////////////////////////////////////////// 6c2c66affSColin Finck /************************************************************************* 7c2c66affSColin Finck * 8c2c66affSColin Finck * File: Sys_Spec.cpp 9c2c66affSColin Finck * 10c2c66affSColin Finck * Module: UDF File System Driver 11c2c66affSColin Finck * (both User and Kernel mode execution) 12c2c66affSColin Finck * 13c2c66affSColin Finck * Description: 14c2c66affSColin Finck * Contains system-secific code 15c2c66affSColin Finck * 16c2c66affSColin Finck *************************************************************************/ 17c2c66affSColin Finck 18c2c66affSColin Finck 19c2c66affSColin Finck /* 20c2c66affSColin Finck This routine converts UDF timestamp to NT time 21c2c66affSColin Finck */ 22c2c66affSColin Finck LONGLONG 23c2c66affSColin Finck UDFTimeToNT( 24c2c66affSColin Finck IN PUDF_TIME_STAMP UdfTime 25c2c66affSColin Finck ) 26c2c66affSColin Finck { 27c2c66affSColin Finck LONGLONG NtTime; 28c2c66affSColin Finck TIME_FIELDS TimeFields; 29c2c66affSColin Finck 30c2c66affSColin Finck TimeFields.Milliseconds = (USHORT)(UdfTime->centiseconds * 10 + UdfTime->hundredsOfMicroseconds / 100); 31c2c66affSColin Finck TimeFields.Second = (USHORT)(UdfTime->second); 32c2c66affSColin Finck TimeFields.Minute = (USHORT)(UdfTime->minute); 33c2c66affSColin Finck TimeFields.Hour = (USHORT)(UdfTime->hour); 34c2c66affSColin Finck TimeFields.Day = (USHORT)(UdfTime->day); 35c2c66affSColin Finck TimeFields.Month = (USHORT)(UdfTime->month); 36c2c66affSColin Finck TimeFields.Year = (USHORT)((UdfTime->year < 1601) ? 1601 : UdfTime->year); 37c2c66affSColin Finck 38c2c66affSColin Finck if (!RtlTimeFieldsToTime(&TimeFields, (PLARGE_INTEGER)&NtTime)) { 39c2c66affSColin Finck NtTime = 0; 40c2c66affSColin Finck } else { 41c2c66affSColin Finck ExLocalTimeToSystemTime( (PLARGE_INTEGER)&NtTime, (PLARGE_INTEGER)&NtTime ); 42c2c66affSColin Finck } 43c2c66affSColin Finck 44c2c66affSColin Finck return NtTime; 45c2c66affSColin Finck } // end UDFTimeToNT() 46c2c66affSColin Finck 47c2c66affSColin Finck 48c2c66affSColin Finck /* 49c2c66affSColin Finck This routine converts NT time to UDF timestamp 50c2c66affSColin Finck */ 51c2c66affSColin Finck VOID 52c2c66affSColin Finck UDFTimeToUDF( 53c2c66affSColin Finck IN LONGLONG NtTime, 54c2c66affSColin Finck OUT PUDF_TIME_STAMP UdfTime 55c2c66affSColin Finck ) 56c2c66affSColin Finck { 57c2c66affSColin Finck if(!NtTime) return; 58c2c66affSColin Finck LONGLONG LocalTime; 59c2c66affSColin Finck 60c2c66affSColin Finck TIME_FIELDS TimeFields; 61c2c66affSColin Finck 62c2c66affSColin Finck ExSystemTimeToLocalTime( (PLARGE_INTEGER)&NtTime, (PLARGE_INTEGER)&LocalTime ); 63c2c66affSColin Finck RtlTimeToTimeFields( (PLARGE_INTEGER)&LocalTime, &TimeFields ); 64c2c66affSColin Finck 65c2c66affSColin Finck LocalTime /= 10; // microseconds 66c2c66affSColin Finck UdfTime->microseconds = (UCHAR)(NtTime % 100); 67c2c66affSColin Finck LocalTime /= 100; // hundreds of microseconds 68c2c66affSColin Finck UdfTime->hundredsOfMicroseconds = (UCHAR)(NtTime % 100); 69c2c66affSColin Finck LocalTime /= 100; // centiseconds 70c2c66affSColin Finck UdfTime->centiseconds = (UCHAR)(TimeFields.Milliseconds / 10); 71c2c66affSColin Finck UdfTime->second = (UCHAR)(TimeFields.Second); 72c2c66affSColin Finck UdfTime->minute = (UCHAR)(TimeFields.Minute); 73c2c66affSColin Finck UdfTime->hour = (UCHAR)(TimeFields.Hour); 74c2c66affSColin Finck UdfTime->day = (UCHAR)(TimeFields.Day); 75c2c66affSColin Finck UdfTime->month = (UCHAR)(TimeFields.Month); 76c2c66affSColin Finck UdfTime->year = (USHORT)(TimeFields.Year); 77c2c66affSColin Finck UdfTime->typeAndTimezone = (TIMESTAMP_TYPE_LOCAL << 14); 78c2c66affSColin Finck } // end UDFTimeToUDF() 79c2c66affSColin Finck 80c2c66affSColin Finck /* 81c2c66affSColin Finck */ 82c2c66affSColin Finck ULONG 83c2c66affSColin Finck UDFAttributesToNT( 84c2c66affSColin Finck IN PDIR_INDEX_ITEM FileDirNdx, 85c2c66affSColin Finck IN tag* FileEntry 86c2c66affSColin Finck ) 87c2c66affSColin Finck { 88c2c66affSColin Finck ASSERT(FileDirNdx); 89c2c66affSColin Finck if( (FileDirNdx->FI_Flags & UDF_FI_FLAG_SYS_ATTR) && 90c2c66affSColin Finck !(FileDirNdx->FI_Flags & UDF_FI_FLAG_LINKED)) 91c2c66affSColin Finck return FileDirNdx->SysAttr; 92c2c66affSColin Finck 93c2c66affSColin Finck ULONG NTAttr = 0; 94c2c66affSColin Finck ULONG attr = 0; //permissions 95c2c66affSColin Finck USHORT Flags = 0; 96c2c66affSColin Finck USHORT Type = 0; 97c2c66affSColin Finck UCHAR FCharact = 0; 98c2c66affSColin Finck 99c2c66affSColin Finck if(!FileEntry) { 100c2c66affSColin Finck if(!FileDirNdx->FileInfo) 101c2c66affSColin Finck return 0; 102c2c66affSColin Finck ValidateFileInfo(FileDirNdx->FileInfo); 103c2c66affSColin Finck FileEntry = FileDirNdx->FileInfo->Dloc->FileEntry; 104c2c66affSColin Finck } 105c2c66affSColin Finck if(FileEntry->tagIdent == TID_FILE_ENTRY) { 106c2c66affSColin Finck attr = ((PFILE_ENTRY)FileEntry)->permissions; 107c2c66affSColin Finck Flags = ((PFILE_ENTRY)FileEntry)->icbTag.flags; 108c2c66affSColin Finck Type = ((PFILE_ENTRY)FileEntry)->icbTag.fileType; 109c2c66affSColin Finck if(((PFILE_ENTRY)FileEntry)->fileLinkCount > 1) 110c2c66affSColin Finck FileDirNdx->FI_Flags |= UDF_FI_FLAG_LINKED; 111c2c66affSColin Finck } else { 112c2c66affSColin Finck attr = ((PEXTENDED_FILE_ENTRY)FileEntry)->permissions; 113c2c66affSColin Finck Flags = ((PEXTENDED_FILE_ENTRY)FileEntry)->icbTag.flags; 114c2c66affSColin Finck Type = ((PEXTENDED_FILE_ENTRY)FileEntry)->icbTag.fileType; 115c2c66affSColin Finck if(((PEXTENDED_FILE_ENTRY)FileEntry)->fileLinkCount > 1) 116c2c66affSColin Finck FileDirNdx->FI_Flags |= UDF_FI_FLAG_LINKED; 117c2c66affSColin Finck } 118c2c66affSColin Finck FCharact = FileDirNdx->FileCharacteristics; 119c2c66affSColin Finck 120c2c66affSColin Finck if(Flags & ICB_FLAG_SYSTEM) NTAttr |= FILE_ATTRIBUTE_SYSTEM; 121c2c66affSColin Finck if(Flags & ICB_FLAG_ARCHIVE) NTAttr |= FILE_ATTRIBUTE_ARCHIVE; 122c2c66affSColin Finck if((Type == UDF_FILE_TYPE_DIRECTORY) || 123c2c66affSColin Finck (Type == UDF_FILE_TYPE_STREAMDIR) || 124c2c66affSColin Finck (FCharact & FILE_DIRECTORY)) { 125c2c66affSColin Finck NTAttr |= FILE_ATTRIBUTE_DIRECTORY; 126c2c66affSColin Finck #ifdef UDF_DBG 127c2c66affSColin Finck } else { 128c2c66affSColin Finck //NTAttr |= FILE_ATTRIBUTE_NORMAL; 129c2c66affSColin Finck #endif 130c2c66affSColin Finck } 131c2c66affSColin Finck if(FCharact & FILE_HIDDEN) NTAttr |= FILE_ATTRIBUTE_HIDDEN; 132c2c66affSColin Finck if( !(attr & PERM_O_WRITE) && 133c2c66affSColin Finck !(attr & PERM_G_WRITE) && 134c2c66affSColin Finck !(attr & PERM_U_WRITE) && 135c2c66affSColin Finck !(attr & PERM_O_DELETE) && 136c2c66affSColin Finck !(attr & PERM_G_DELETE) && 137c2c66affSColin Finck !(attr & PERM_U_DELETE) ) { 138c2c66affSColin Finck NTAttr |= FILE_ATTRIBUTE_READONLY; 139c2c66affSColin Finck } 140c2c66affSColin Finck FileDirNdx->SysAttr = NTAttr; 141c2c66affSColin Finck return NTAttr; 142c2c66affSColin Finck } // end UDFAttributesToNT() 143c2c66affSColin Finck 144c2c66affSColin Finck /* 145c2c66affSColin Finck */ 146c2c66affSColin Finck VOID 147c2c66affSColin Finck UDFAttributesToUDF( 148c2c66affSColin Finck IN PDIR_INDEX_ITEM FileDirNdx, 149c2c66affSColin Finck IN tag* FileEntry, 150c2c66affSColin Finck IN ULONG NTAttr 151c2c66affSColin Finck ) 152c2c66affSColin Finck { 153c2c66affSColin Finck PULONG attr; //permissions 154c2c66affSColin Finck PUSHORT Flags; 155c2c66affSColin Finck PUCHAR Type; 156c2c66affSColin Finck PUCHAR FCharact; 157c2c66affSColin Finck 158c2c66affSColin Finck NTAttr &= UDF_VALID_FILE_ATTRIBUTES; 159c2c66affSColin Finck 160c2c66affSColin Finck if(!FileEntry) { 161c2c66affSColin Finck ASSERT(FileDirNdx); 162c2c66affSColin Finck if(!FileDirNdx->FileInfo) 163c2c66affSColin Finck return; 164c2c66affSColin Finck ValidateFileInfo(FileDirNdx->FileInfo); 165c2c66affSColin Finck FileEntry = FileDirNdx->FileInfo->Dloc->FileEntry; 166c2c66affSColin Finck FileDirNdx->FileInfo->Dloc->FE_Flags |= UDF_FE_FLAG_FE_MODIFIED; 167c2c66affSColin Finck } 168c2c66affSColin Finck if(FileEntry->tagIdent == TID_FILE_ENTRY) { 169c2c66affSColin Finck attr = &((PFILE_ENTRY)FileEntry)->permissions; 170c2c66affSColin Finck Flags = &((PFILE_ENTRY)FileEntry)->icbTag.flags; 171c2c66affSColin Finck Type = &((PFILE_ENTRY)FileEntry)->icbTag.fileType; 172c2c66affSColin Finck } else { 173c2c66affSColin Finck attr = &((PEXTENDED_FILE_ENTRY)FileEntry)->permissions; 174c2c66affSColin Finck Flags = &((PEXTENDED_FILE_ENTRY)FileEntry)->icbTag.flags; 175c2c66affSColin Finck Type = &((PEXTENDED_FILE_ENTRY)FileEntry)->icbTag.fileType; 176c2c66affSColin Finck } 177c2c66affSColin Finck FCharact = &(FileDirNdx->FileCharacteristics); 178c2c66affSColin Finck 179c2c66affSColin Finck if((*FCharact & FILE_DIRECTORY) || 180c2c66affSColin Finck (*Type == UDF_FILE_TYPE_STREAMDIR) || 181c2c66affSColin Finck (*Type == UDF_FILE_TYPE_DIRECTORY)) { 182c2c66affSColin Finck *FCharact |= FILE_DIRECTORY; 183c2c66affSColin Finck if(*Type != UDF_FILE_TYPE_STREAMDIR) 184c2c66affSColin Finck *Type = UDF_FILE_TYPE_DIRECTORY; 185c2c66affSColin Finck *attr |= (PERM_O_EXEC | PERM_G_EXEC | PERM_U_EXEC); 186c2c66affSColin Finck NTAttr |= FILE_ATTRIBUTE_DIRECTORY; 187c2c66affSColin Finck NTAttr &= ~FILE_ATTRIBUTE_NORMAL; 188c2c66affSColin Finck } else { 189c2c66affSColin Finck *FCharact &= ~FILE_DIRECTORY; 190c2c66affSColin Finck *Type = UDF_FILE_TYPE_REGULAR; 191c2c66affSColin Finck *attr &= ~(PERM_O_EXEC | PERM_G_EXEC | PERM_U_EXEC); 192c2c66affSColin Finck } 193c2c66affSColin Finck 194c2c66affSColin Finck if(NTAttr & FILE_ATTRIBUTE_SYSTEM) { 195c2c66affSColin Finck *Flags |= ICB_FLAG_SYSTEM; 196c2c66affSColin Finck } else { 197c2c66affSColin Finck *Flags &= ~ICB_FLAG_SYSTEM; 198c2c66affSColin Finck } 199c2c66affSColin Finck if(NTAttr & FILE_ATTRIBUTE_ARCHIVE) { 200c2c66affSColin Finck *Flags |= ICB_FLAG_ARCHIVE; 201c2c66affSColin Finck } else { 202c2c66affSColin Finck *Flags &= ~ICB_FLAG_ARCHIVE; 203c2c66affSColin Finck } 204c2c66affSColin Finck if(NTAttr & FILE_ATTRIBUTE_HIDDEN) { 205c2c66affSColin Finck *FCharact |= FILE_HIDDEN; 206c2c66affSColin Finck } else { 207c2c66affSColin Finck *FCharact &= ~FILE_HIDDEN; 208c2c66affSColin Finck } 209c2c66affSColin Finck *attr |= (PERM_O_READ | PERM_G_READ | PERM_U_READ); 210c2c66affSColin Finck if(!(NTAttr & FILE_ATTRIBUTE_READONLY)) { 211c2c66affSColin Finck *attr |= (PERM_O_WRITE | PERM_G_WRITE | PERM_U_WRITE | 212c2c66affSColin Finck PERM_O_DELETE | PERM_G_DELETE | PERM_U_DELETE | 213c2c66affSColin Finck PERM_O_CHATTR | PERM_G_CHATTR | PERM_U_CHATTR); 214c2c66affSColin Finck } else { 215c2c66affSColin Finck *attr &= ~(PERM_O_WRITE | PERM_G_WRITE | PERM_U_WRITE | 216c2c66affSColin Finck PERM_O_DELETE | PERM_G_DELETE | PERM_U_DELETE | 217c2c66affSColin Finck PERM_O_CHATTR | PERM_G_CHATTR | PERM_U_CHATTR); 218c2c66affSColin Finck } 219c2c66affSColin Finck FileDirNdx->SysAttr = NTAttr; 220c2c66affSColin Finck if(FileDirNdx->FileInfo) 221c2c66affSColin Finck FileDirNdx->FileInfo->Dloc->FE_Flags |= UDF_FE_FLAG_FE_MODIFIED; 222c2c66affSColin Finck FileDirNdx->FI_Flags |= UDF_FI_FLAG_FI_MODIFIED; 223c2c66affSColin Finck return; 224c2c66affSColin Finck } // end UDFAttributesToUDF() 225c2c66affSColin Finck 226c2c66affSColin Finck #ifndef _CONSOLE 227c2c66affSColin Finck /* 228c2c66affSColin Finck This routine fills PFILE_BOTH_DIR_INFORMATION structure (NT) 229c2c66affSColin Finck */ 230c2c66affSColin Finck NTSTATUS 231c2c66affSColin Finck UDFFileDirInfoToNT( 232c2c66affSColin Finck IN PVCB Vcb, 233c2c66affSColin Finck IN PDIR_INDEX_ITEM FileDirNdx, 234c2c66affSColin Finck OUT PFILE_BOTH_DIR_INFORMATION NTFileInfo 235c2c66affSColin Finck ) 236c2c66affSColin Finck { 237c2c66affSColin Finck PFILE_ENTRY FileEntry; 238c2c66affSColin Finck UNICODE_STRING UdfName; 239c2c66affSColin Finck UNICODE_STRING DosName; 240c2c66affSColin Finck PEXTENDED_FILE_ENTRY ExFileEntry; 241c2c66affSColin Finck USHORT Ident; 242*d97e4909SVictor Martinez BOOLEAN ReadSizes = FALSE; 243c2c66affSColin Finck NTSTATUS status; 244c2c66affSColin Finck PtrUDFNTRequiredFCB NtReqFcb; 245c2c66affSColin Finck 246c2c66affSColin Finck UDFPrint(("@=%#x, FileDirNdx %x\n", &Vcb, FileDirNdx)); 247c2c66affSColin Finck 248c334c17dSTimo Kreuzer ASSERT((ULONG_PTR)NTFileInfo > 0x1000); 249c2c66affSColin Finck RtlZeroMemory(NTFileInfo, sizeof(FILE_BOTH_DIR_INFORMATION)); 250c2c66affSColin Finck 251c2c66affSColin Finck DosName.Buffer = (PWCHAR)&(NTFileInfo->ShortName); 252c2c66affSColin Finck DosName.MaximumLength = sizeof(NTFileInfo->ShortName); // 12*sizeof(WCHAR) 253c2c66affSColin Finck 254c2c66affSColin Finck _SEH2_TRY { 255c2c66affSColin Finck UDFPrint((" DirInfoToNT: %*.*S\n", FileDirNdx->FName.Length/sizeof(WCHAR), FileDirNdx->FName.Length/sizeof(WCHAR), FileDirNdx->FName)); 256c2c66affSColin Finck } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { 257c2c66affSColin Finck UDFPrint((" DirInfoToNT: exception when printing file name\n")); 258c2c66affSColin Finck } _SEH2_END; 259c2c66affSColin Finck 260c2c66affSColin Finck if(FileDirNdx->FileInfo) { 261c2c66affSColin Finck UDFPrint((" FileInfo\n")); 262c2c66affSColin Finck // validate FileInfo 263c2c66affSColin Finck ValidateFileInfo(FileDirNdx->FileInfo); 264c2c66affSColin Finck if(UDFGetFileLinkCount(FileDirNdx->FileInfo) > 1) 265c2c66affSColin Finck FileDirNdx->FI_Flags |= UDF_FI_FLAG_LINKED; 266c2c66affSColin Finck FileEntry = (PFILE_ENTRY)(FileDirNdx->FileInfo->Dloc->FileEntry); 267c2c66affSColin Finck // read required sizes from Fcb (if any) if file is not linked 268c2c66affSColin Finck // otherwise we should read them from FileEntry 269c2c66affSColin Finck if(FileDirNdx->FileInfo->Fcb) { 270c2c66affSColin Finck UDFPrint((" Fcb\n")); 271c2c66affSColin Finck NtReqFcb = FileDirNdx->FileInfo->Fcb->NTRequiredFCB; 272c2c66affSColin Finck NTFileInfo->CreationTime.QuadPart = NtReqFcb->CreationTime.QuadPart; 273c2c66affSColin Finck NTFileInfo->LastWriteTime.QuadPart = NtReqFcb->LastWriteTime.QuadPart; 274c2c66affSColin Finck NTFileInfo->LastAccessTime.QuadPart = NtReqFcb->LastAccessTime.QuadPart; 275c2c66affSColin Finck NTFileInfo->ChangeTime.QuadPart = NtReqFcb->ChangeTime.QuadPart; 276c2c66affSColin Finck // NTFileInfo->AllocationSize.QuadPart = NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart; 277c2c66affSColin Finck NTFileInfo->AllocationSize.QuadPart = FileDirNdx->AllocationSize; 278c2c66affSColin Finck /* FileDirNdx->FileSize = 279c2c66affSColin Finck NTFileInfo->EndOfFile.QuadPart = NtReqFcb->CommonFCBHeader.FileSize.QuadPart;*/ 280c2c66affSColin Finck NTFileInfo->EndOfFile.QuadPart = FileDirNdx->FileSize; 281c2c66affSColin Finck if(FileDirNdx->FI_Flags & UDF_FI_FLAG_SYS_ATTR) { 282c2c66affSColin Finck UDFPrint((" SYS_ATTR\n")); 283c2c66affSColin Finck NTFileInfo->FileAttributes = FileDirNdx->SysAttr; 284c2c66affSColin Finck goto get_name_only; 285c2c66affSColin Finck } 286c2c66affSColin Finck FileDirNdx->CreationTime = NTFileInfo->CreationTime.QuadPart; 287c2c66affSColin Finck FileDirNdx->LastWriteTime = NTFileInfo->LastWriteTime.QuadPart; 288c2c66affSColin Finck FileDirNdx->LastAccessTime = NTFileInfo->LastAccessTime.QuadPart; 289c2c66affSColin Finck FileDirNdx->ChangeTime = NTFileInfo->ChangeTime.QuadPart; 290c2c66affSColin Finck goto get_attr_only; 291c2c66affSColin Finck } 292c2c66affSColin Finck ASSERT(FileEntry); 293c2c66affSColin Finck } else if(!(FileDirNdx->FI_Flags & UDF_FI_FLAG_SYS_ATTR) || 294c2c66affSColin Finck (FileDirNdx->FI_Flags & UDF_FI_FLAG_LINKED)) { 295c2c66affSColin Finck LONG_AD feloc; 296c2c66affSColin Finck 297c2c66affSColin Finck UDFPrint((" !SYS_ATTR\n")); 298c2c66affSColin Finck FileEntry = (PFILE_ENTRY)MyAllocatePool__(NonPagedPool, Vcb->LBlockSize); 299c2c66affSColin Finck if(!FileEntry) return STATUS_INSUFFICIENT_RESOURCES; 300c2c66affSColin Finck 301c2c66affSColin Finck feloc.extLength = Vcb->LBlockSize; 302c2c66affSColin Finck feloc.extLocation = FileDirNdx->FileEntryLoc; 303c2c66affSColin Finck 304c2c66affSColin Finck if(!NT_SUCCESS(status = UDFReadFileEntry(Vcb, &feloc, FileEntry, &Ident))) { 305c2c66affSColin Finck UDFPrint((" !UDFReadFileEntry\n")); 306c2c66affSColin Finck MyFreePool__(FileEntry); 307c2c66affSColin Finck FileEntry = NULL; 308c2c66affSColin Finck goto get_name_only; 309c2c66affSColin Finck } 310c2c66affSColin Finck ReadSizes = TRUE; 311c2c66affSColin Finck } else { 312c2c66affSColin Finck UDFPrint((" FileDirNdx\n")); 313c2c66affSColin Finck NTFileInfo->CreationTime.QuadPart = FileDirNdx->CreationTime; 314c2c66affSColin Finck NTFileInfo->LastWriteTime.QuadPart = FileDirNdx->LastWriteTime; 315c2c66affSColin Finck NTFileInfo->LastAccessTime.QuadPart = FileDirNdx->LastAccessTime; 316c2c66affSColin Finck NTFileInfo->ChangeTime.QuadPart = FileDirNdx->ChangeTime; 317c2c66affSColin Finck NTFileInfo->FileAttributes = FileDirNdx->SysAttr; 318c2c66affSColin Finck NTFileInfo->AllocationSize.QuadPart = FileDirNdx->AllocationSize; 319c2c66affSColin Finck NTFileInfo->EndOfFile.QuadPart = FileDirNdx->FileSize; 320c2c66affSColin Finck NTFileInfo->EaSize = 0; 321c2c66affSColin Finck FileEntry = NULL; 322c2c66affSColin Finck goto get_name_only; 323c2c66affSColin Finck } 324c2c66affSColin Finck 325c2c66affSColin Finck if(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) 326c2c66affSColin Finck goto get_name_only; 327c2c66affSColin Finck 328c2c66affSColin Finck UDFPrint((" direct\n")); 329c2c66affSColin Finck if(FileEntry->descTag.tagIdent == TID_FILE_ENTRY) { 330c2c66affSColin Finck UDFPrint((" TID_FILE_ENTRY\n")); 331c2c66affSColin Finck if(ReadSizes) { 332c2c66affSColin Finck UDFPrint((" ReadSizes\n")); 333c2c66affSColin Finck // Times 334c2c66affSColin Finck FileDirNdx->CreationTime = NTFileInfo->CreationTime.QuadPart = 335c2c66affSColin Finck FileDirNdx->LastWriteTime = NTFileInfo->LastWriteTime.QuadPart = UDFTimeToNT(&(FileEntry->modificationTime)); 336c2c66affSColin Finck FileDirNdx->LastAccessTime = NTFileInfo->LastAccessTime.QuadPart = UDFTimeToNT(&(FileEntry->accessTime)); 337c2c66affSColin Finck FileDirNdx->ChangeTime = NTFileInfo->ChangeTime.QuadPart = UDFTimeToNT(&(FileEntry->attrTime)); 338c2c66affSColin Finck // FileSize 339c2c66affSColin Finck FileDirNdx->FileSize = 340c2c66affSColin Finck NTFileInfo->EndOfFile.QuadPart = 341c2c66affSColin Finck FileEntry->informationLength; 342c2c66affSColin Finck UDFPrint((" informationLength=%I64x, lengthAllocDescs=%I64x\n", 343c2c66affSColin Finck FileEntry->informationLength, 344c2c66affSColin Finck FileEntry->lengthAllocDescs 345c2c66affSColin Finck )); 346c2c66affSColin Finck // AllocSize 347c2c66affSColin Finck FileDirNdx->AllocationSize = 348c2c66affSColin Finck NTFileInfo->AllocationSize.QuadPart = 349c2c66affSColin Finck (FileEntry->informationLength + Vcb->LBlockSize - 1) & ~((LONGLONG)(Vcb->LBlockSize) - 1); 350c2c66affSColin Finck } 351c2c66affSColin Finck // NTFileInfo->EaSize = 0;//FileEntry->lengthExtendedAttr; 352c2c66affSColin Finck } else if(FileEntry->descTag.tagIdent == TID_EXTENDED_FILE_ENTRY) { 353c2c66affSColin Finck ExFileEntry = (PEXTENDED_FILE_ENTRY)FileEntry; 354c2c66affSColin Finck UDFPrint((" PEXTENDED_FILE_ENTRY\n")); 355c2c66affSColin Finck if(ReadSizes) { 356c2c66affSColin Finck UDFPrint((" ReadSizes\n")); 357c2c66affSColin Finck // Times 358c2c66affSColin Finck FileDirNdx->CreationTime = NTFileInfo->CreationTime.QuadPart = UDFTimeToNT(&(ExFileEntry->createTime)); 359c2c66affSColin Finck FileDirNdx->LastWriteTime = NTFileInfo->LastWriteTime.QuadPart = UDFTimeToNT(&(ExFileEntry->modificationTime)); 360c2c66affSColin Finck FileDirNdx->LastAccessTime = NTFileInfo->LastAccessTime.QuadPart = UDFTimeToNT(&(ExFileEntry->accessTime)); 361c2c66affSColin Finck FileDirNdx->ChangeTime = NTFileInfo->ChangeTime.QuadPart = UDFTimeToNT(&(ExFileEntry->attrTime)); 362c2c66affSColin Finck // FileSize 363c2c66affSColin Finck FileDirNdx->FileSize = 364c2c66affSColin Finck NTFileInfo->EndOfFile.QuadPart = 365c2c66affSColin Finck ExFileEntry->informationLength; 366c2c66affSColin Finck UDFPrint((" informationLength=%I64x, lengthAllocDescs=%I64x\n", 367c2c66affSColin Finck FileEntry->informationLength, 368c2c66affSColin Finck FileEntry->lengthAllocDescs 369c2c66affSColin Finck )); 370c2c66affSColin Finck // AllocSize 371c2c66affSColin Finck FileDirNdx->AllocationSize = 372c2c66affSColin Finck NTFileInfo->AllocationSize.QuadPart = 373c2c66affSColin Finck (ExFileEntry->informationLength + Vcb->LBlockSize - 1) & ~((LONGLONG)(Vcb->LBlockSize) - 1); 374c2c66affSColin Finck } 375c2c66affSColin Finck // NTFileInfo->EaSize = 0;//ExFileEntry->lengthExtendedAttr; 376c2c66affSColin Finck } else { 377c2c66affSColin Finck UDFPrint((" ???\n")); 378c2c66affSColin Finck goto get_name_only; 379c2c66affSColin Finck } 380c2c66affSColin Finck 381c2c66affSColin Finck get_attr_only: 382c2c66affSColin Finck 383c2c66affSColin Finck UDFPrint((" get_attr")); 384c2c66affSColin Finck // do some substitutions 385c2c66affSColin Finck if(!FileDirNdx->CreationTime) { 386c2c66affSColin Finck FileDirNdx->CreationTime = NTFileInfo->CreationTime.QuadPart = Vcb->VolCreationTime; 387c2c66affSColin Finck } 388c2c66affSColin Finck if(!FileDirNdx->LastAccessTime) { 389c2c66affSColin Finck FileDirNdx->LastAccessTime = NTFileInfo->LastAccessTime.QuadPart = FileDirNdx->CreationTime; 390c2c66affSColin Finck } 391c2c66affSColin Finck if(!FileDirNdx->LastWriteTime) { 392c2c66affSColin Finck FileDirNdx->LastWriteTime = NTFileInfo->LastWriteTime.QuadPart = FileDirNdx->CreationTime; 393c2c66affSColin Finck } 394c2c66affSColin Finck if(!FileDirNdx->ChangeTime) { 395c2c66affSColin Finck FileDirNdx->ChangeTime = NTFileInfo->ChangeTime.QuadPart = FileDirNdx->CreationTime; 396c2c66affSColin Finck } 397c2c66affSColin Finck 398c2c66affSColin Finck FileDirNdx->SysAttr = 399c2c66affSColin Finck NTFileInfo->FileAttributes = UDFAttributesToNT(FileDirNdx, (tag*)FileEntry); 400c2c66affSColin Finck FileDirNdx->FI_Flags |= UDF_FI_FLAG_SYS_ATTR; 401c2c66affSColin Finck 402c2c66affSColin Finck get_name_only: 403c2c66affSColin Finck // get filename in standard Unicode format 404c2c66affSColin Finck UdfName = FileDirNdx->FName; 405c2c66affSColin Finck NTFileInfo->FileNameLength = UdfName.Length; 406c2c66affSColin Finck RtlCopyMemory((PCHAR)&(NTFileInfo->FileName), (PCHAR)(UdfName.Buffer), UdfName.MaximumLength); 407c2c66affSColin Finck if(!(FileDirNdx->FI_Flags & UDF_FI_FLAG_DOS)) { 408c2c66affSColin Finck UDFPrint((" !UDF_FI_FLAG_DOS")); 409c2c66affSColin Finck UDFDOSName(Vcb, &DosName, &UdfName, 410c2c66affSColin Finck (FileDirNdx->FI_Flags & UDF_FI_FLAG_KEEP_NAME) ? TRUE : FALSE); 411c2c66affSColin Finck NTFileInfo->ShortNameLength = (UCHAR)DosName.Length; 412c2c66affSColin Finck } 413c2c66affSColin Finck // report zero EOF & AllocSize for Dirs 414c2c66affSColin Finck if(FileDirNdx->FileCharacteristics & FILE_DIRECTORY) { 415c2c66affSColin Finck UDFPrint((" FILE_DIRECTORY")); 416c2c66affSColin Finck NTFileInfo->AllocationSize.QuadPart = 417c2c66affSColin Finck NTFileInfo->EndOfFile.QuadPart = 0; 418c2c66affSColin Finck } 419c2c66affSColin Finck UDFPrint((" AllocationSize=%I64x, NTFileInfo->EndOfFile=%I64x", NTFileInfo->AllocationSize.QuadPart, NTFileInfo->EndOfFile.QuadPart)); 420c2c66affSColin Finck // free tmp buffer (if any) 421c2c66affSColin Finck UDFPrint(("\n")); 422c2c66affSColin Finck if(FileEntry && !FileDirNdx->FileInfo) 423c2c66affSColin Finck MyFreePool__(FileEntry); 424c2c66affSColin Finck return STATUS_SUCCESS; 425c2c66affSColin Finck } // end UDFFileDirInfoToNT() 426c2c66affSColin Finck 427c2c66affSColin Finck #endif //_CONSOLE 428c2c66affSColin Finck 429c2c66affSColin Finck #ifndef UDF_READ_ONLY_BUILD 430c2c66affSColin Finck /* 431c2c66affSColin Finck This routine changes xxxTime field(s) in (Ext)FileEntry 432c2c66affSColin Finck */ 433c2c66affSColin Finck VOID 434c2c66affSColin Finck UDFSetFileXTime( 435c2c66affSColin Finck IN PUDF_FILE_INFO FileInfo, 436c2c66affSColin Finck IN LONGLONG* CrtTime, 437c2c66affSColin Finck IN LONGLONG* AccTime, 438c2c66affSColin Finck IN LONGLONG* AttrTime, 439c2c66affSColin Finck IN LONGLONG* ChgTime 440c2c66affSColin Finck ) 441c2c66affSColin Finck { 442c2c66affSColin Finck USHORT Ident; 443c2c66affSColin Finck PDIR_INDEX_ITEM DirNdx; 444c2c66affSColin Finck 445c2c66affSColin Finck ValidateFileInfo(FileInfo); 446c2c66affSColin Finck 447c2c66affSColin Finck FileInfo->Dloc->FE_Flags |= UDF_FE_FLAG_FE_MODIFIED; 448c2c66affSColin Finck DirNdx = UDFDirIndex(UDFGetDirIndexByFileInfo(FileInfo), FileInfo->Index); 449c2c66affSColin Finck Ident = FileInfo->Dloc->FileEntry->tagIdent; 450c2c66affSColin Finck 451c2c66affSColin Finck if(Ident == TID_FILE_ENTRY) { 452c2c66affSColin Finck PFILE_ENTRY fe = (PFILE_ENTRY)(FileInfo->Dloc->FileEntry); 453c2c66affSColin Finck 454c2c66affSColin Finck if(AccTime) { 455c2c66affSColin Finck if(DirNdx && *AccTime) DirNdx->LastAccessTime = *AccTime; 456c2c66affSColin Finck UDFTimeToUDF(*AccTime, &(fe->accessTime)); 457c2c66affSColin Finck } 458c2c66affSColin Finck if(AttrTime) { 459c2c66affSColin Finck if(DirNdx && *AttrTime) DirNdx->ChangeTime = *AttrTime; 460c2c66affSColin Finck UDFTimeToUDF(*AttrTime, &(fe->attrTime)); 461c2c66affSColin Finck } 462c2c66affSColin Finck if(ChgTime) { 463c2c66affSColin Finck if(DirNdx && *ChgTime) DirNdx->CreationTime = 464c2c66affSColin Finck DirNdx->LastWriteTime = *ChgTime; 465c2c66affSColin Finck UDFTimeToUDF(*ChgTime, &(fe->modificationTime)); 466c2c66affSColin Finck } else 467c2c66affSColin Finck if(CrtTime) { 468c2c66affSColin Finck if(DirNdx && *CrtTime) DirNdx->CreationTime = 469c2c66affSColin Finck DirNdx->LastWriteTime = *CrtTime; 470c2c66affSColin Finck UDFTimeToUDF(*CrtTime, &(fe->modificationTime)); 471c2c66affSColin Finck } 472c2c66affSColin Finck 473c2c66affSColin Finck } else if(Ident == TID_EXTENDED_FILE_ENTRY) { 474c2c66affSColin Finck PEXTENDED_FILE_ENTRY fe = (PEXTENDED_FILE_ENTRY)(FileInfo->Dloc->FileEntry); 475c2c66affSColin Finck 476c2c66affSColin Finck if(AccTime) { 477c2c66affSColin Finck if(DirNdx && *AccTime) DirNdx->LastAccessTime = *AccTime; 478c2c66affSColin Finck UDFTimeToUDF(*AccTime, &(fe->accessTime)); 479c2c66affSColin Finck } 480c2c66affSColin Finck if(AttrTime) { 481c2c66affSColin Finck if(DirNdx && *AttrTime) DirNdx->ChangeTime = *AttrTime; 482c2c66affSColin Finck UDFTimeToUDF(*AttrTime, &(fe->attrTime)); 483c2c66affSColin Finck } 484c2c66affSColin Finck if(ChgTime) { 485c2c66affSColin Finck if(DirNdx && *ChgTime) DirNdx->LastWriteTime = *ChgTime; 486c2c66affSColin Finck UDFTimeToUDF(*ChgTime, &(fe->modificationTime)); 487c2c66affSColin Finck } 488c2c66affSColin Finck if(CrtTime) { 489c2c66affSColin Finck if(DirNdx && *CrtTime) DirNdx->CreationTime = *CrtTime; 490c2c66affSColin Finck UDFTimeToUDF(*CrtTime, &(fe->createTime)); 491c2c66affSColin Finck } 492c2c66affSColin Finck 493c2c66affSColin Finck } 494c2c66affSColin Finck } // end UDFSetFileXTime() 495c2c66affSColin Finck #endif //UDF_READ_ONLY_BUILD 496c2c66affSColin Finck 497c2c66affSColin Finck /* 498c2c66affSColin Finck This routine gets xxxTime field(s) in (Ext)FileEntry 499c2c66affSColin Finck */ 500c2c66affSColin Finck VOID 501c2c66affSColin Finck UDFGetFileXTime( 502c2c66affSColin Finck IN PUDF_FILE_INFO FileInfo, 503c2c66affSColin Finck OUT LONGLONG* CrtTime, 504c2c66affSColin Finck OUT LONGLONG* AccTime, 505c2c66affSColin Finck OUT LONGLONG* AttrTime, 506c2c66affSColin Finck OUT LONGLONG* ChgTime 507c2c66affSColin Finck ) 508c2c66affSColin Finck { 509c2c66affSColin Finck USHORT Ident; 510c2c66affSColin Finck 511c2c66affSColin Finck ValidateFileInfo(FileInfo); 512c2c66affSColin Finck 513c2c66affSColin Finck Ident = FileInfo->Dloc->FileEntry->tagIdent; 514c2c66affSColin Finck 515c2c66affSColin Finck if(Ident == TID_FILE_ENTRY) { 516c2c66affSColin Finck PFILE_ENTRY fe = (PFILE_ENTRY)(FileInfo->Dloc->FileEntry); 517c2c66affSColin Finck 518c2c66affSColin Finck if(AccTime) *AccTime = UDFTimeToNT(&(fe->accessTime)); 519c2c66affSColin Finck if(AttrTime) *AttrTime = UDFTimeToNT(&(fe->attrTime)); 520c2c66affSColin Finck if(ChgTime) *ChgTime = UDFTimeToNT(&(fe->modificationTime)); 521c2c66affSColin Finck if(CrtTime) { 522c2c66affSColin Finck (*CrtTime) = *ChgTime; 523c2c66affSColin Finck } 524c2c66affSColin Finck 525c2c66affSColin Finck } else if(Ident == TID_EXTENDED_FILE_ENTRY) { 526c2c66affSColin Finck PEXTENDED_FILE_ENTRY fe = (PEXTENDED_FILE_ENTRY)(FileInfo->Dloc->FileEntry); 527c2c66affSColin Finck 528c2c66affSColin Finck if(AccTime) *AccTime = UDFTimeToNT(&(fe->accessTime)); 529c2c66affSColin Finck if(AttrTime) *AttrTime = UDFTimeToNT(&(fe->attrTime)); 530c2c66affSColin Finck if(ChgTime) *ChgTime = UDFTimeToNT(&(fe->modificationTime)); 531c2c66affSColin Finck if(CrtTime) *CrtTime = UDFTimeToNT(&(fe->createTime)); 532c2c66affSColin Finck 533c2c66affSColin Finck } 534c2c66affSColin Finck if(CrtTime) { 535c2c66affSColin Finck if(!(*CrtTime)) 536c2c66affSColin Finck KeQuerySystemTime((PLARGE_INTEGER)CrtTime); 537c2c66affSColin Finck if(AccTime && !(*AccTime)) (*AccTime) = *CrtTime; 538c2c66affSColin Finck if(AttrTime && !(*AttrTime)) (*AttrTime) = *CrtTime; 539c2c66affSColin Finck if(AccTime && !(*AccTime)) (*AccTime) = *CrtTime; 540c2c66affSColin Finck } 541c2c66affSColin Finck } // end UDFGetFileXTime() 542c2c66affSColin Finck 543c2c66affSColin Finck VOID 544c2c66affSColin Finck UDFNormalizeFileName( 545c2c66affSColin Finck IN PUNICODE_STRING FName, 546c2c66affSColin Finck IN USHORT valueCRC 547c2c66affSColin Finck ) 548c2c66affSColin Finck { 549c2c66affSColin Finck PWCHAR buffer; 550c2c66affSColin Finck USHORT len; 551c2c66affSColin Finck 552c2c66affSColin Finck len = FName->Length/sizeof(WCHAR); 553c2c66affSColin Finck buffer = FName->Buffer; 554c2c66affSColin Finck 555c2c66affSColin Finck // check for '', '.' & '..' 556c2c66affSColin Finck if(!len) return; 557c2c66affSColin Finck if(!buffer[len-1]) { 558c2c66affSColin Finck FName->Length-=sizeof(WCHAR); 559c2c66affSColin Finck len--; 560c2c66affSColin Finck } 561c2c66affSColin Finck if(!len) return; 562c2c66affSColin Finck if(buffer[0] == UNICODE_PERIOD) { 563c2c66affSColin Finck if(len == 1) return; 564c2c66affSColin Finck if((buffer[1] == UNICODE_PERIOD) && (len == 2)) return; 565c2c66affSColin Finck } 566c2c66affSColin Finck 567c2c66affSColin Finck // check for trailing '.' 568c2c66affSColin Finck for(len--;len;len--) { 569c2c66affSColin Finck if( ((buffer[len] == UNICODE_PERIOD) || (buffer[len] == UNICODE_SPACE)) ) { 570c2c66affSColin Finck FName->Length-=sizeof(WCHAR); 571c2c66affSColin Finck buffer[len] = 0; 572c2c66affSColin Finck } else 573c2c66affSColin Finck break; 574c2c66affSColin Finck } 575c2c66affSColin Finck } // end UDFNormalizeFileName() 576c2c66affSColin Finck 577c2c66affSColin Finck #ifndef _CONSOLE 578c2c66affSColin Finck 579c2c66affSColin Finck void 580c2c66affSColin Finck __fastcall 581c2c66affSColin Finck UDFDOSNameOsNative( 582c2c66affSColin Finck IN OUT PUNICODE_STRING DosName, 583c2c66affSColin Finck IN PUNICODE_STRING UdfName, 584c2c66affSColin Finck IN BOOLEAN KeepIntact 585c2c66affSColin Finck ) 586c2c66affSColin Finck { 587c2c66affSColin Finck PWCHAR dosName = DosName->Buffer; 588c2c66affSColin Finck PWCHAR udfName = UdfName->Buffer; 589c2c66affSColin Finck uint32 udfLen = UdfName->Length / sizeof(WCHAR); 590c2c66affSColin Finck GENERATE_NAME_CONTEXT Ctx; 591c2c66affSColin Finck 592c2c66affSColin Finck if(KeepIntact && 593c2c66affSColin Finck (udfLen <= 2) && (udfName[0] == UNICODE_PERIOD)) { 594c2c66affSColin Finck if((udfLen != 2) || (udfName[1] == UNICODE_PERIOD)) { 595c2c66affSColin Finck RtlCopyMemory(dosName, udfName, UdfName->Length); 596c2c66affSColin Finck DosName->Length = UdfName->Length; 597c2c66affSColin Finck return; 598c2c66affSColin Finck } 599c2c66affSColin Finck } 600c2c66affSColin Finck RtlZeroMemory(&Ctx, sizeof(GENERATE_NAME_CONTEXT)); 601c2c66affSColin Finck RtlGenerate8dot3Name(UdfName, FALSE, &Ctx, DosName); 602c2c66affSColin Finck 603c2c66affSColin Finck } // UDFDOSNameOsNative() 604c2c66affSColin Finck 605c2c66affSColin Finck #endif //_CONSOLE 606c2c66affSColin Finck 607c2c66affSColin Finck /*VOID 608c2c66affSColin Finck UDFNormalizeFileName( 609c2c66affSColin Finck IN PUNICODE_STRING FName, 610c2c66affSColin Finck IN USHORT valueCRC 611c2c66affSColin Finck ) 612c2c66affSColin Finck { 613c2c66affSColin Finck WCHAR _newName[UDF_NAME_LEN+5]; 614c2c66affSColin Finck PWCHAR newName = (PWCHAR)(&_newName); 615c2c66affSColin Finck PWCHAR udfName = FName->Buffer; 616c2c66affSColin Finck LONG udfLen = FName->Length >> 1; 617c2c66affSColin Finck 618c2c66affSColin Finck LONG index, newIndex = 0, extIndex = 0, newExtIndex = 0, trailIndex = 0; 619c2c66affSColin Finck BOOLEAN needsCRC = FALSE, hasExt = FALSE; 620c2c66affSColin Finck WCHAR ext[UDF_EXT_SIZE], current; 621c2c66affSColin Finck 622c2c66affSColin Finck // handle CurrentDir ('.') and ParentDir ('..') cases 623c2c66affSColin Finck if((udfLen <= 2) && (udfName[0] == UNICODE_PERIOD)) { 624c2c66affSColin Finck if((udfLen != 2) || (udfName[1] == UNICODE_PERIOD)) 625c2c66affSColin Finck return; 626c2c66affSColin Finck } 627c2c66affSColin Finck 628c2c66affSColin Finck for (index = 0 ; index < udfLen ; index++) { 629c2c66affSColin Finck current = udfName[index]; 630c2c66affSColin Finck 631c2c66affSColin Finck // Look for illegal or unprintable characters. 632c2c66affSColin Finck if (UDFIsIllegalChar(current) || !UnicodeIsPrint(current)) { 633c2c66affSColin Finck needsCRC = TRUE; 634c2c66affSColin Finck current = ILLEGAL_CHAR_MARK; 635c2c66affSColin Finck // Skip Illegal characters(even spaces), 636c2c66affSColin Finck // but not periods. 637c2c66affSColin Finck while(index+1 < udfLen && 638c2c66affSColin Finck (UDFIsIllegalChar(udfName[index+1]) || 639c2c66affSColin Finck !UnicodeIsPrint(udfName[index+1])) && 640c2c66affSColin Finck udfName[index+1] != UNICODE_PERIOD) 641c2c66affSColin Finck index++; 642c2c66affSColin Finck } 643c2c66affSColin Finck 644c2c66affSColin Finck // Record position of extension, if one is found. 645c2c66affSColin Finck if ((current == UNICODE_PERIOD) && ((udfLen - index -1) <= UDF_EXT_SIZE)) { 646c2c66affSColin Finck if (udfLen == index + 1) { 647c2c66affSColin Finck // A trailing period is NOT an extension. 648c2c66affSColin Finck hasExt = FALSE; 649c2c66affSColin Finck } else { 650c2c66affSColin Finck hasExt = TRUE; 651c2c66affSColin Finck extIndex = index; 652c2c66affSColin Finck newExtIndex = newIndex; 653c2c66affSColin Finck } 654c2c66affSColin Finck } else if((current != UNICODE_PERIOD) && (current != UNICODE_SPACE)) { 655c2c66affSColin Finck trailIndex = index; 656c2c66affSColin Finck } 657c2c66affSColin Finck 658c2c66affSColin Finck // if (newIndex < MAXLEN) // tshi is always TRUE for WINNT 659c2c66affSColin Finck newName[newIndex] = current; 660c2c66affSColin Finck newIndex++; 661c2c66affSColin Finck 662c2c66affSColin Finck // For OS2, 95 & NT, truncate any trailing periods and\or spaces. 663c2c66affSColin Finck if (trailIndex != (newIndex - 1)) { 664c2c66affSColin Finck newIndex = trailIndex + 1; 665c2c66affSColin Finck needsCRC = TRUE; 666c2c66affSColin Finck hasExt = FALSE; // Trailing period does not make an extension. 667c2c66affSColin Finck } 668c2c66affSColin Finck } 669c2c66affSColin Finck 670c2c66affSColin Finck if (needsCRC) { 671c2c66affSColin Finck int localExtIndex = 0; 672c2c66affSColin Finck if (hasExt) { 673c2c66affSColin Finck int maxFilenameLen; 674c2c66affSColin Finck // Translate extension, and store it in ext. 675c2c66affSColin Finck for(index = 0; index<UDF_EXT_SIZE && extIndex + index +1 < udfLen; index++ ) { 676c2c66affSColin Finck current = udfName[extIndex + index + 1]; 677c2c66affSColin Finck if (UDFIsIllegalChar(current) //|| !UnicodeIsPrint(current)) { 678c2c66affSColin Finck needsCRC = TRUE; 679c2c66affSColin Finck // Replace Illegal and non-displayable chars 680c2c66affSColin Finck // with underscore. 681c2c66affSColin Finck current = ILLEGAL_CHAR_MARK; 682c2c66affSColin Finck // Skip any other illegal or non-displayable 683c2c66affSColin Finck // characters. 684c2c66affSColin Finck while(index + 1 < UDF_EXT_SIZE && 685c2c66affSColin Finck (UDFIsIllegalChar(udfName[extIndex + index + 2]) || 686c2c66affSColin Finck !UnicodeIsPrint(udfName[extIndex + index + 2])) ) 687c2c66affSColin Finck index++; 688c2c66affSColin Finck } 689c2c66affSColin Finck ext[localExtIndex++] = current; 690c2c66affSColin Finck } 691c2c66affSColin Finck // Truncate filename to leave room for extension and CRC. 692c2c66affSColin Finck maxFilenameLen = ((UDF_NAME_LEN - 4) - localExtIndex - 1); 693c2c66affSColin Finck if (newIndex > maxFilenameLen) { 694c2c66affSColin Finck newIndex = maxFilenameLen; 695c2c66affSColin Finck } else { 696c2c66affSColin Finck newIndex = newExtIndex; 697c2c66affSColin Finck } 698c2c66affSColin Finck } else if (newIndex > UDF_NAME_LEN - 5) { 699c2c66affSColin Finck //If no extension, make sure to leave room for CRC. 700c2c66affSColin Finck newIndex = UDF_NAME_LEN - 5; 701c2c66affSColin Finck } 702c2c66affSColin Finck newName[newIndex++] = UNICODE_CRC_MARK; // Add mark for CRC. 703c2c66affSColin Finck //Calculate CRC from original filename from FileIdentifier. 704c2c66affSColin Finck // valueCRC = UDFUnicodeCksum(fidName, fidNameLen); 705c2c66affSColin Finck // / Convert 16-bits of CRC to hex characters. 706c2c66affSColin Finck newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12]; 707c2c66affSColin Finck newName[newIndex++] = hexChar[(valueCRC & 0x0f00) >> 8]; 708c2c66affSColin Finck newName[newIndex++] = hexChar[(valueCRC & 0x00f0) >> 4]; 709c2c66affSColin Finck newName[newIndex++] = hexChar[(valueCRC & 0x000f)]; 710c2c66affSColin Finck // Place a translated extension at end, if found. 711c2c66affSColin Finck if (hasExt) { 712c2c66affSColin Finck newName[newIndex++] = UNICODE_PERIOD; 713c2c66affSColin Finck for (index = 0;index < localExtIndex ;index++ ) { 714c2c66affSColin Finck newName[newIndex++] = ext[index]; 715c2c66affSColin Finck } 716c2c66affSColin Finck } 717c2c66affSColin Finck } 718c2c66affSColin Finck 719c2c66affSColin Finck if(FName->Length == (USHORT)newIndex*sizeof(WCHAR)) { 720c2c66affSColin Finck RtlCopyMemory(FName->Buffer, newName, newIndex*sizeof(WCHAR)); 721c2c66affSColin Finck return; 722c2c66affSColin Finck } 723c2c66affSColin Finck MyFreePool__(FName->Buffer); 724c2c66affSColin Finck FName->Buffer = (PWCHAR)MyAllocatePool__(UDF_FILENAME_MT, (newIndex+1)*sizeof(WCHAR)); 725c2c66affSColin Finck if(FName->Buffer) { 726c2c66affSColin Finck FName->Buffer[newIndex] = 0; 727c2c66affSColin Finck RtlCopyMemory(FName->Buffer, newName, newIndex*sizeof(WCHAR)); 728c2c66affSColin Finck } 729c2c66affSColin Finck FName->Length = (USHORT)newIndex*sizeof(WCHAR); 730c2c66affSColin Finck FName->MaximumLength = (USHORT)(newIndex+1)*sizeof(WCHAR); 731c2c66affSColin Finck }*/ 732c2c66affSColin Finck 733c2c66affSColin Finck /*PUDF_FILE_INFO 734c2c66affSColin Finck UDFAllocFileInfo( 735c2c66affSColin Finck return ExAllocateFromZone(&(UDFGlobalData.FileInfoZoneHeader)); 736c2c66affSColin Finck )*/ 737c2c66affSColin Finck 738c2c66affSColin Finck #define STRING_BUFFER_ALIGNMENT (32) 739c2c66affSColin Finck #define STRING_BUFFER_ALIGN(sz) (((sz)+STRING_BUFFER_ALIGNMENT)&(~((ULONG)(STRING_BUFFER_ALIGNMENT-1)))) 740c2c66affSColin Finck 741c2c66affSColin Finck NTSTATUS 742c2c66affSColin Finck MyAppendUnicodeStringToString_( 743c2c66affSColin Finck IN PUNICODE_STRING Str1, 744c2c66affSColin Finck IN PUNICODE_STRING Str2 745c2c66affSColin Finck #ifdef UDF_TRACK_UNICODE_STR 746c2c66affSColin Finck ,IN PCHAR Tag 747c2c66affSColin Finck #endif 748c2c66affSColin Finck ) 749c2c66affSColin Finck { 750c2c66affSColin Finck PWCHAR tmp; 751c2c66affSColin Finck USHORT i; 752c2c66affSColin Finck 753c2c66affSColin Finck #ifdef UDF_TRACK_UNICODE_STR 754c2c66affSColin Finck #define UDF_UNC_STR_TAG Tag 755c2c66affSColin Finck #else 756c2c66affSColin Finck #define UDF_UNC_STR_TAG "AppUStr" 757c2c66affSColin Finck #endif 758c2c66affSColin Finck 759c2c66affSColin Finck tmp = Str1->Buffer; 760c2c66affSColin Finck i = Str1->Length + Str2->Length + sizeof(WCHAR); 761c2c66affSColin Finck ASSERT(Str1->MaximumLength); 762c2c66affSColin Finck if(i > Str1->MaximumLength) { 763c2c66affSColin Finck if(!MyReallocPool__((PCHAR)tmp, Str1->MaximumLength, 764c2c66affSColin Finck (PCHAR*)&tmp, STRING_BUFFER_ALIGN(i)*2) ) { 765c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 766c2c66affSColin Finck } 767c2c66affSColin Finck Str1->MaximumLength = i*2; 768c2c66affSColin Finck Str1->Buffer = tmp; 769c2c66affSColin Finck } 770c2c66affSColin Finck RtlCopyMemory(((PCHAR)tmp)+Str1->Length, Str2->Buffer, Str2->Length); 771c2c66affSColin Finck 772c2c66affSColin Finck /* tmp = (PWCHAR)MyAllocatePoolTag__(NonPagedPool, i = Str1->Length + Str2->Length + sizeof(WCHAR), UDF_UNC_STR_TAG); 773c2c66affSColin Finck if(!tmp) 774c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 775c2c66affSColin Finck RtlCopyMemory(tmp, Str1->Buffer, Str1->Length); 776c2c66affSColin Finck RtlCopyMemory(((PCHAR)tmp)+Str1->Length, Str2->Buffer, Str2->Length);*/ 777c2c66affSColin Finck tmp[(i / sizeof(WCHAR)) - 1] = 0; 778c2c66affSColin Finck Str1->Length = i - sizeof(WCHAR); 779c2c66affSColin Finck //MyFreePool__(Str1->Buffer); 780c2c66affSColin Finck #ifdef UDF_DBG 781c2c66affSColin Finck if(Str1->Buffer && (Str1->Length >= 2*sizeof(WCHAR))) { 782c2c66affSColin Finck ASSERT((Str1->Buffer[0] != L'\\') || (Str1->Buffer[1] != L'\\')); 783c2c66affSColin Finck } 784c2c66affSColin Finck #endif // UDF_DBG 785c2c66affSColin Finck return STATUS_SUCCESS; 786c2c66affSColin Finck 787c2c66affSColin Finck #undef UDF_UNC_STR_TAG 788c2c66affSColin Finck 789c2c66affSColin Finck } // end MyAppendUnicodeStringToString() 790c2c66affSColin Finck 791c2c66affSColin Finck NTSTATUS 792c2c66affSColin Finck MyAppendUnicodeToString_( 793c2c66affSColin Finck IN PUNICODE_STRING Str1, 794c2c66affSColin Finck IN PCWSTR Str2 795c2c66affSColin Finck #ifdef UDF_TRACK_UNICODE_STR 796c2c66affSColin Finck ,IN PCHAR Tag 797c2c66affSColin Finck #endif 798c2c66affSColin Finck ) 799c2c66affSColin Finck { 800c2c66affSColin Finck PWCHAR tmp; 801c2c66affSColin Finck USHORT i; 802c2c66affSColin Finck 803c2c66affSColin Finck #ifdef UDF_TRACK_UNICODE_STR 804c2c66affSColin Finck #define UDF_UNC_STR_TAG Tag 805c2c66affSColin Finck #else 806c2c66affSColin Finck #define UDF_UNC_STR_TAG "AppStr" 807c2c66affSColin Finck #endif 808c2c66affSColin Finck 8095bf1fbecSAmine Khaldi #if defined(_X86_) && defined(_MSC_VER) && !defined(__clang__) 810c2c66affSColin Finck 811c2c66affSColin Finck __asm push ebx 812c2c66affSColin Finck __asm push esi 813c2c66affSColin Finck 814c2c66affSColin Finck __asm xor ebx,ebx 815c2c66affSColin Finck __asm mov esi,Str2 816c2c66affSColin Finck Scan_1: 817c2c66affSColin Finck __asm cmp [word ptr esi+ebx],0 818c2c66affSColin Finck __asm je EO_Scan 819c2c66affSColin Finck __asm add ebx,2 820c2c66affSColin Finck __asm jmp Scan_1 821c2c66affSColin Finck EO_Scan: 822c2c66affSColin Finck __asm mov i,bx 823c2c66affSColin Finck 824c2c66affSColin Finck __asm pop esi 825c2c66affSColin Finck __asm pop ebx 826c2c66affSColin Finck 827c2c66affSColin Finck #else // NO X86 optimization, use generic C/C++ 828c2c66affSColin Finck 829c2c66affSColin Finck i=0; 830c2c66affSColin Finck while(Str2[i]) { 831c2c66affSColin Finck i++; 832c2c66affSColin Finck } 833c2c66affSColin Finck i *= sizeof(WCHAR); 834c2c66affSColin Finck 835c2c66affSColin Finck #endif // _X86_ 836c2c66affSColin Finck 837c2c66affSColin Finck tmp = Str1->Buffer; 838c2c66affSColin Finck ASSERT(Str1->MaximumLength); 839c2c66affSColin Finck if((Str1->Length+i+sizeof(WCHAR)) > Str1->MaximumLength) { 840c2c66affSColin Finck if(!MyReallocPool__((PCHAR)tmp, Str1->MaximumLength, 841c2c66affSColin Finck (PCHAR*)&tmp, STRING_BUFFER_ALIGN(i + Str1->Length + sizeof(WCHAR))*2 ) ) { 842c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 843c2c66affSColin Finck } 844c2c66affSColin Finck Str1->MaximumLength = STRING_BUFFER_ALIGN(i + sizeof(WCHAR))*2; 845c2c66affSColin Finck Str1->Buffer = tmp; 846c2c66affSColin Finck } 847c2c66affSColin Finck RtlCopyMemory(((PCHAR)tmp)+Str1->Length, Str2, i); 848c2c66affSColin Finck i+=Str1->Length; 849c2c66affSColin Finck tmp[(i / sizeof(WCHAR))] = 0; 850c2c66affSColin Finck Str1->Length = i; 851c2c66affSColin Finck #ifdef UDF_DBG 852c2c66affSColin Finck /* if(Str1->Buffer && (Str1->Length >= 2*sizeof(WCHAR))) { 853c2c66affSColin Finck ASSERT((Str1->Buffer[0] != L'\\') || (Str1->Buffer[1] != L'\\')); 854c2c66affSColin Finck }*/ 855c2c66affSColin Finck #endif // UDF_DBG 856c2c66affSColin Finck return STATUS_SUCCESS; 857c2c66affSColin Finck 858c2c66affSColin Finck #undef UDF_UNC_STR_TAG 859c2c66affSColin Finck 860c2c66affSColin Finck } // end MyAppendUnicodeToString_() 861c2c66affSColin Finck 862c2c66affSColin Finck NTSTATUS 863c2c66affSColin Finck MyInitUnicodeString( 864c2c66affSColin Finck IN PUNICODE_STRING Str1, 865c2c66affSColin Finck IN PCWSTR Str2 866c2c66affSColin Finck ) 867c2c66affSColin Finck { 868c2c66affSColin Finck 869c2c66affSColin Finck USHORT i; 870c2c66affSColin Finck 8715bf1fbecSAmine Khaldi #if defined(_X86_) && defined(_MSC_VER) && !defined(__clang__) 872c2c66affSColin Finck 873c2c66affSColin Finck __asm push ebx 874c2c66affSColin Finck __asm push esi 875c2c66affSColin Finck 876c2c66affSColin Finck __asm xor ebx,ebx 877c2c66affSColin Finck __asm mov esi,Str2 878c2c66affSColin Finck Scan_1: 879c2c66affSColin Finck __asm cmp [word ptr esi+ebx],0 880c2c66affSColin Finck __asm je EO_Scan 881c2c66affSColin Finck __asm add ebx,2 882c2c66affSColin Finck __asm jmp Scan_1 883c2c66affSColin Finck EO_Scan: 884c2c66affSColin Finck __asm mov i,bx 885c2c66affSColin Finck 886c2c66affSColin Finck __asm pop esi 887c2c66affSColin Finck __asm pop ebx 888c2c66affSColin Finck 889c2c66affSColin Finck #else // NO X86 optimization, use generic C/C++ 890c2c66affSColin Finck 891c2c66affSColin Finck i=0; 892c2c66affSColin Finck while(Str2[i]) { 893c2c66affSColin Finck i++; 894c2c66affSColin Finck } 895c2c66affSColin Finck i *= sizeof(WCHAR); 896c2c66affSColin Finck 897c2c66affSColin Finck #endif // _X86_ 898c2c66affSColin Finck 899c2c66affSColin Finck Str1->MaximumLength = STRING_BUFFER_ALIGN((Str1->Length = i) + sizeof(WCHAR)); 900c2c66affSColin Finck Str1->Buffer = (PWCHAR)MyAllocatePool__(NonPagedPool, Str1->MaximumLength); 901c2c66affSColin Finck if(!Str1->Buffer) 902c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 903c2c66affSColin Finck RtlCopyMemory(Str1->Buffer, Str2, i); 904c2c66affSColin Finck Str1->Buffer[i/sizeof(WCHAR)] = 0; 905c2c66affSColin Finck return STATUS_SUCCESS; 906c2c66affSColin Finck 907c2c66affSColin Finck } // end MyInitUnicodeString() 908c2c66affSColin Finck 909c2c66affSColin Finck NTSTATUS 910c2c66affSColin Finck MyCloneUnicodeString( 911c2c66affSColin Finck IN PUNICODE_STRING Str1, 912c2c66affSColin Finck IN PUNICODE_STRING Str2 913c2c66affSColin Finck ) 914c2c66affSColin Finck { 915c2c66affSColin Finck Str1->MaximumLength = STRING_BUFFER_ALIGN((Str1->Length = Str2->Length) + sizeof(WCHAR)); 916c2c66affSColin Finck Str1->Buffer = (PWCHAR)MyAllocatePool__(NonPagedPool, Str1->MaximumLength); 917c2c66affSColin Finck if(!Str1->Buffer) 918c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 919c2c66affSColin Finck ASSERT(Str2->Buffer); 920c2c66affSColin Finck RtlCopyMemory(Str1->Buffer, Str2->Buffer, Str2->Length); 921c2c66affSColin Finck Str1->Buffer[Str1->Length/sizeof(WCHAR)] = 0; 922c2c66affSColin Finck return STATUS_SUCCESS; 923c2c66affSColin Finck 924c2c66affSColin Finck } // end MyCloneUnicodeString() 925c2c66affSColin Finck 926c2c66affSColin Finck /* 927c2c66affSColin Finck This routine checks do we needn't read something from disk to 928c2c66affSColin Finck obtain Attributes & so on 929c2c66affSColin Finck */ 930c2c66affSColin Finck BOOLEAN 931c2c66affSColin Finck UDFIsDirInfoCached( 932c2c66affSColin Finck IN PVCB Vcb, 933c2c66affSColin Finck IN PUDF_FILE_INFO DirInfo 934c2c66affSColin Finck ) 935c2c66affSColin Finck { 936c2c66affSColin Finck PDIR_INDEX_HDR hDirNdx = DirInfo->Dloc->DirIndex; 937c2c66affSColin Finck PDIR_INDEX_ITEM DirNdx; 938c2c66affSColin Finck for(uint_di i=2; (DirNdx = UDFDirIndex(hDirNdx,i)); i++) { 939c2c66affSColin Finck if(!(DirNdx->FI_Flags & UDF_FI_FLAG_SYS_ATTR) || 940c2c66affSColin Finck (DirNdx->FI_Flags & UDF_FI_FLAG_LINKED)) return FALSE; 941c2c66affSColin Finck } 942c2c66affSColin Finck return TRUE; 943c2c66affSColin Finck } // end UDFIsDirInfoCached() 944c2c66affSColin Finck 945c2c66affSColin Finck #ifndef UDF_READ_ONLY_BUILD 946c2c66affSColin Finck NTSTATUS 947c2c66affSColin Finck UDFDoesOSAllowFileToBeTargetForRename__( 948c2c66affSColin Finck IN PUDF_FILE_INFO FileInfo 949c2c66affSColin Finck ) 950c2c66affSColin Finck { 951c2c66affSColin Finck #ifndef _CONSOLE 952c2c66affSColin Finck NTSTATUS RC; 953c2c66affSColin Finck #endif //_CONSOLE 954c2c66affSColin Finck 955c2c66affSColin Finck if(UDFIsADirectory(FileInfo)) 956c2c66affSColin Finck return STATUS_ACCESS_DENIED; 957c2c66affSColin Finck if(!FileInfo->ParentFile) 958c2c66affSColin Finck return STATUS_ACCESS_DENIED; 959c2c66affSColin Finck 960c2c66affSColin Finck if(UDFAttributesToNT(UDFDirIndex(UDFGetDirIndexByFileInfo(FileInfo),FileInfo->Index), 961c2c66affSColin Finck FileInfo->Dloc->FileEntry) & FILE_ATTRIBUTE_READONLY) 962c2c66affSColin Finck return STATUS_ACCESS_DENIED; 963c2c66affSColin Finck 964c2c66affSColin Finck if(!FileInfo->Fcb) 965c2c66affSColin Finck return STATUS_SUCCESS; 966c2c66affSColin Finck #ifndef _CONSOLE 967c2c66affSColin Finck RC = UDFCheckAccessRights(NULL, NULL, FileInfo->Fcb, NULL, DELETE, 0); 968c2c66affSColin Finck if(!NT_SUCCESS(RC)) 969c2c66affSColin Finck return RC; 970c2c66affSColin Finck #endif //_CONSOLE 971c2c66affSColin Finck if(!FileInfo->Fcb) 972c2c66affSColin Finck return STATUS_SUCCESS; 973c2c66affSColin Finck // RC = UDFMarkStreamsForDeletion(FileInfo->Fcb->Vcb, FileInfo->Fcb, TRUE); // Delete 974c2c66affSColin Finck /* RC = UDFSetDispositionInformation(FileInfo->Fcb, NULL, 975c2c66affSColin Finck FileInfo->Fcb->Vcb, NULL, TRUE); 976c2c66affSColin Finck if(NT_SUCCESS(RC)) { 977c2c66affSColin Finck FileInfo->Fcb->FCBFlags |= UDF_FCB_DELETED; 978c2c66affSColin Finck if(UDFGetFileLinkCount(FileInfo) <= 1) { 979c2c66affSColin Finck FileInfo->Fcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_DELETED; 980c2c66affSColin Finck } 981c2c66affSColin Finck } 982c2c66affSColin Finck return RC;*/ 983c2c66affSColin Finck return STATUS_ACCESS_DENIED; 984c2c66affSColin Finck 985c2c66affSColin Finck } // end UDFDoesOSAllowFileToBeTargetForRename__() 986c2c66affSColin Finck 987c2c66affSColin Finck NTSTATUS 988c2c66affSColin Finck UDFDoesOSAllowFileToBeUnlinked__( 989c2c66affSColin Finck IN PUDF_FILE_INFO FileInfo 990c2c66affSColin Finck ) 991c2c66affSColin Finck { 992c2c66affSColin Finck PDIR_INDEX_HDR hCurDirNdx; 993c2c66affSColin Finck PDIR_INDEX_ITEM CurDirNdx; 994c2c66affSColin Finck uint_di i; 995c2c66affSColin Finck // IO_STATUS_BLOCK IoStatus; 996c2c66affSColin Finck 997c2c66affSColin Finck ASSERT(FileInfo->Dloc); 998c2c66affSColin Finck 999c2c66affSColin Finck if(!FileInfo->ParentFile) 1000c2c66affSColin Finck return STATUS_CANNOT_DELETE; 1001c2c66affSColin Finck if(FileInfo->Dloc->SDirInfo) 1002c2c66affSColin Finck return STATUS_CANNOT_DELETE; 1003c2c66affSColin Finck if(!UDFIsADirectory(FileInfo)) 1004c2c66affSColin Finck return STATUS_SUCCESS; 1005c2c66affSColin Finck 1006c2c66affSColin Finck // UDFFlushAFile(FileInfo->Fcb, NULL, &IoStatus, 0); 1007c2c66affSColin Finck hCurDirNdx = FileInfo->Dloc->DirIndex; 1008c2c66affSColin Finck // check if we can delete all files 1009c2c66affSColin Finck for(i=2; (CurDirNdx = UDFDirIndex(hCurDirNdx,i)); i++) { 1010c2c66affSColin Finck // try to open Stream 1011c2c66affSColin Finck if(CurDirNdx->FileInfo) 1012c2c66affSColin Finck return STATUS_CANNOT_DELETE; 1013c2c66affSColin Finck } 1014c2c66affSColin Finck // return UDFCheckAccessRights(NULL, NULL, FileInfo->Fcb, NULL, DELETE, 0); 1015c2c66affSColin Finck return STATUS_SUCCESS; 1016c2c66affSColin Finck } // end UDFDoesOSAllowFileToBeUnlinked__() 1017c2c66affSColin Finck 1018c2c66affSColin Finck NTSTATUS 1019c2c66affSColin Finck UDFDoesOSAllowFilePretendDeleted__( 1020c2c66affSColin Finck IN PUDF_FILE_INFO FileInfo 1021c2c66affSColin Finck ) 1022c2c66affSColin Finck { 1023c2c66affSColin Finck PDIR_INDEX_HDR hDirNdx = UDFGetDirIndexByFileInfo(FileInfo); 1024c2c66affSColin Finck if(!hDirNdx) return STATUS_CANNOT_DELETE; 1025c2c66affSColin Finck PDIR_INDEX_ITEM DirNdx = UDFDirIndex(hDirNdx, FileInfo->Index); 1026c2c66affSColin Finck if(!DirNdx) return STATUS_CANNOT_DELETE; 1027c2c66affSColin Finck // we can't hide file that is not marked as deleted 1028c2c66affSColin Finck if(!(DirNdx->FileCharacteristics & FILE_DELETED)) { 1029c2c66affSColin Finck BrutePoint(); 1030c2c66affSColin Finck 1031c2c66affSColin Finck #ifndef _CONSOLE 1032c2c66affSColin Finck if(!(FileInfo->Fcb->FCBFlags & (UDF_FCB_DELETE_ON_CLOSE | 1033c2c66affSColin Finck UDF_FCB_DELETED) )) 1034c2c66affSColin Finck #endif //_CONSOLE 1035c2c66affSColin Finck 1036c2c66affSColin Finck return STATUS_CANNOT_DELETE; 1037c2c66affSColin Finck } 1038c2c66affSColin Finck return STATUS_SUCCESS; 1039c2c66affSColin Finck } 1040c2c66affSColin Finck #endif //UDF_READ_ONLY_BUILD 1041c2c66affSColin Finck 1042