1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 ////////////////////////////////////////////////////////////////////
5 /*************************************************************************
9 * Module: UDF File System Driver
10 * (both User and Kernel mode execution)
13 * Contains system-secific code
15 *************************************************************************/
19 This routine converts UDF timestamp to NT time
23 IN PUDF_TIME_STAMP UdfTime
27 TIME_FIELDS TimeFields
;
29 TimeFields
.Milliseconds
= (USHORT
)(UdfTime
->centiseconds
* 10 + UdfTime
->hundredsOfMicroseconds
/ 100);
30 TimeFields
.Second
= (USHORT
)(UdfTime
->second
);
31 TimeFields
.Minute
= (USHORT
)(UdfTime
->minute
);
32 TimeFields
.Hour
= (USHORT
)(UdfTime
->hour
);
33 TimeFields
.Day
= (USHORT
)(UdfTime
->day
);
34 TimeFields
.Month
= (USHORT
)(UdfTime
->month
);
35 TimeFields
.Year
= (USHORT
)((UdfTime
->year
< 1601) ? 1601 : UdfTime
->year
);
37 if (!RtlTimeFieldsToTime(&TimeFields
, (PLARGE_INTEGER
)&NtTime
)) {
40 ExLocalTimeToSystemTime( (PLARGE_INTEGER
)&NtTime
, (PLARGE_INTEGER
)&NtTime
);
44 } // end UDFTimeToNT()
48 This routine converts NT time to UDF timestamp
53 OUT PUDF_TIME_STAMP UdfTime
59 TIME_FIELDS TimeFields
;
61 ExSystemTimeToLocalTime( (PLARGE_INTEGER
)&NtTime
, (PLARGE_INTEGER
)&LocalTime
);
62 RtlTimeToTimeFields( (PLARGE_INTEGER
)&LocalTime
, &TimeFields
);
64 LocalTime
/= 10; // microseconds
65 UdfTime
->microseconds
= (UCHAR
)(NtTime
% 100);
66 LocalTime
/= 100; // hundreds of microseconds
67 UdfTime
->hundredsOfMicroseconds
= (UCHAR
)(NtTime
% 100);
68 LocalTime
/= 100; // centiseconds
69 UdfTime
->centiseconds
= (UCHAR
)(TimeFields
.Milliseconds
/ 10);
70 UdfTime
->second
= (UCHAR
)(TimeFields
.Second
);
71 UdfTime
->minute
= (UCHAR
)(TimeFields
.Minute
);
72 UdfTime
->hour
= (UCHAR
)(TimeFields
.Hour
);
73 UdfTime
->day
= (UCHAR
)(TimeFields
.Day
);
74 UdfTime
->month
= (UCHAR
)(TimeFields
.Month
);
75 UdfTime
->year
= (USHORT
)(TimeFields
.Year
);
76 UdfTime
->typeAndTimezone
= (TIMESTAMP_TYPE_LOCAL
<< 14);
77 } // end UDFTimeToUDF()
83 IN PDIR_INDEX_ITEM FileDirNdx
,
88 if( (FileDirNdx
->FI_Flags
& UDF_FI_FLAG_SYS_ATTR
) &&
89 !(FileDirNdx
->FI_Flags
& UDF_FI_FLAG_LINKED
))
90 return FileDirNdx
->SysAttr
;
93 ULONG attr
= 0; //permissions
99 if(!FileDirNdx
->FileInfo
)
101 ValidateFileInfo(FileDirNdx
->FileInfo
);
102 FileEntry
= FileDirNdx
->FileInfo
->Dloc
->FileEntry
;
104 if(FileEntry
->tagIdent
== TID_FILE_ENTRY
) {
105 attr
= ((PFILE_ENTRY
)FileEntry
)->permissions
;
106 Flags
= ((PFILE_ENTRY
)FileEntry
)->icbTag
.flags
;
107 Type
= ((PFILE_ENTRY
)FileEntry
)->icbTag
.fileType
;
108 if(((PFILE_ENTRY
)FileEntry
)->fileLinkCount
> 1)
109 FileDirNdx
->FI_Flags
|= UDF_FI_FLAG_LINKED
;
111 attr
= ((PEXTENDED_FILE_ENTRY
)FileEntry
)->permissions
;
112 Flags
= ((PEXTENDED_FILE_ENTRY
)FileEntry
)->icbTag
.flags
;
113 Type
= ((PEXTENDED_FILE_ENTRY
)FileEntry
)->icbTag
.fileType
;
114 if(((PEXTENDED_FILE_ENTRY
)FileEntry
)->fileLinkCount
> 1)
115 FileDirNdx
->FI_Flags
|= UDF_FI_FLAG_LINKED
;
117 FCharact
= FileDirNdx
->FileCharacteristics
;
119 if(Flags
& ICB_FLAG_SYSTEM
) NTAttr
|= FILE_ATTRIBUTE_SYSTEM
;
120 if(Flags
& ICB_FLAG_ARCHIVE
) NTAttr
|= FILE_ATTRIBUTE_ARCHIVE
;
121 if((Type
== UDF_FILE_TYPE_DIRECTORY
) ||
122 (Type
== UDF_FILE_TYPE_STREAMDIR
) ||
123 (FCharact
& FILE_DIRECTORY
)) {
124 NTAttr
|= FILE_ATTRIBUTE_DIRECTORY
;
127 //NTAttr |= FILE_ATTRIBUTE_NORMAL;
130 if(FCharact
& FILE_HIDDEN
) NTAttr
|= FILE_ATTRIBUTE_HIDDEN
;
131 if( !(attr
& PERM_O_WRITE
) &&
132 !(attr
& PERM_G_WRITE
) &&
133 !(attr
& PERM_U_WRITE
) &&
134 !(attr
& PERM_O_DELETE
) &&
135 !(attr
& PERM_G_DELETE
) &&
136 !(attr
& PERM_U_DELETE
) ) {
137 NTAttr
|= FILE_ATTRIBUTE_READONLY
;
139 FileDirNdx
->SysAttr
= NTAttr
;
141 } // end UDFAttributesToNT()
147 IN PDIR_INDEX_ITEM FileDirNdx
,
152 PULONG attr
; //permissions
157 NTAttr
&= UDF_VALID_FILE_ATTRIBUTES
;
161 if(!FileDirNdx
->FileInfo
)
163 ValidateFileInfo(FileDirNdx
->FileInfo
);
164 FileEntry
= FileDirNdx
->FileInfo
->Dloc
->FileEntry
;
165 FileDirNdx
->FileInfo
->Dloc
->FE_Flags
|= UDF_FE_FLAG_FE_MODIFIED
;
167 if(FileEntry
->tagIdent
== TID_FILE_ENTRY
) {
168 attr
= &((PFILE_ENTRY
)FileEntry
)->permissions
;
169 Flags
= &((PFILE_ENTRY
)FileEntry
)->icbTag
.flags
;
170 Type
= &((PFILE_ENTRY
)FileEntry
)->icbTag
.fileType
;
172 attr
= &((PEXTENDED_FILE_ENTRY
)FileEntry
)->permissions
;
173 Flags
= &((PEXTENDED_FILE_ENTRY
)FileEntry
)->icbTag
.flags
;
174 Type
= &((PEXTENDED_FILE_ENTRY
)FileEntry
)->icbTag
.fileType
;
176 FCharact
= &(FileDirNdx
->FileCharacteristics
);
178 if((*FCharact
& FILE_DIRECTORY
) ||
179 (*Type
== UDF_FILE_TYPE_STREAMDIR
) ||
180 (*Type
== UDF_FILE_TYPE_DIRECTORY
)) {
181 *FCharact
|= FILE_DIRECTORY
;
182 if(*Type
!= UDF_FILE_TYPE_STREAMDIR
)
183 *Type
= UDF_FILE_TYPE_DIRECTORY
;
184 *attr
|= (PERM_O_EXEC
| PERM_G_EXEC
| PERM_U_EXEC
);
185 NTAttr
|= FILE_ATTRIBUTE_DIRECTORY
;
186 NTAttr
&= ~FILE_ATTRIBUTE_NORMAL
;
188 *FCharact
&= ~FILE_DIRECTORY
;
189 *Type
= UDF_FILE_TYPE_REGULAR
;
190 *attr
&= ~(PERM_O_EXEC
| PERM_G_EXEC
| PERM_U_EXEC
);
193 if(NTAttr
& FILE_ATTRIBUTE_SYSTEM
) {
194 *Flags
|= ICB_FLAG_SYSTEM
;
196 *Flags
&= ~ICB_FLAG_SYSTEM
;
198 if(NTAttr
& FILE_ATTRIBUTE_ARCHIVE
) {
199 *Flags
|= ICB_FLAG_ARCHIVE
;
201 *Flags
&= ~ICB_FLAG_ARCHIVE
;
203 if(NTAttr
& FILE_ATTRIBUTE_HIDDEN
) {
204 *FCharact
|= FILE_HIDDEN
;
206 *FCharact
&= ~FILE_HIDDEN
;
208 *attr
|= (PERM_O_READ
| PERM_G_READ
| PERM_U_READ
);
209 if(!(NTAttr
& FILE_ATTRIBUTE_READONLY
)) {
210 *attr
|= (PERM_O_WRITE
| PERM_G_WRITE
| PERM_U_WRITE
|
211 PERM_O_DELETE
| PERM_G_DELETE
| PERM_U_DELETE
|
212 PERM_O_CHATTR
| PERM_G_CHATTR
| PERM_U_CHATTR
);
214 *attr
&= ~(PERM_O_WRITE
| PERM_G_WRITE
| PERM_U_WRITE
|
215 PERM_O_DELETE
| PERM_G_DELETE
| PERM_U_DELETE
|
216 PERM_O_CHATTR
| PERM_G_CHATTR
| PERM_U_CHATTR
);
218 FileDirNdx
->SysAttr
= NTAttr
;
219 if(FileDirNdx
->FileInfo
)
220 FileDirNdx
->FileInfo
->Dloc
->FE_Flags
|= UDF_FE_FLAG_FE_MODIFIED
;
221 FileDirNdx
->FI_Flags
|= UDF_FI_FLAG_FI_MODIFIED
;
223 } // end UDFAttributesToUDF()
227 This routine fills PFILE_BOTH_DIR_INFORMATION structure (NT)
232 IN PDIR_INDEX_ITEM FileDirNdx
,
233 OUT PFILE_BOTH_DIR_INFORMATION NTFileInfo
236 PFILE_ENTRY FileEntry
;
237 UNICODE_STRING UdfName
;
238 UNICODE_STRING DosName
;
239 PEXTENDED_FILE_ENTRY ExFileEntry
;
243 PtrUDFNTRequiredFCB NtReqFcb
;
245 KdPrint(("@=%#x, FileDirNdx %x\n", &Vcb
, FileDirNdx
));
247 ASSERT((ULONG
)NTFileInfo
> 0x1000);
248 RtlZeroMemory(NTFileInfo
, sizeof(FILE_BOTH_DIR_INFORMATION
));
250 DosName
.Buffer
= (PWCHAR
)&(NTFileInfo
->ShortName
);
251 DosName
.MaximumLength
= sizeof(NTFileInfo
->ShortName
); // 12*sizeof(WCHAR)
254 KdPrint((" DirInfoToNT: %*.*S\n", FileDirNdx
->FName
.Length
/sizeof(WCHAR
), FileDirNdx
->FName
.Length
/sizeof(WCHAR
), FileDirNdx
->FName
));
255 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
256 KdPrint((" DirInfoToNT: exception when printing file name\n"));
259 if(FileDirNdx
->FileInfo
) {
260 KdPrint((" FileInfo\n"));
262 ValidateFileInfo(FileDirNdx
->FileInfo
);
263 if(UDFGetFileLinkCount(FileDirNdx
->FileInfo
) > 1)
264 FileDirNdx
->FI_Flags
|= UDF_FI_FLAG_LINKED
;
265 FileEntry
= (PFILE_ENTRY
)(FileDirNdx
->FileInfo
->Dloc
->FileEntry
);
266 // read required sizes from Fcb (if any) if file is not linked
267 // otherwise we should read them from FileEntry
268 if(FileDirNdx
->FileInfo
->Fcb
) {
270 NtReqFcb
= FileDirNdx
->FileInfo
->Fcb
->NTRequiredFCB
;
271 NTFileInfo
->CreationTime
.QuadPart
= NtReqFcb
->CreationTime
.QuadPart
;
272 NTFileInfo
->LastWriteTime
.QuadPart
= NtReqFcb
->LastWriteTime
.QuadPart
;
273 NTFileInfo
->LastAccessTime
.QuadPart
= NtReqFcb
->LastAccessTime
.QuadPart
;
274 NTFileInfo
->ChangeTime
.QuadPart
= NtReqFcb
->ChangeTime
.QuadPart
;
275 // NTFileInfo->AllocationSize.QuadPart = NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart;
276 NTFileInfo
->AllocationSize
.QuadPart
= FileDirNdx
->AllocationSize
;
277 /* FileDirNdx->FileSize =
278 NTFileInfo->EndOfFile.QuadPart = NtReqFcb->CommonFCBHeader.FileSize.QuadPart;*/
279 NTFileInfo
->EndOfFile
.QuadPart
= FileDirNdx
->FileSize
;
280 if(FileDirNdx
->FI_Flags
& UDF_FI_FLAG_SYS_ATTR
) {
281 KdPrint((" SYS_ATTR\n"));
282 NTFileInfo
->FileAttributes
= FileDirNdx
->SysAttr
;
285 FileDirNdx
->CreationTime
= NTFileInfo
->CreationTime
.QuadPart
;
286 FileDirNdx
->LastWriteTime
= NTFileInfo
->LastWriteTime
.QuadPart
;
287 FileDirNdx
->LastAccessTime
= NTFileInfo
->LastAccessTime
.QuadPart
;
288 FileDirNdx
->ChangeTime
= NTFileInfo
->ChangeTime
.QuadPart
;
292 } else if(!(FileDirNdx
->FI_Flags
& UDF_FI_FLAG_SYS_ATTR
) ||
293 (FileDirNdx
->FI_Flags
& UDF_FI_FLAG_LINKED
)) {
296 KdPrint((" !SYS_ATTR\n"));
297 FileEntry
= (PFILE_ENTRY
)MyAllocatePool__(NonPagedPool
, Vcb
->LBlockSize
);
298 if(!FileEntry
) return STATUS_INSUFFICIENT_RESOURCES
;
300 feloc
.extLength
= Vcb
->LBlockSize
;
301 feloc
.extLocation
= FileDirNdx
->FileEntryLoc
;
303 if(!NT_SUCCESS(status
= UDFReadFileEntry(Vcb
, &feloc
, FileEntry
, &Ident
))) {
304 KdPrint((" !UDFReadFileEntry\n"));
305 MyFreePool__(FileEntry
);
311 KdPrint((" FileDirNdx\n"));
312 NTFileInfo
->CreationTime
.QuadPart
= FileDirNdx
->CreationTime
;
313 NTFileInfo
->LastWriteTime
.QuadPart
= FileDirNdx
->LastWriteTime
;
314 NTFileInfo
->LastAccessTime
.QuadPart
= FileDirNdx
->LastAccessTime
;
315 NTFileInfo
->ChangeTime
.QuadPart
= FileDirNdx
->ChangeTime
;
316 NTFileInfo
->FileAttributes
= FileDirNdx
->SysAttr
;
317 NTFileInfo
->AllocationSize
.QuadPart
= FileDirNdx
->AllocationSize
;
318 NTFileInfo
->EndOfFile
.QuadPart
= FileDirNdx
->FileSize
;
319 NTFileInfo
->EaSize
= 0;
324 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
)
327 KdPrint((" direct\n"));
328 if(FileEntry
->descTag
.tagIdent
== TID_FILE_ENTRY
) {
329 KdPrint((" TID_FILE_ENTRY\n"));
331 KdPrint((" ReadSizes\n"));
333 FileDirNdx
->CreationTime
= NTFileInfo
->CreationTime
.QuadPart
=
334 FileDirNdx
->LastWriteTime
= NTFileInfo
->LastWriteTime
.QuadPart
= UDFTimeToNT(&(FileEntry
->modificationTime
));
335 FileDirNdx
->LastAccessTime
= NTFileInfo
->LastAccessTime
.QuadPart
= UDFTimeToNT(&(FileEntry
->accessTime
));
336 FileDirNdx
->ChangeTime
= NTFileInfo
->ChangeTime
.QuadPart
= UDFTimeToNT(&(FileEntry
->attrTime
));
338 FileDirNdx
->FileSize
=
339 NTFileInfo
->EndOfFile
.QuadPart
=
340 FileEntry
->informationLength
;
341 KdPrint((" informationLength=%I64x, lengthAllocDescs=%I64x\n",
342 FileEntry
->informationLength
,
343 FileEntry
->lengthAllocDescs
346 FileDirNdx
->AllocationSize
=
347 NTFileInfo
->AllocationSize
.QuadPart
=
348 (FileEntry
->informationLength
+ Vcb
->LBlockSize
- 1) & ~((LONGLONG
)(Vcb
->LBlockSize
) - 1);
350 // NTFileInfo->EaSize = 0;//FileEntry->lengthExtendedAttr;
351 } else if(FileEntry
->descTag
.tagIdent
== TID_EXTENDED_FILE_ENTRY
) {
352 ExFileEntry
= (PEXTENDED_FILE_ENTRY
)FileEntry
;
353 KdPrint((" PEXTENDED_FILE_ENTRY\n"));
355 KdPrint((" ReadSizes\n"));
357 FileDirNdx
->CreationTime
= NTFileInfo
->CreationTime
.QuadPart
= UDFTimeToNT(&(ExFileEntry
->createTime
));
358 FileDirNdx
->LastWriteTime
= NTFileInfo
->LastWriteTime
.QuadPart
= UDFTimeToNT(&(ExFileEntry
->modificationTime
));
359 FileDirNdx
->LastAccessTime
= NTFileInfo
->LastAccessTime
.QuadPart
= UDFTimeToNT(&(ExFileEntry
->accessTime
));
360 FileDirNdx
->ChangeTime
= NTFileInfo
->ChangeTime
.QuadPart
= UDFTimeToNT(&(ExFileEntry
->attrTime
));
362 FileDirNdx
->FileSize
=
363 NTFileInfo
->EndOfFile
.QuadPart
=
364 ExFileEntry
->informationLength
;
365 KdPrint((" informationLength=%I64x, lengthAllocDescs=%I64x\n",
366 FileEntry
->informationLength
,
367 FileEntry
->lengthAllocDescs
370 FileDirNdx
->AllocationSize
=
371 NTFileInfo
->AllocationSize
.QuadPart
=
372 (ExFileEntry
->informationLength
+ Vcb
->LBlockSize
- 1) & ~((LONGLONG
)(Vcb
->LBlockSize
) - 1);
374 // NTFileInfo->EaSize = 0;//ExFileEntry->lengthExtendedAttr;
382 KdPrint((" get_attr"));
383 // do some substitutions
384 if(!FileDirNdx
->CreationTime
) {
385 FileDirNdx
->CreationTime
= NTFileInfo
->CreationTime
.QuadPart
= Vcb
->VolCreationTime
;
387 if(!FileDirNdx
->LastAccessTime
) {
388 FileDirNdx
->LastAccessTime
= NTFileInfo
->LastAccessTime
.QuadPart
= FileDirNdx
->CreationTime
;
390 if(!FileDirNdx
->LastWriteTime
) {
391 FileDirNdx
->LastWriteTime
= NTFileInfo
->LastWriteTime
.QuadPart
= FileDirNdx
->CreationTime
;
393 if(!FileDirNdx
->ChangeTime
) {
394 FileDirNdx
->ChangeTime
= NTFileInfo
->ChangeTime
.QuadPart
= FileDirNdx
->CreationTime
;
397 FileDirNdx
->SysAttr
=
398 NTFileInfo
->FileAttributes
= UDFAttributesToNT(FileDirNdx
, (tag
*)FileEntry
);
399 FileDirNdx
->FI_Flags
|= UDF_FI_FLAG_SYS_ATTR
;
402 // get filename in standard Unicode format
403 UdfName
= FileDirNdx
->FName
;
404 NTFileInfo
->FileNameLength
= UdfName
.Length
;
405 RtlCopyMemory((PCHAR
)&(NTFileInfo
->FileName
), (PCHAR
)(UdfName
.Buffer
), UdfName
.MaximumLength
);
406 if(!(FileDirNdx
->FI_Flags
& UDF_FI_FLAG_DOS
)) {
407 KdPrint((" !UDF_FI_FLAG_DOS"));
408 UDFDOSName(Vcb
, &DosName
, &UdfName
,
409 (FileDirNdx
->FI_Flags
& UDF_FI_FLAG_KEEP_NAME
) ? TRUE
: FALSE
);
410 NTFileInfo
->ShortNameLength
= (UCHAR
)DosName
.Length
;
412 // report zero EOF & AllocSize for Dirs
413 if(FileDirNdx
->FileCharacteristics
& FILE_DIRECTORY
) {
414 KdPrint((" FILE_DIRECTORY"));
415 NTFileInfo
->AllocationSize
.QuadPart
=
416 NTFileInfo
->EndOfFile
.QuadPart
= 0;
418 KdPrint((" AllocationSize=%I64x, NTFileInfo->EndOfFile=%I64x", NTFileInfo
->AllocationSize
.QuadPart
, NTFileInfo
->EndOfFile
.QuadPart
));
419 // free tmp buffer (if any)
421 if(FileEntry
&& !FileDirNdx
->FileInfo
)
422 MyFreePool__(FileEntry
);
423 return STATUS_SUCCESS
;
424 } // end UDFFileDirInfoToNT()
428 #ifndef UDF_READ_ONLY_BUILD
430 This routine changes xxxTime field(s) in (Ext)FileEntry
434 IN PUDF_FILE_INFO FileInfo
,
435 IN LONGLONG
* CrtTime
,
436 IN LONGLONG
* AccTime
,
437 IN LONGLONG
* AttrTime
,
442 PDIR_INDEX_ITEM DirNdx
;
444 ValidateFileInfo(FileInfo
);
446 FileInfo
->Dloc
->FE_Flags
|= UDF_FE_FLAG_FE_MODIFIED
;
447 DirNdx
= UDFDirIndex(UDFGetDirIndexByFileInfo(FileInfo
), FileInfo
->Index
);
448 Ident
= FileInfo
->Dloc
->FileEntry
->tagIdent
;
450 if(Ident
== TID_FILE_ENTRY
) {
451 PFILE_ENTRY fe
= (PFILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
);
454 if(DirNdx
&& *AccTime
) DirNdx
->LastAccessTime
= *AccTime
;
455 UDFTimeToUDF(*AccTime
, &(fe
->accessTime
));
458 if(DirNdx
&& *AttrTime
) DirNdx
->ChangeTime
= *AttrTime
;
459 UDFTimeToUDF(*AttrTime
, &(fe
->attrTime
));
462 if(DirNdx
&& *ChgTime
) DirNdx
->CreationTime
=
463 DirNdx
->LastWriteTime
= *ChgTime
;
464 UDFTimeToUDF(*ChgTime
, &(fe
->modificationTime
));
467 if(DirNdx
&& *CrtTime
) DirNdx
->CreationTime
=
468 DirNdx
->LastWriteTime
= *CrtTime
;
469 UDFTimeToUDF(*CrtTime
, &(fe
->modificationTime
));
472 } else if(Ident
== TID_EXTENDED_FILE_ENTRY
) {
473 PEXTENDED_FILE_ENTRY fe
= (PEXTENDED_FILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
);
476 if(DirNdx
&& *AccTime
) DirNdx
->LastAccessTime
= *AccTime
;
477 UDFTimeToUDF(*AccTime
, &(fe
->accessTime
));
480 if(DirNdx
&& *AttrTime
) DirNdx
->ChangeTime
= *AttrTime
;
481 UDFTimeToUDF(*AttrTime
, &(fe
->attrTime
));
484 if(DirNdx
&& *ChgTime
) DirNdx
->LastWriteTime
= *ChgTime
;
485 UDFTimeToUDF(*ChgTime
, &(fe
->modificationTime
));
488 if(DirNdx
&& *CrtTime
) DirNdx
->CreationTime
= *CrtTime
;
489 UDFTimeToUDF(*CrtTime
, &(fe
->createTime
));
493 } // end UDFSetFileXTime()
494 #endif //UDF_READ_ONLY_BUILD
497 This routine gets xxxTime field(s) in (Ext)FileEntry
501 IN PUDF_FILE_INFO FileInfo
,
502 OUT LONGLONG
* CrtTime
,
503 OUT LONGLONG
* AccTime
,
504 OUT LONGLONG
* AttrTime
,
505 OUT LONGLONG
* ChgTime
510 ValidateFileInfo(FileInfo
);
512 Ident
= FileInfo
->Dloc
->FileEntry
->tagIdent
;
514 if(Ident
== TID_FILE_ENTRY
) {
515 PFILE_ENTRY fe
= (PFILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
);
517 if(AccTime
) *AccTime
= UDFTimeToNT(&(fe
->accessTime
));
518 if(AttrTime
) *AttrTime
= UDFTimeToNT(&(fe
->attrTime
));
519 if(ChgTime
) *ChgTime
= UDFTimeToNT(&(fe
->modificationTime
));
521 (*CrtTime
) = *ChgTime
;
524 } else if(Ident
== TID_EXTENDED_FILE_ENTRY
) {
525 PEXTENDED_FILE_ENTRY fe
= (PEXTENDED_FILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
);
527 if(AccTime
) *AccTime
= UDFTimeToNT(&(fe
->accessTime
));
528 if(AttrTime
) *AttrTime
= UDFTimeToNT(&(fe
->attrTime
));
529 if(ChgTime
) *ChgTime
= UDFTimeToNT(&(fe
->modificationTime
));
530 if(CrtTime
) *CrtTime
= UDFTimeToNT(&(fe
->createTime
));
535 KeQuerySystemTime((PLARGE_INTEGER
)CrtTime
);
536 if(AccTime
&& !(*AccTime
)) (*AccTime
) = *CrtTime
;
537 if(AttrTime
&& !(*AttrTime
)) (*AttrTime
) = *CrtTime
;
538 if(AccTime
&& !(*AccTime
)) (*AccTime
) = *CrtTime
;
540 } // end UDFGetFileXTime()
543 UDFNormalizeFileName(
544 IN PUNICODE_STRING FName
,
551 len
= FName
->Length
/sizeof(WCHAR
);
552 buffer
= FName
->Buffer
;
554 // check for '', '.' & '..'
557 FName
->Length
-=sizeof(WCHAR
);
561 if(buffer
[0] == UNICODE_PERIOD
) {
563 if((buffer
[1] == UNICODE_PERIOD
) && (len
== 2)) return;
566 // check for trailing '.'
567 for(len
--;len
;len
--) {
568 if( ((buffer
[len
] == UNICODE_PERIOD
) || (buffer
[len
] == UNICODE_SPACE
)) ) {
569 FName
->Length
-=sizeof(WCHAR
);
574 } // end UDFNormalizeFileName()
581 IN OUT PUNICODE_STRING DosName
,
582 IN PUNICODE_STRING UdfName
,
583 IN BOOLEAN KeepIntact
586 PWCHAR dosName
= DosName
->Buffer
;
587 PWCHAR udfName
= UdfName
->Buffer
;
588 uint32 udfLen
= UdfName
->Length
/ sizeof(WCHAR
);
589 GENERATE_NAME_CONTEXT Ctx
;
592 (udfLen
<= 2) && (udfName
[0] == UNICODE_PERIOD
)) {
593 if((udfLen
!= 2) || (udfName
[1] == UNICODE_PERIOD
)) {
594 RtlCopyMemory(dosName
, udfName
, UdfName
->Length
);
595 DosName
->Length
= UdfName
->Length
;
599 RtlZeroMemory(&Ctx
, sizeof(GENERATE_NAME_CONTEXT
));
600 RtlGenerate8dot3Name(UdfName
, FALSE
, &Ctx
, DosName
);
602 } // UDFDOSNameOsNative()
607 UDFNormalizeFileName(
608 IN PUNICODE_STRING FName,
612 WCHAR _newName[UDF_NAME_LEN+5];
613 PWCHAR newName = (PWCHAR)(&_newName);
614 PWCHAR udfName = FName->Buffer;
615 LONG udfLen = FName->Length >> 1;
617 LONG index, newIndex = 0, extIndex = 0, newExtIndex = 0, trailIndex = 0;
618 BOOLEAN needsCRC = FALSE, hasExt = FALSE;
619 WCHAR ext[UDF_EXT_SIZE], current;
621 // handle CurrentDir ('.') and ParentDir ('..') cases
622 if((udfLen <= 2) && (udfName[0] == UNICODE_PERIOD)) {
623 if((udfLen != 2) || (udfName[1] == UNICODE_PERIOD))
627 for (index = 0 ; index < udfLen ; index++) {
628 current = udfName[index];
630 // Look for illegal or unprintable characters.
631 if (UDFIsIllegalChar(current) || !UnicodeIsPrint(current)) {
633 current = ILLEGAL_CHAR_MARK;
634 // Skip Illegal characters(even spaces),
636 while(index+1 < udfLen &&
637 (UDFIsIllegalChar(udfName[index+1]) ||
638 !UnicodeIsPrint(udfName[index+1])) &&
639 udfName[index+1] != UNICODE_PERIOD)
643 // Record position of extension, if one is found.
644 if ((current == UNICODE_PERIOD) && ((udfLen - index -1) <= UDF_EXT_SIZE)) {
645 if (udfLen == index + 1) {
646 // A trailing period is NOT an extension.
651 newExtIndex = newIndex;
653 } else if((current != UNICODE_PERIOD) && (current != UNICODE_SPACE)) {
657 // if (newIndex < MAXLEN) // tshi is always TRUE for WINNT
658 newName[newIndex] = current;
661 // For OS2, 95 & NT, truncate any trailing periods and\or spaces.
662 if (trailIndex != (newIndex - 1)) {
663 newIndex = trailIndex + 1;
665 hasExt = FALSE; //* Trailing period does not make an extension.
670 int localExtIndex = 0;
673 //* Translate extension, and store it in ext.
674 for(index = 0; index<UDF_EXT_SIZE && extIndex + index +1 < udfLen; index++ ) {
675 current = udfName[extIndex + index + 1];
676 if (UDFIsIllegalChar(current) /*|| !UnicodeIsPrint(current)) {
678 // Replace Illegal and non-displayable chars
680 current = ILLEGAL_CHAR_MARK;
681 // Skip any other illegal or non-displayable
683 while(index + 1 < UDF_EXT_SIZE &&
684 (UDFIsIllegalChar(udfName[extIndex + index + 2]) ||
685 !UnicodeIsPrint(udfName[extIndex + index + 2])) )
688 ext[localExtIndex++] = current;
690 // Truncate filename to leave room for extension and CRC.
691 maxFilenameLen = ((UDF_NAME_LEN - 4) - localExtIndex - 1);
692 if (newIndex > maxFilenameLen) {
693 newIndex = maxFilenameLen;
695 newIndex = newExtIndex;
697 } else if (newIndex > UDF_NAME_LEN - 5) {
698 //If no extension, make sure to leave room for CRC.
699 newIndex = UDF_NAME_LEN - 5;
701 newName[newIndex++] = UNICODE_CRC_MARK; // Add mark for CRC.
702 //Calculate CRC from original filename from FileIdentifier.
703 // valueCRC = UDFUnicodeCksum(fidName, fidNameLen);
704 // / Convert 16-bits of CRC to hex characters.
705 newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12];
706 newName[newIndex++] = hexChar[(valueCRC & 0x0f00) >> 8];
707 newName[newIndex++] = hexChar[(valueCRC & 0x00f0) >> 4];
708 newName[newIndex++] = hexChar[(valueCRC & 0x000f)];
709 // Place a translated extension at end, if found.
711 newName[newIndex++] = UNICODE_PERIOD;
712 for (index = 0;index < localExtIndex ;index++ ) {
713 newName[newIndex++] = ext[index];
718 if(FName->Length == (USHORT)newIndex*sizeof(WCHAR)) {
719 RtlCopyMemory(FName->Buffer, newName, newIndex*sizeof(WCHAR));
722 MyFreePool__(FName->Buffer);
723 FName->Buffer = (PWCHAR)MyAllocatePool__(UDF_FILENAME_MT, (newIndex+1)*sizeof(WCHAR));
725 FName->Buffer[newIndex] = 0;
726 RtlCopyMemory(FName->Buffer, newName, newIndex*sizeof(WCHAR));
728 FName->Length = (USHORT)newIndex*sizeof(WCHAR);
729 FName->MaximumLength = (USHORT)(newIndex+1)*sizeof(WCHAR);
734 return ExAllocateFromZone(&(UDFGlobalData.FileInfoZoneHeader));
737 #define STRING_BUFFER_ALIGNMENT (32)
738 #define STRING_BUFFER_ALIGN(sz) (((sz)+STRING_BUFFER_ALIGNMENT)&(~((ULONG)(STRING_BUFFER_ALIGNMENT-1))))
741 MyAppendUnicodeStringToString_(
742 IN PUNICODE_STRING Str1
,
743 IN PUNICODE_STRING Str2
744 #ifdef UDF_TRACK_UNICODE_STR
752 #ifdef UDF_TRACK_UNICODE_STR
753 #define UDF_UNC_STR_TAG Tag
755 #define UDF_UNC_STR_TAG "AppUStr"
759 i
= Str1
->Length
+ Str2
->Length
+ sizeof(WCHAR
);
760 ASSERT(Str1
->MaximumLength
);
761 if(i
> Str1
->MaximumLength
) {
762 if(!MyReallocPool__((PCHAR
)tmp
, Str1
->MaximumLength
,
763 (PCHAR
*)&tmp
, STRING_BUFFER_ALIGN(i
)*2) ) {
764 return STATUS_INSUFFICIENT_RESOURCES
;
766 Str1
->MaximumLength
= i
*2;
769 RtlCopyMemory(((PCHAR
)tmp
)+Str1
->Length
, Str2
->Buffer
, Str2
->Length
);
771 /* tmp = (PWCHAR)MyAllocatePoolTag__(NonPagedPool, i = Str1->Length + Str2->Length + sizeof(WCHAR), UDF_UNC_STR_TAG);
773 return STATUS_INSUFFICIENT_RESOURCES;
774 RtlCopyMemory(tmp, Str1->Buffer, Str1->Length);
775 RtlCopyMemory(((PCHAR)tmp)+Str1->Length, Str2->Buffer, Str2->Length);*/
776 tmp
[(i
/ sizeof(WCHAR
)) - 1] = 0;
777 Str1
->Length
= i
- sizeof(WCHAR
);
778 //MyFreePool__(Str1->Buffer);
780 if(Str1
->Buffer
&& (Str1
->Length
>= 2*sizeof(WCHAR
))) {
781 ASSERT((Str1
->Buffer
[0] != L
'\\') || (Str1
->Buffer
[1] != L
'\\'));
784 return STATUS_SUCCESS
;
786 #undef UDF_UNC_STR_TAG
788 } // end MyAppendUnicodeStringToString()
791 MyAppendUnicodeToString_(
792 IN PUNICODE_STRING Str1
,
794 #ifdef UDF_TRACK_UNICODE_STR
802 #ifdef UDF_TRACK_UNICODE_STR
803 #define UDF_UNC_STR_TAG Tag
805 #define UDF_UNC_STR_TAG "AppStr"
817 __asm cmp
[word ptr esi
+ebx
],0
827 #else // NO X86 optimization, use generic C/C++
838 ASSERT(Str1
->MaximumLength
);
839 if((Str1
->Length
+i
+sizeof(WCHAR
)) > Str1
->MaximumLength
) {
840 if(!MyReallocPool__((PCHAR
)tmp
, Str1
->MaximumLength
,
841 (PCHAR
*)&tmp
, STRING_BUFFER_ALIGN(i
+ Str1
->Length
+ sizeof(WCHAR
))*2 ) ) {
842 return STATUS_INSUFFICIENT_RESOURCES
;
844 Str1
->MaximumLength
= STRING_BUFFER_ALIGN(i
+ sizeof(WCHAR
))*2;
847 RtlCopyMemory(((PCHAR
)tmp
)+Str1
->Length
, Str2
, i
);
849 tmp
[(i
/ sizeof(WCHAR
))] = 0;
852 /* if(Str1->Buffer && (Str1->Length >= 2*sizeof(WCHAR))) {
853 ASSERT((Str1->Buffer[0] != L'\\') || (Str1->Buffer[1] != L'\\'));
856 return STATUS_SUCCESS
;
858 #undef UDF_UNC_STR_TAG
860 } // end MyAppendUnicodeToString_()
864 IN PUNICODE_STRING Str1
,
880 __asm cmp
[word ptr esi
+ebx
],0
890 #else // NO X86 optimization, use generic C/C++
900 Str1
->MaximumLength
= STRING_BUFFER_ALIGN((Str1
->Length
= i
) + sizeof(WCHAR
));
901 Str1
->Buffer
= (PWCHAR
)MyAllocatePool__(NonPagedPool
, Str1
->MaximumLength
);
903 return STATUS_INSUFFICIENT_RESOURCES
;
904 RtlCopyMemory(Str1
->Buffer
, Str2
, i
);
905 Str1
->Buffer
[i
/sizeof(WCHAR
)] = 0;
906 return STATUS_SUCCESS
;
908 } // end MyInitUnicodeString()
911 MyCloneUnicodeString(
912 IN PUNICODE_STRING Str1
,
913 IN PUNICODE_STRING Str2
916 Str1
->MaximumLength
= STRING_BUFFER_ALIGN((Str1
->Length
= Str2
->Length
) + sizeof(WCHAR
));
917 Str1
->Buffer
= (PWCHAR
)MyAllocatePool__(NonPagedPool
, Str1
->MaximumLength
);
919 return STATUS_INSUFFICIENT_RESOURCES
;
920 ASSERT(Str2
->Buffer
);
921 RtlCopyMemory(Str1
->Buffer
, Str2
->Buffer
, Str2
->Length
);
922 Str1
->Buffer
[Str1
->Length
/sizeof(WCHAR
)] = 0;
923 return STATUS_SUCCESS
;
925 } // end MyCloneUnicodeString()
928 This routine checks do we needn't read something from disk to
929 obtain Attributes & so on
934 IN PUDF_FILE_INFO DirInfo
937 PDIR_INDEX_HDR hDirNdx
= DirInfo
->Dloc
->DirIndex
;
938 PDIR_INDEX_ITEM DirNdx
;
939 for(uint_di i
=2; DirNdx
= UDFDirIndex(hDirNdx
,i
); i
++) {
940 if(!(DirNdx
->FI_Flags
& UDF_FI_FLAG_SYS_ATTR
) ||
941 (DirNdx
->FI_Flags
& UDF_FI_FLAG_LINKED
)) return FALSE
;
944 } // end UDFIsDirInfoCached()
946 #ifndef UDF_READ_ONLY_BUILD
948 UDFDoesOSAllowFileToBeTargetForRename__(
949 IN PUDF_FILE_INFO FileInfo
956 if(UDFIsADirectory(FileInfo
))
957 return STATUS_ACCESS_DENIED
;
958 if(!FileInfo
->ParentFile
)
959 return STATUS_ACCESS_DENIED
;
961 if(UDFAttributesToNT(UDFDirIndex(UDFGetDirIndexByFileInfo(FileInfo
),FileInfo
->Index
),
962 FileInfo
->Dloc
->FileEntry
) & FILE_ATTRIBUTE_READONLY
)
963 return STATUS_ACCESS_DENIED
;
966 return STATUS_SUCCESS
;
968 RC
= UDFCheckAccessRights(NULL
, NULL
, FileInfo
->Fcb
, NULL
, DELETE
, 0);
973 return STATUS_SUCCESS
;
974 // RC = UDFMarkStreamsForDeletion(FileInfo->Fcb->Vcb, FileInfo->Fcb, TRUE); // Delete
975 /* RC = UDFSetDispositionInformation(FileInfo->Fcb, NULL,
976 FileInfo->Fcb->Vcb, NULL, TRUE);
978 FileInfo->Fcb->FCBFlags |= UDF_FCB_DELETED;
979 if(UDFGetFileLinkCount(FileInfo) <= 1) {
980 FileInfo->Fcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_DELETED;
984 return STATUS_ACCESS_DENIED
;
986 } // end UDFDoesOSAllowFileToBeTargetForRename__()
989 UDFDoesOSAllowFileToBeUnlinked__(
990 IN PUDF_FILE_INFO FileInfo
993 PDIR_INDEX_HDR hCurDirNdx
;
994 PDIR_INDEX_ITEM CurDirNdx
;
996 // IO_STATUS_BLOCK IoStatus;
998 ASSERT(FileInfo
->Dloc
);
1000 if(!FileInfo
->ParentFile
)
1001 return STATUS_CANNOT_DELETE
;
1002 if(FileInfo
->Dloc
->SDirInfo
)
1003 return STATUS_CANNOT_DELETE
;
1004 if(!UDFIsADirectory(FileInfo
))
1005 return STATUS_SUCCESS
;
1007 // UDFFlushAFile(FileInfo->Fcb, NULL, &IoStatus, 0);
1008 hCurDirNdx
= FileInfo
->Dloc
->DirIndex
;
1009 // check if we can delete all files
1010 for(i
=2; CurDirNdx
= UDFDirIndex(hCurDirNdx
,i
); i
++) {
1011 // try to open Stream
1012 if(CurDirNdx
->FileInfo
)
1013 return STATUS_CANNOT_DELETE
;
1015 // return UDFCheckAccessRights(NULL, NULL, FileInfo->Fcb, NULL, DELETE, 0);
1016 return STATUS_SUCCESS
;
1017 } // end UDFDoesOSAllowFileToBeUnlinked__()
1020 UDFDoesOSAllowFilePretendDeleted__(
1021 IN PUDF_FILE_INFO FileInfo
1024 PDIR_INDEX_HDR hDirNdx
= UDFGetDirIndexByFileInfo(FileInfo
);
1025 if(!hDirNdx
) return STATUS_CANNOT_DELETE
;
1026 PDIR_INDEX_ITEM DirNdx
= UDFDirIndex(hDirNdx
, FileInfo
->Index
);
1027 if(!DirNdx
) return STATUS_CANNOT_DELETE
;
1028 // we can't hide file that is not marked as deleted
1029 if(!(DirNdx
->FileCharacteristics
& FILE_DELETED
)) {
1033 if(!(FileInfo
->Fcb
->FCBFlags
& (UDF_FCB_DELETE_ON_CLOSE
|
1037 return STATUS_CANNOT_DELETE
;
1039 return STATUS_SUCCESS
;
1041 #endif //UDF_READ_ONLY_BUILD