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