1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
13 This file contains filesystem-specific routines
19 #define UDF_BUG_CHECK_ID UDF_FILE_UDF_INFO
22 static const int8 valid_char_arr
[] =
23 {1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
24 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
25 1,0,1,0, 0,0,0,0, 0,0,1,1, 1,0,0,1,
26 0,0,0,0, 0,0,0,0, 0,0,1,1, 1,1,1,1,
27 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // @ABCDE....
28 0,0,0,0, 0,0,0,0, 0,0,0,1, 1,1,0,0, // ....Z[/]^_
29 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // `abcde....
30 0,0,0,0, 0,0,0,0, 0,0,0,1, 1,1,0,1, // ....z{|}~
32 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
33 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
34 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
35 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
36 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
37 1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
38 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
39 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
40 #else // NO X86 optimization , use generic C/C++
41 static const char valid_char_arr
[] = {"*/:?\"<>|\\"};
44 #define DOS_CRC_MODULUS 41
45 #define hexChar crcChar
46 static const char crcChar
[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ#_~-@";
48 /* Used to convert hex digits to ASCII for readability. */
49 //static const char hexChar[] = "0123456789ABCDEF";
51 static const uint16 CrcTable
[256] = {
52 0x0000U
, 0x1021U
, 0x2042U
, 0x3063U
, 0x4084U
, 0x50a5U
, 0x60c6U
, 0x70e7U
,
53 0x8108U
, 0x9129U
, 0xa14aU
, 0xb16bU
, 0xc18cU
, 0xd1adU
, 0xe1ceU
, 0xf1efU
,
54 0x1231U
, 0x0210U
, 0x3273U
, 0x2252U
, 0x52b5U
, 0x4294U
, 0x72f7U
, 0x62d6U
,
55 0x9339U
, 0x8318U
, 0xb37bU
, 0xa35aU
, 0xd3bdU
, 0xc39cU
, 0xf3ffU
, 0xe3deU
,
56 0x2462U
, 0x3443U
, 0x0420U
, 0x1401U
, 0x64e6U
, 0x74c7U
, 0x44a4U
, 0x5485U
,
57 0xa56aU
, 0xb54bU
, 0x8528U
, 0x9509U
, 0xe5eeU
, 0xf5cfU
, 0xc5acU
, 0xd58dU
,
58 0x3653U
, 0x2672U
, 0x1611U
, 0x0630U
, 0x76d7U
, 0x66f6U
, 0x5695U
, 0x46b4U
,
59 0xb75bU
, 0xa77aU
, 0x9719U
, 0x8738U
, 0xf7dfU
, 0xe7feU
, 0xd79dU
, 0xc7bcU
,
60 0x48c4U
, 0x58e5U
, 0x6886U
, 0x78a7U
, 0x0840U
, 0x1861U
, 0x2802U
, 0x3823U
,
61 0xc9ccU
, 0xd9edU
, 0xe98eU
, 0xf9afU
, 0x8948U
, 0x9969U
, 0xa90aU
, 0xb92bU
,
62 0x5af5U
, 0x4ad4U
, 0x7ab7U
, 0x6a96U
, 0x1a71U
, 0x0a50U
, 0x3a33U
, 0x2a12U
,
63 0xdbfdU
, 0xcbdcU
, 0xfbbfU
, 0xeb9eU
, 0x9b79U
, 0x8b58U
, 0xbb3bU
, 0xab1aU
,
64 0x6ca6U
, 0x7c87U
, 0x4ce4U
, 0x5cc5U
, 0x2c22U
, 0x3c03U
, 0x0c60U
, 0x1c41U
,
65 0xedaeU
, 0xfd8fU
, 0xcdecU
, 0xddcdU
, 0xad2aU
, 0xbd0bU
, 0x8d68U
, 0x9d49U
,
66 0x7e97U
, 0x6eb6U
, 0x5ed5U
, 0x4ef4U
, 0x3e13U
, 0x2e32U
, 0x1e51U
, 0x0e70U
,
67 0xff9fU
, 0xefbeU
, 0xdfddU
, 0xcffcU
, 0xbf1bU
, 0xaf3aU
, 0x9f59U
, 0x8f78U
,
68 0x9188U
, 0x81a9U
, 0xb1caU
, 0xa1ebU
, 0xd10cU
, 0xc12dU
, 0xf14eU
, 0xe16fU
,
69 0x1080U
, 0x00a1U
, 0x30c2U
, 0x20e3U
, 0x5004U
, 0x4025U
, 0x7046U
, 0x6067U
,
70 0x83b9U
, 0x9398U
, 0xa3fbU
, 0xb3daU
, 0xc33dU
, 0xd31cU
, 0xe37fU
, 0xf35eU
,
71 0x02b1U
, 0x1290U
, 0x22f3U
, 0x32d2U
, 0x4235U
, 0x5214U
, 0x6277U
, 0x7256U
,
72 0xb5eaU
, 0xa5cbU
, 0x95a8U
, 0x8589U
, 0xf56eU
, 0xe54fU
, 0xd52cU
, 0xc50dU
,
73 0x34e2U
, 0x24c3U
, 0x14a0U
, 0x0481U
, 0x7466U
, 0x6447U
, 0x5424U
, 0x4405U
,
74 0xa7dbU
, 0xb7faU
, 0x8799U
, 0x97b8U
, 0xe75fU
, 0xf77eU
, 0xc71dU
, 0xd73cU
,
75 0x26d3U
, 0x36f2U
, 0x0691U
, 0x16b0U
, 0x6657U
, 0x7676U
, 0x4615U
, 0x5634U
,
76 0xd94cU
, 0xc96dU
, 0xf90eU
, 0xe92fU
, 0x99c8U
, 0x89e9U
, 0xb98aU
, 0xa9abU
,
77 0x5844U
, 0x4865U
, 0x7806U
, 0x6827U
, 0x18c0U
, 0x08e1U
, 0x3882U
, 0x28a3U
,
78 0xcb7dU
, 0xdb5cU
, 0xeb3fU
, 0xfb1eU
, 0x8bf9U
, 0x9bd8U
, 0xabbbU
, 0xbb9aU
,
79 0x4a75U
, 0x5a54U
, 0x6a37U
, 0x7a16U
, 0x0af1U
, 0x1ad0U
, 0x2ab3U
, 0x3a92U
,
80 0xfd2eU
, 0xed0fU
, 0xdd6cU
, 0xcd4dU
, 0xbdaaU
, 0xad8bU
, 0x9de8U
, 0x8dc9U
,
81 0x7c26U
, 0x6c07U
, 0x5c64U
, 0x4c45U
, 0x3ca2U
, 0x2c83U
, 0x1ce0U
, 0x0cc1U
,
82 0xef1fU
, 0xff3eU
, 0xcf5dU
, 0xdf7cU
, 0xaf9bU
, 0xbfbaU
, 0x8fd9U
, 0x9ff8U
,
83 0x6e17U
, 0x7e36U
, 0x4e55U
, 0x5e74U
, 0x2e93U
, 0x3eb2U
, 0x0ed1U
, 0x1ef0U
86 static const uint32 crc32_tab
[] = {
87 0x00000000L
, 0x77073096L
, 0xee0e612cL
, 0x990951baL
, 0x076dc419L
,
88 0x706af48fL
, 0xe963a535L
, 0x9e6495a3L
, 0x0edb8832L
, 0x79dcb8a4L
,
89 0xe0d5e91eL
, 0x97d2d988L
, 0x09b64c2bL
, 0x7eb17cbdL
, 0xe7b82d07L
,
90 0x90bf1d91L
, 0x1db71064L
, 0x6ab020f2L
, 0xf3b97148L
, 0x84be41deL
,
91 0x1adad47dL
, 0x6ddde4ebL
, 0xf4d4b551L
, 0x83d385c7L
, 0x136c9856L
,
92 0x646ba8c0L
, 0xfd62f97aL
, 0x8a65c9ecL
, 0x14015c4fL
, 0x63066cd9L
,
93 0xfa0f3d63L
, 0x8d080df5L
, 0x3b6e20c8L
, 0x4c69105eL
, 0xd56041e4L
,
94 0xa2677172L
, 0x3c03e4d1L
, 0x4b04d447L
, 0xd20d85fdL
, 0xa50ab56bL
,
95 0x35b5a8faL
, 0x42b2986cL
, 0xdbbbc9d6L
, 0xacbcf940L
, 0x32d86ce3L
,
96 0x45df5c75L
, 0xdcd60dcfL
, 0xabd13d59L
, 0x26d930acL
, 0x51de003aL
,
97 0xc8d75180L
, 0xbfd06116L
, 0x21b4f4b5L
, 0x56b3c423L
, 0xcfba9599L
,
98 0xb8bda50fL
, 0x2802b89eL
, 0x5f058808L
, 0xc60cd9b2L
, 0xb10be924L
,
99 0x2f6f7c87L
, 0x58684c11L
, 0xc1611dabL
, 0xb6662d3dL
, 0x76dc4190L
,
100 0x01db7106L
, 0x98d220bcL
, 0xefd5102aL
, 0x71b18589L
, 0x06b6b51fL
,
101 0x9fbfe4a5L
, 0xe8b8d433L
, 0x7807c9a2L
, 0x0f00f934L
, 0x9609a88eL
,
102 0xe10e9818L
, 0x7f6a0dbbL
, 0x086d3d2dL
, 0x91646c97L
, 0xe6635c01L
,
103 0x6b6b51f4L
, 0x1c6c6162L
, 0x856530d8L
, 0xf262004eL
, 0x6c0695edL
,
104 0x1b01a57bL
, 0x8208f4c1L
, 0xf50fc457L
, 0x65b0d9c6L
, 0x12b7e950L
,
105 0x8bbeb8eaL
, 0xfcb9887cL
, 0x62dd1ddfL
, 0x15da2d49L
, 0x8cd37cf3L
,
106 0xfbd44c65L
, 0x4db26158L
, 0x3ab551ceL
, 0xa3bc0074L
, 0xd4bb30e2L
,
107 0x4adfa541L
, 0x3dd895d7L
, 0xa4d1c46dL
, 0xd3d6f4fbL
, 0x4369e96aL
,
108 0x346ed9fcL
, 0xad678846L
, 0xda60b8d0L
, 0x44042d73L
, 0x33031de5L
,
109 0xaa0a4c5fL
, 0xdd0d7cc9L
, 0x5005713cL
, 0x270241aaL
, 0xbe0b1010L
,
110 0xc90c2086L
, 0x5768b525L
, 0x206f85b3L
, 0xb966d409L
, 0xce61e49fL
,
111 0x5edef90eL
, 0x29d9c998L
, 0xb0d09822L
, 0xc7d7a8b4L
, 0x59b33d17L
,
112 0x2eb40d81L
, 0xb7bd5c3bL
, 0xc0ba6cadL
, 0xedb88320L
, 0x9abfb3b6L
,
113 0x03b6e20cL
, 0x74b1d29aL
, 0xead54739L
, 0x9dd277afL
, 0x04db2615L
,
114 0x73dc1683L
, 0xe3630b12L
, 0x94643b84L
, 0x0d6d6a3eL
, 0x7a6a5aa8L
,
115 0xe40ecf0bL
, 0x9309ff9dL
, 0x0a00ae27L
, 0x7d079eb1L
, 0xf00f9344L
,
116 0x8708a3d2L
, 0x1e01f268L
, 0x6906c2feL
, 0xf762575dL
, 0x806567cbL
,
117 0x196c3671L
, 0x6e6b06e7L
, 0xfed41b76L
, 0x89d32be0L
, 0x10da7a5aL
,
118 0x67dd4accL
, 0xf9b9df6fL
, 0x8ebeeff9L
, 0x17b7be43L
, 0x60b08ed5L
,
119 0xd6d6a3e8L
, 0xa1d1937eL
, 0x38d8c2c4L
, 0x4fdff252L
, 0xd1bb67f1L
,
120 0xa6bc5767L
, 0x3fb506ddL
, 0x48b2364bL
, 0xd80d2bdaL
, 0xaf0a1b4cL
,
121 0x36034af6L
, 0x41047a60L
, 0xdf60efc3L
, 0xa867df55L
, 0x316e8eefL
,
122 0x4669be79L
, 0xcb61b38cL
, 0xbc66831aL
, 0x256fd2a0L
, 0x5268e236L
,
123 0xcc0c7795L
, 0xbb0b4703L
, 0x220216b9L
, 0x5505262fL
, 0xc5ba3bbeL
,
124 0xb2bd0b28L
, 0x2bb45a92L
, 0x5cb36a04L
, 0xc2d7ffa7L
, 0xb5d0cf31L
,
125 0x2cd99e8bL
, 0x5bdeae1dL
, 0x9b64c2b0L
, 0xec63f226L
, 0x756aa39cL
,
126 0x026d930aL
, 0x9c0906a9L
, 0xeb0e363fL
, 0x72076785L
, 0x05005713L
,
127 0x95bf4a82L
, 0xe2b87a14L
, 0x7bb12baeL
, 0x0cb61b38L
, 0x92d28e9bL
,
128 0xe5d5be0dL
, 0x7cdcefb7L
, 0x0bdbdf21L
, 0x86d3d2d4L
, 0xf1d4e242L
,
129 0x68ddb3f8L
, 0x1fda836eL
, 0x81be16cdL
, 0xf6b9265bL
, 0x6fb077e1L
,
130 0x18b74777L
, 0x88085ae6L
, 0xff0f6a70L
, 0x66063bcaL
, 0x11010b5cL
,
131 0x8f659effL
, 0xf862ae69L
, 0x616bffd3L
, 0x166ccf45L
, 0xa00ae278L
,
132 0xd70dd2eeL
, 0x4e048354L
, 0x3903b3c2L
, 0xa7672661L
, 0xd06016f7L
,
133 0x4969474dL
, 0x3e6e77dbL
, 0xaed16a4aL
, 0xd9d65adcL
, 0x40df0b66L
,
134 0x37d83bf0L
, 0xa9bcae53L
, 0xdebb9ec5L
, 0x47b2cf7fL
, 0x30b5ffe9L
,
135 0xbdbdf21cL
, 0xcabac28aL
, 0x53b39330L
, 0x24b4a3a6L
, 0xbad03605L
,
136 0xcdd70693L
, 0x54de5729L
, 0x23d967bfL
, 0xb3667a2eL
, 0xc4614ab8L
,
137 0x5d681b02L
, 0x2a6f2b94L
, 0xb40bbe37L
, 0xc30c8ea1L
, 0x5a05df1bL
,
142 This routine allocates new memory block, copies data there & free old one
154 (*NewBuff) = OldBuff;
155 if(OldLength == NewLength) return OldLength;
156 new_buff = (int8*)MyAllocatePool__(NonPagedPool, NewLength);
157 if(!new_buff) return 0;
158 if(OldLength > NewLength) OldLength = NewLength;
159 RtlCopyMemory(new_buff, OldBuff, OldLength);
160 MyFreePool__(OldBuff);
161 (*NewBuff) = new_buff;
163 } // end UDFMemRealloc()*/
166 This routine converts compressed Unicode to standard
170 UDFDecompressUnicode(
171 IN OUT PUNICODE_STRING UName
,
177 uint16 compID
= CS0
[0];
178 uint32 unicodeIndex
= 0;
179 uint32 byteIndex
= 1;
183 if(!Length
) goto return_empty_str
;
184 // First check for valid compID.
186 case UDF_COMP_ID_8
: {
188 buff
= (PWCHAR
)MyAllocatePoolTag__(UDF_FILENAME_MT
, (Length
)*sizeof(WCHAR
), MEM_FNAME_TAG
);
189 if(!buff
) goto return_empty_str
;
190 UName
->Buffer
= buff
;
192 // Loop through all the bytes.
193 while (byteIndex
< Length
) {
199 unicodeIndex
= byteIndex
-1;
202 case UDF_COMP_ID_16
: {
204 buff
= (PWCHAR
)MyAllocatePoolTag__(UDF_FILENAME_MT
, (Length
-1)+sizeof(WCHAR
), MEM_FNAME16_TAG
);
205 if(!buff
) goto return_empty_str
;
206 UName
->Buffer
= buff
;
208 // Loop through all the bytes.
209 while (byteIndex
< Length
) {
210 // Move the first byte to the high bits of the unicode char.
211 *buff
= ((*_CS0
) << 8) | (*(_CS0
+1));
216 ASSERT(byteIndex
<= Length
);
222 UName
->Buffer
= NULL
;
223 UName
->MaximumLength
=
228 UName
->MaximumLength
= (UName
->Length
= (((uint16
)unicodeIndex
)*sizeof(WCHAR
))) + sizeof(WCHAR
);
229 UName
->Buffer
[unicodeIndex
] = 0;
231 *valueCRC
= UDFCrc(CS0
+1, Length
-1);
233 } // end UDFDecompressUnicode()
236 This routine converts standard Unicode to compressed
241 IN PUNICODE_STRING UName
,
243 IN OUT uint32
* Length
252 len
= (UName
->Length
) / sizeof(WCHAR
);
253 compID
= (!len
) ? 0 : UDF_COMP_ID_8
;
254 // check for uncompressable characters
255 Buff
= UName
->Buffer
;
256 for(i
=0; i
<len
; i
++, Buff
++) {
257 if((*Buff
) & 0xff00) {
258 compID
= UDF_COMP_ID_16
;
263 CS0
= (uint8
*)MyAllocatePool__(NonPagedPool
, *Length
= (((compID
==UDF_COMP_ID_8
) ? 1 : 2)*len
+ 1) );
271 Buff
= UName
->Buffer
;
272 if(compID
== UDF_COMP_ID_16
) {
273 // Loop through all the bytes.
274 while (unicodeIndex
< len
) {
275 // Move the 2nd byte to the low bits of the compressed unicode char.
276 *CS0
= (uint8
)((*Buff
) >> 8);
278 *CS0
= (uint8
)(*Buff
);
284 // Loop through all the bytes.
285 while (unicodeIndex
< len
) {
286 *CS0
= (uint8
)(*Buff
);
292 } // end UDFCompressUnicode()
295 OSSTATUS UDFFindFile__(IN PVCB Vcb,
296 IN BOOLEAN IgnoreCase,
297 IN PUNICODE_STRING Name,
298 IN PUDF_FILE_INFO DirInfo)
303 This routine reads (Extended)FileEntry according to FileDesc
309 IN OUT PFILE_ENTRY FileEntry
, // here we can also get ExtendedFileEntry
315 if(!OS_SUCCESS(status
= UDFReadTagged(Vcb
, (int8
*)FileEntry
,
316 UDFPartLbaToPhys(Vcb
,&(Icb
->extLocation
)),
317 Icb
->extLocation
.logicalBlockNum
,
318 Ident
))) return status
;
319 if((FileEntry
->descTag
.tagIdent
!= TID_FILE_ENTRY
) &&
320 (FileEntry
->descTag
.tagIdent
!= TID_EXTENDED_FILE_ENTRY
)) {
321 KdPrint((" Not a FileEntry (lbn=%x, tag=%x)\n", Icb
->extLocation
.logicalBlockNum
, FileEntry
->descTag
.tagIdent
));
322 return STATUS_FILE_CORRUPT_ERROR
;
324 return STATUS_SUCCESS
;
325 } // UDFReadFileEntry()
327 #if !defined (_X86_) || !defined (_MSC_VER)
329 Decides if a Unicode character matches one of a list
331 Used by DOS version of UDFIsIllegalChar for readability, since all of the
332 illegal characters above 0x0020 are in the ASCII subset of Unicode.
333 Works very similarly to the standard C function strchr().
337 IN uint8
* string
, // String to search through.
338 IN WCHAR ch
// Unicode char to search for.
341 BOOLEAN found
= FALSE
;
343 while(*string
!= '\0' && !found
) {
344 // These types should compare, since both are unsigned numbers.
351 } // end UDFUnicodeInString()
355 Decides whether character passed is an illegal character for a
359 #pragma warning(push)
360 #pragma warning(disable:4035) // re-enable below
374 // Genuine illegal char's for DOS.
375 #if defined (_X86_) && defined (_MSC_VER)
385 lea ebx
,[valid_char_arr
]
396 #else // NO X86 optimization , use generic C/C++
398 //return ((ch < 0x20) || UDFUnicodeInString((uint8*)&valid_char_arr, ch));
399 return ((chr
< 0x20) || UDFUnicodeInString((uint8
*)&valid_char_arr
, chr
));
401 } // end UDFIsIllegalChar()
404 #pragma warning(pop) // re-enable warning #4035
408 Translate udfName to dosName using OSTA compliant.
409 dosName must be a unicode string with min length of 12.
414 IN OUT PUNICODE_STRING DosName,
415 IN PUNICODE_STRING UdfName,
416 IN PUDF_FILE_INFO FileInfo
421 KeepIntact = (FileInfo && (FileInfo->Index < 2));
422 UDFDOSName(Vcb, DosName, UdfName, KeepIntact);
429 IN OUT PUNICODE_STRING DosName
,
430 IN PUNICODE_STRING UdfName
,
431 IN BOOLEAN KeepIntact
435 if(Vcb
->CompatFlags
& UDF_VCB_IC_OS_NATIVE_DOS_NAME
) {
436 UDFDOSNameOsNative(DosName
, UdfName
, KeepIntact
);
441 switch(Vcb
->CurrentUDFRev
) {
445 UDFDOSName100(DosName
, UdfName
, KeepIntact
);
449 // in general, we need bytes-from-media to
450 // create valid UDF 1.50 name.
451 // Curently it is impossible, thus, we'll use
452 // UDF 2.00 translation algorithm
454 UDFDOSName200(DosName
, UdfName
, KeepIntact
, Vcb
->CurrentUDFRev
== 0x0150);
459 UDFDOSName201(DosName
, UdfName
, KeepIntact
);
466 IN OUT PUNICODE_STRING DosName
,
467 IN PUNICODE_STRING UdfName
,
468 IN BOOLEAN KeepIntact
471 PWCHAR dosName
= DosName
->Buffer
;
472 PWCHAR udfName
= UdfName
->Buffer
;
473 uint32 udfLen
= UdfName
->Length
/ sizeof(WCHAR
);
475 uint32 index
, dosIndex
= 0, extIndex
= 0, lastPeriodIndex
;
476 BOOLEAN needsCRC
= FALSE
, hasExt
= FALSE
, writingExt
= FALSE
, isParent
= FALSE
;
478 WCHAR ext
[DOS_EXT_LEN
], current
;
481 (udfLen
<= 2) && (udfName
[0] == UNICODE_PERIOD
)) {
483 if((udfLen
== 2) && (udfName
[1] != UNICODE_PERIOD
))
487 for (index
= 0 ; index
< udfLen
; index
++) {
488 current
= udfName
[index
];
489 if (current
== UNICODE_PERIOD
&& !isParent
) {
490 if (dosIndex
==0 || hasExt
) {
491 // Ignore leading periods or any other than used for extension.
494 // First, find last character which is NOT a period or space.
495 lastPeriodIndex
= udfLen
- 1;
496 while(lastPeriodIndex
>=0 &&
497 (udfName
[lastPeriodIndex
] == UNICODE_PERIOD
||
498 udfName
[lastPeriodIndex
] == UNICODE_SPACE
))
500 // Now search for last remaining period.
501 while(lastPeriodIndex
>= 0 &&
502 udfName
[lastPeriodIndex
] != UNICODE_PERIOD
)
504 // See if the period we found was the last or not.
505 if (lastPeriodIndex
!= index
)
506 needsCRC
= TRUE
; // If not, name needs translation.
507 // As long as the period was not trailing,
508 // the file name has an extension.
509 if (lastPeriodIndex
>= 0) hasExt
= TRUE
;
512 if ((!hasExt
&& dosIndex
== DOS_NAME_LEN
) ||
513 extIndex
== DOS_EXT_LEN
) {
514 // File name or extension is too long for DOS.
517 if (current
== UNICODE_SPACE
) { // Ignore spaces.
520 // Look for illegal or unprintable characters.
521 if (UDFIsIllegalChar(current
) /*|| !UnicodeIsPrint(current)*/) {
523 current
= ILLEGAL_CHAR_MARK
;
524 /* Skip Illegal characters(even spaces),
527 while(index
+1 < udfLen
&&
528 (UDFIsIllegalChar(udfName
[index
+1]) /*||
529 !UnicodeIsPrint(udfName[index+1])*/) &&
530 udfName
[index
+1] != UNICODE_PERIOD
)
533 // Add current char to either file name or ext.
535 ext
[extIndex
] = current
;
538 dosName
[dosIndex
] = current
;
544 // See if we are done with file name, either because we reached
545 // the end of the file name length, or the final period.
546 if (!writingExt
&& hasExt
&& (dosIndex
== DOS_NAME_LEN
||
547 index
== lastPeriodIndex
)) {
548 // If so, and the name has an extension, start reading it.
550 // Extension starts after last period.
551 index
= lastPeriodIndex
;
556 // Add CRC to end of file name or at position 4.
557 if (dosIndex
>4) dosIndex
= 4;
558 valueCRC
= UDFUnicodeCksum(udfName
, udfLen
);
560 dosName
[dosIndex
] = UNICODE_CRC_MARK
;
561 // Convert 12-bit CRC to hex characters.
562 dosName
[dosIndex
+1] = hexChar
[(valueCRC
& 0x0f00) >> 8];
563 dosName
[dosIndex
+2] = hexChar
[(valueCRC
& 0x00f0) >> 4];
564 dosName
[dosIndex
+3] = hexChar
[(valueCRC
& 0x000f)];
567 // Add extension, if any.
569 dosName
[dosIndex
] = UNICODE_PERIOD
;
571 for (index
= 0; index
< extIndex
; index
++) {
572 dosName
[dosIndex
] = ext
[index
];
576 DosName
->Length
= (uint16
)dosIndex
*sizeof(WCHAR
);
577 RtlUpcaseUnicodeString(DosName
, DosName
, FALSE
);
578 } // end UDFDOSName100()
583 IN OUT PUNICODE_STRING DosName
,
584 IN PUNICODE_STRING UdfName
,
585 IN BOOLEAN KeepIntact
,
589 PWCHAR dosName
= DosName
->Buffer
;
590 PWCHAR udfName
= UdfName
->Buffer
;
591 uint32 udfLen
= UdfName
->Length
/ sizeof(WCHAR
);
593 uint32 index
, dosIndex
= 0, extIndex
= 0, lastPeriodIndex
;
594 BOOLEAN needsCRC
= FALSE
, hasExt
= FALSE
, writingExt
= FALSE
, isParent
= FALSE
;
596 WCHAR ext
[DOS_EXT_LEN
], current
;
599 (udfLen
<= 2) && (udfName
[0] == UNICODE_PERIOD
)) {
601 if((udfLen
== 2) && (udfName
[1] != UNICODE_PERIOD
))
605 for (index
= 0 ; index
< udfLen
; index
++) {
606 current
= udfName
[index
];
607 if (current
== UNICODE_PERIOD
&& !isParent
) {
608 if (dosIndex
==0 || hasExt
) {
609 // Ignore leading periods or any other than used for extension.
612 // First, find last character which is NOT a period or space.
613 lastPeriodIndex
= udfLen
- 1;
614 while(lastPeriodIndex
>=0 &&
615 (udfName
[lastPeriodIndex
] == UNICODE_PERIOD
||
616 udfName
[lastPeriodIndex
] == UNICODE_SPACE
))
618 // Now search for last remaining period.
619 while(lastPeriodIndex
>= 0 &&
620 udfName
[lastPeriodIndex
] != UNICODE_PERIOD
)
622 // See if the period we found was the last or not.
623 if (lastPeriodIndex
!= index
)
624 needsCRC
= TRUE
; // If not, name needs translation.
625 // As long as the period was not trailing,
626 // the file name has an extension.
627 if (lastPeriodIndex
>= 0) hasExt
= TRUE
;
630 if ((!hasExt
&& dosIndex
== DOS_NAME_LEN
) ||
631 extIndex
== DOS_EXT_LEN
) {
632 // File name or extension is too long for DOS.
635 if (current
== UNICODE_SPACE
) { // Ignore spaces.
638 // Look for illegal or unprintable characters.
639 if (UDFIsIllegalChar(current
) /*|| !UnicodeIsPrint(current)*/) {
641 current
= ILLEGAL_CHAR_MARK
;
642 /* Skip Illegal characters(even spaces),
645 while(index
+1 < udfLen
&&
646 (UDFIsIllegalChar(udfName
[index
+1]) /*||
647 !UnicodeIsPrint(udfName[index+1])*/) &&
648 udfName
[index
+1] != UNICODE_PERIOD
)
651 // Add current char to either file name or ext.
653 ext
[extIndex
] = current
;
656 dosName
[dosIndex
] = current
;
662 // See if we are done with file name, either because we reached
663 // the end of the file name length, or the final period.
664 if (!writingExt
&& hasExt
&& (dosIndex
== DOS_NAME_LEN
||
665 index
== lastPeriodIndex
)) {
666 // If so, and the name has an extension, start reading it.
668 // Extension starts after last period.
669 index
= lastPeriodIndex
;
672 // Now handle CRC if needed.
674 // Add CRC to end of file name or at position 4.
675 if (dosIndex
>4) dosIndex
= 4;
676 valueCRC
= Mode150
? UDFUnicodeCksum150(udfName
, udfLen
) : UDFUnicodeCksum(udfName
, udfLen
);
677 // Convert 16-bit CRC to hex characters.
678 dosName
[dosIndex
] = hexChar
[(valueCRC
& 0xf000) >> 12];
679 dosName
[dosIndex
+1] = hexChar
[(valueCRC
& 0x0f00) >> 8];
680 dosName
[dosIndex
+2] = hexChar
[(valueCRC
& 0x00f0) >> 4];
681 dosName
[dosIndex
+3] = hexChar
[(valueCRC
& 0x000f)];
684 // Add extension, if any.
686 dosName
[dosIndex
] = UNICODE_PERIOD
;
688 for (index
= 0; index
< extIndex
; index
++) {
689 dosName
[dosIndex
] = ext
[index
];
693 DosName
->Length
= (uint16
)dosIndex
*sizeof(WCHAR
);
694 RtlUpcaseUnicodeString(DosName
, DosName
, FALSE
);
695 } // end UDFDOSName200()
701 IN OUT PUNICODE_STRING DosName
,
702 IN PUNICODE_STRING UdfName
,
703 IN BOOLEAN KeepIntact
706 PWCHAR dosName
= DosName
->Buffer
;
707 PWCHAR udfName
= UdfName
->Buffer
;
708 uint16 udfLen
= UdfName
->Length
/ sizeof(WCHAR
);
710 uint16 index
, dosIndex
= 0;
711 //uint16 extIndex = 0;
712 BOOLEAN needsCRC
= FALSE
, isParent
= FALSE
;
713 //BOOLEAN hasExt = FALSE, writingExt = FALSE;
715 WCHAR ext
[DOS_EXT_LEN
];
719 (udfLen
<= 2) && (udfName
[0] == UNICODE_PERIOD
)) {
721 if((udfLen
== 2) && (udfName
[1] != UNICODE_PERIOD
))
725 #define DOS_CRC_LEN 4
726 #define DOS_CRC_MODULUS 41
735 /* Start at the end of the UDF file name and scan for a period */
736 /* ('.'). This will be where the DOS extension starts (if */
739 while (index
-- > 0) {
740 if (udfName
[index
] == '.')
743 if ((index
< 0) || isParent
) {
744 /* There name was scanned to the beginning of the buffer */
745 /* and no extension was found. */
749 /* A DOS extension was found, process it first. */
750 extLen
= udfLen
- index
- 1;
753 bytesLeft
= DOS_EXT_LEN
;
754 while (++index
< udfLen
&& bytesLeft
> 0) {
755 /* Get the current character and convert it to upper */
757 current
= udfName
[index
];
758 if (current
== ' ') {
759 /* If a space is found, a CRC must be appended to */
760 /* the mangled file name. */
763 /* Determine if this is a valid file name char and */
764 /* calculate its corresponding BCS character byte */
765 /* length (zero if the char is not legal or */
766 /* undisplayable on this system). */
768 charLen
= (UDFIsIllegalChar(current
)
769 /*|| !UnicodeIsPrint(current)*/) ? 0 : 1;
771 /* If the char is larger than the available space */
772 /* in the buffer, pretend it is undisplayable. */
773 if (charLen
> bytesLeft
)
776 /* Undisplayable or illegal characters are */
777 /* substituted with an underscore ("_"), and */
778 /* required a CRC code appended to the mangled */
783 /* Skip over any following undiplayable or */
785 while (index
+1 <udfLen
&&
786 (UDFIsIllegalChar(udfName
[index
+1])
787 /*|| !UnicodeIsPrint(udfName[index+1])*/))
790 /* Assign the resulting char to the next index in */
791 /* the extension buffer and determine how many BCS */
792 /* bytes are left. */
793 ext
[dosIndex
++] = current
;
794 bytesLeft
-= charLen
;
797 /* Save the number of Unicode characters in the extension */
799 /* If the extension was too large, or it was zero length */
800 /* (i.e. the name ended in a period), a CRC code must be */
801 /* appended to the mangled name. */
802 if (index
< udfLen
|| extLen
== 0)
805 /* Now process the actual file name. */
810 bytesLeft
= DOS_NAME_LEN
;
811 while (index
< nameLen
&& bytesLeft
> 0) {
812 /* Get the current character and convert it to upper case. */
813 current
= udfName
[index
];
814 if (current
==' ' || (current
== '.' && !isParent
) ) {
815 /* Spaces and periods are just skipped, a CRC code */
816 /* must be added to the mangled file name. */
819 /* Determine if this is a valid file name char and */
820 /* calculate its corresponding BCS character byte */
821 /* length (zero if the char is not legal or */
822 /* undisplayable on this system). */
824 charLen
= (UDFIsIllegalChar(current
)
825 /*|| !UnicodeIsPrint(current)*/) ? 0 : 1;
827 /* If the char is larger than the available space in */
828 /* the buffer, pretend it is undisplayable. */
829 if (charLen
> bytesLeft
)
833 /* Undisplayable or illegal characters are */
834 /* substituted with an underscore ("_"), and */
835 /* required a CRC code appended to the mangled */
840 /* Skip over any following undisplayable or illegal */
842 while (index
+1 <nameLen
&&
843 (UDFIsIllegalChar(udfName
[index
+1])
844 /*|| !UnicodeIsPrint(udfName[index+1])*/))
846 /* Terminate loop if at the end of the file name. */
847 if (index
>= nameLen
)
850 /* Assign the resulting char to the next index in the */
851 /* file name buffer and determine how many BCS bytes */
853 dosName
[dosIndex
++] = current
;
854 bytesLeft
-= charLen
;
855 /* This figures out where the CRC code needs to start */
856 /* in the file name buffer. */
857 if (bytesLeft
>= DOS_CRC_LEN
) {
858 /* If there is enough space left, just tack it */
862 /* If there is not enough space left, the CRC */
863 /* must overlay a character already in the file */
864 /* name buffer. Once this condition has been */
865 /* met, the value will not change. */
866 if (overlayBytes
< 0) {
867 /* Determine the index and save the length of */
868 /* the BCS character that is overlayed. It */
869 /* is possible that the CRC might overlay */
870 /* half of a two-byte BCS character depending */
871 /* upon how the character boundaries line up. */
872 overlayBytes
= (bytesLeft
+ charLen
> DOS_CRC_LEN
)?1 :0;
873 crcIndex
= dosIndex
- 1;
877 /* Advance to the next character. */
880 /* If the scan did not reach the end of the file name, or the */
881 /* length of the file name is zero, a CRC code is needed. */
882 if (index
< nameLen
|| index
== 0)
885 /* If the name has illegal characters or and extension, it */
886 /* is not a DOS device name. */
888 /* if (needsCRC == FALSE && extLen == 0) { */
889 /* If this is the name of a DOS device, a CRC code should */
890 /* be appended to the file name.
891 if (IsDeviceName(udfName, udfLen))
895 /* Append the CRC code to the file name, if needed. */
897 /* Get the CRC value for the original Unicode string */
898 valueCRC
= UDFUnicodeCksum(udfName
, udfLen
);
902 /* If the character being overlayed is a two-byte BCS */
903 /* character, replace the first byte with an underscore. */
904 if (overlayBytes
> 0)
905 dosName
[dosIndex
++] = '_';
906 /* Append the encoded CRC value with delimiter. */
907 dosName
[dosIndex
++] = '#';
908 dosName
[dosIndex
++] =
909 crcChar
[valueCRC
/ (DOS_CRC_MODULUS
* DOS_CRC_MODULUS
)];
910 valueCRC
%= DOS_CRC_MODULUS
* DOS_CRC_MODULUS
;
911 dosName
[dosIndex
++] =
912 crcChar
[valueCRC
/ DOS_CRC_MODULUS
];
913 valueCRC
%= DOS_CRC_MODULUS
;
914 dosName
[dosIndex
++] = crcChar
[valueCRC
];
916 /* Append the extension, if any. */
918 /* Tack on a period and each successive byte in the */
919 /* extension buffer. */
920 dosName
[dosIndex
++] = '.';
921 for (index
= 0; index
< extLen
; index
++)
922 dosName
[dosIndex
++] = ext
[index
];
924 /* Return the length of the resulting Unicode string. */
925 DosName
->Length
= (uint16
)dosIndex
*sizeof(WCHAR
);
926 RtlUpcaseUnicodeString(DosName
, DosName
, FALSE
);
928 } // end UDFDOSName201()
930 #ifndef UDF_READ_ONLY_BUILD
932 This routine initializes Tag structure. It must be called after all
933 manual settings to generate valid CRC & Checksum
939 IN uint16 DataLen
, // total length of descriptor _including_ icbTag
946 AdPrint(("UDF: SetTag Loc=%x(%x), tagIdent=%x\n", TagLoc
, Tag
->tagLocation
, Tag
->tagIdent
));
948 if(DataLen
) DataLen
-= sizeof(tag
);
949 // int8* Data = ((int8*)Tag) + sizeof(tag);
950 // Ecma-167 states, that all implementations
951 // shall set this field to '3' even if
952 // disc contains descriptors recorded with
954 // But we should ignore this to make happy othe UDF implementations :(
955 Tag
->descVersion
= (Vcb
->NSRDesc
& VRS_NSR03_FOUND
) ? 3 : 2;
956 Tag
->tagLocation
= TagLoc
;
957 Tag
->tagSerialNum
= (uint16
)(Vcb
->SerialNumber
+ 1);
958 Tag
->descCRCLength
= DataLen
;
959 Tag
->descCRC
= UDFCrc((uint8
*)(Tag
+1), DataLen
);
960 Tag
->tagChecksum
= 0;
962 for (i
=0; i
<sizeof(tag
); i
++,tb
++)
963 Tag
->tagChecksum
+= (i
!=4) ? (*tb
) : 0;
964 } // end UDFSetUpTag()
967 This routine builds FileEntry & associated AllocDescs for specified
973 IN PUDF_FILE_INFO DirInfo
,
974 IN PUDF_FILE_INFO FileInfo
,
976 IN uint16 AllocMode
, // short/long/ext/in-icb
981 PFILE_ENTRY FileEntry
;
985 EXTENT_INFO _FEExtInfo
;
990 // calculate the length required
991 l
= (Extended
? sizeof(EXTENDED_FILE_ENTRY
) : sizeof(FILE_ENTRY
)) + ExtAttrSz
;
992 if(l
> Vcb
->LBlockSize
) return STATUS_INVALID_PARAMETER
;
993 // allocate block for FE
994 if(!OS_SUCCESS(status
= UDFAllocateFESpace(Vcb
, DirInfo
, PartNum
, &_FEExtInfo
, l
) ))
996 // remember FE location for future hard link creation
997 ASSERT(UDFFindDloc(Vcb
, _FEExtInfo
.Mapping
[0].extLocation
) == (-1));
998 if(!OS_SUCCESS(status
= UDFStoreDloc(Vcb
, FileInfo
, _FEExtInfo
.Mapping
[0].extLocation
))) {
999 ASSERT(status
!= STATUS_SHARING_PAUSED
);
1000 UDFFreeFESpace(Vcb
, DirInfo
, &_FEExtInfo
); // free
1001 MyFreePool__(_FEExtInfo
.Mapping
);
1004 FileEntry
= (PFILE_ENTRY
)MyAllocatePoolTag__(NonPagedPool
, l
, MEM_FE_TAG
);
1006 UDFRemoveDloc(Vcb
, FileInfo
->Dloc
);
1007 FileInfo
->Dloc
= NULL
;
1008 UDFFreeFESpace(Vcb
, DirInfo
, &_FEExtInfo
); // free
1009 MyFreePool__(_FEExtInfo
.Mapping
);
1010 return STATUS_INSUFFICIENT_RESOURCES
;
1012 FileInfo
->Dloc
->FELoc
= _FEExtInfo
;
1014 RtlZeroMemory((int8
*)FileEntry
, l
);
1015 // set up in-memory FE structure
1016 FileEntry
->icbTag
.flags
= AllocMode
;
1017 FileEntry
->icbTag
.fileType
= UDF_FILE_TYPE_REGULAR
;
1018 FileEntry
->icbTag
.numEntries
= 1;
1019 // if(DirInfo && DirInfo->Dloc && DirInfo->Dloc
1020 FileEntry
->icbTag
.strategyType
= 4;
1021 // FileEntry->icbTag.strategyParameter = 0;
1022 FileEntry
->descTag
.tagIdent
= Extended
? TID_EXTENDED_FILE_ENTRY
: TID_FILE_ENTRY
;
1023 FileEntry
->descTag
.tagLocation
= UDFPhysLbaToPart(Vcb
, PartNum
, _FEExtInfo
.Mapping
[0].extLocation
);
1024 FileEntry
->uid
= Vcb
->DefaultUID
;
1025 FileEntry
->gid
= Vcb
->DefaultGID
;
1028 // eID = &(((PEXTENDED_FILE_ENTRY)FileEntry)->impIdent);
1029 lcp
= &(((PEXTENDED_FILE_ENTRY
)FileEntry
)->fileLinkCount
);
1030 ((PEXTENDED_FILE_ENTRY
)FileEntry
)->checkpoint
= 1;
1032 // eID = &(FileEntry->impIdent);
1033 lcp
= &(FileEntry
->fileLinkCount
);
1034 ((PFILE_ENTRY
)FileEntry
)->checkpoint
= 1;
1038 UDFSetEntityID_imp(eID
, UDF_ID_DEVELOPER
);
1041 /*RtlCopyMemory((int8*)&(eID->ident), UDF_ID_DEVELOPER, sizeof(UDF_ID_DEVELOPER) );
1042 iis = (impIdentSuffix*)&(eID->identSuffix);
1043 iis->OSClass = UDF_OS_CLASS_WINNT;
1044 iis->OSIdent = UDF_OS_ID_WINNT;*/
1048 FileInfo
->Dloc
->FileEntry
= (tag
*)FileEntry
;
1049 FileInfo
->Dloc
->FileEntryLen
= l
;
1051 FileInfo
->Dloc
->FE_Flags
|= UDF_FE_FLAG_FE_MODIFIED
;
1053 return STATUS_SUCCESS
;
1054 } // end UDFBuildFileEntry()
1055 #endif //UDF_READ_ONLY_BUILD
1058 This routine builds ExtentInfo for specified (Ex)FileEntry & associated
1066 IN OUT PEXTENT_INFO FExtInfo
, // user data
1067 IN OUT PEXTENT_INFO AExtInfo
// alloc descs
1072 KdPrint((" UDFLoadExtInfo:\n"));
1073 FExtInfo
->Mapping
= UDFReadMappingFromXEntry(Vcb
, fe_loc
->extLocation
.partitionReferenceNum
,
1074 (tag
*)fe
, &(FExtInfo
->Offset
), AExtInfo
);
1075 if(!(FExtInfo
->Mapping
)) {
1076 if(!(FExtInfo
->Offset
))
1077 return STATUS_UNSUCCESSFUL
;
1078 TmpExt
.extLength
= fe_loc
->extLength
;
1079 TmpExt
.extLocation
= UDFPartLbaToPhys(Vcb
, &(fe_loc
->extLocation
));
1080 if(TmpExt
.extLocation
== LBA_OUT_OF_EXTENT
)
1081 return STATUS_FILE_CORRUPT_ERROR
;
1082 FExtInfo
->Mapping
= UDFExtentToMapping(&TmpExt
);
1084 if(fe
->descTag
.tagIdent
== TID_FILE_ENTRY
) {
1085 // KdPrint(("Standard FileEntry\n"));
1086 FExtInfo
->Length
= fe
->informationLength
;
1087 } else /*if(fe->descTag.tagIdent == TID_EXTENDED_FILE_ENTRY) */ {
1088 FExtInfo
->Length
= ((PEXTENDED_FILE_ENTRY
)fe
)->informationLength
;
1090 KdPrint((" FExtInfo->Length %x\n", FExtInfo
->Length
));
1091 ASSERT(FExtInfo
->Length
<= UDFGetExtentLength(FExtInfo
->Mapping
));
1092 FExtInfo
->Modified
= FALSE
;
1094 return STATUS_SUCCESS
;
1095 } // end UDFLoadExtInfo()
1098 This routine builds FileIdent for specified FileEntry.
1099 We shall call UDFSetUpTag after all other initializations
1100 This structure is a precise copy of on-disk FileIdent
1101 structure. All modifications of it (including memory block
1102 size) are reflected on Directory extent. This, allocation of
1103 too long block (without changes in ImpUseLen) will lead to
1104 unreadable Directory
1109 IN PUNICODE_STRING fn
,
1110 IN PLONG_AD FileEntryIcb
, // virtual address of FileEntry
1111 IN uint32 ImpUseLen
,
1112 OUT PFILE_IDENT_DESC
* _FileId
,
1113 OUT uint32
* FileIdLen
1116 PFILE_IDENT_DESC FileId
;
1120 UDFCompressUnicode(fn
, &CS0
, &Nlen
);
1121 if(!CS0
) return STATUS_INSUFFICIENT_RESOURCES
;
1125 if(Nlen
> UDF_NAME_LEN
) {
1126 if(CS0
) MyFreePool__(CS0
);
1127 return STATUS_OBJECT_NAME_INVALID
;
1129 // allocate memory for FI
1130 l
= (sizeof(FILE_IDENT_DESC
) + Nlen
+ ImpUseLen
+ 3) & ~((uint32
)3);
1131 FileId
= (PFILE_IDENT_DESC
)MyAllocatePoolTag__(NonPagedPool
, l
, MEM_FID_TAG
);
1133 if(CS0
) MyFreePool__(CS0
);
1134 return STATUS_INSUFFICIENT_RESOURCES
;
1136 // fill FI structure
1137 RtlZeroMemory( (int8
*)FileId
, l
);
1138 RtlCopyMemory( ((int8
*)(FileId
+1))+ImpUseLen
, CS0
, Nlen
);
1139 FileId
->descTag
.tagIdent
= TID_FILE_IDENT_DESC
;
1140 FileId
->fileVersionNum
= 1;
1141 FileId
->lengthOfImpUse
= (uint16
)ImpUseLen
;
1142 FileId
->lengthFileIdent
= (uint8
)Nlen
;
1143 FileId
->icb
= *FileEntryIcb
;
1147 if(CS0
) MyFreePool__(CS0
);
1148 return STATUS_SUCCESS
;
1149 } // end UDFBuildFileIdent()
1151 #ifndef UDF_READ_ONLY_BUILD
1153 This routine sets informationLength field in (Ext)FileEntry
1157 IN PUDF_FILE_INFO FileInfo
,
1162 // PDIR_INDEX_ITEM DirIndex;
1164 ValidateFileInfo(FileInfo
);
1165 AdPrint(("UDFSetFileSize: %I64x, FI %x\n", Size
, FileInfo
));
1167 //AdPrint((" Dloc %x\n", FileInfo->Dloc));
1168 FileInfo
->Dloc
->FE_Flags
|= UDF_FE_FLAG_FE_MODIFIED
;
1169 //AdPrint((" FileEntry %x\n", FileInfo->Dloc->FileEntry));
1170 Ident
= FileInfo
->Dloc
->FileEntry
->tagIdent
;
1171 //AdPrint((" Ident %x\n", Ident));
1172 if(Ident
== TID_FILE_ENTRY
) {
1173 PFILE_ENTRY fe
= (PFILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
);
1174 //AdPrint((" fe %x\n", fe));
1175 fe
->informationLength
= Size
;
1176 } else if(Ident
== TID_EXTENDED_FILE_ENTRY
) {
1177 PEXTENDED_FILE_ENTRY fe
= (PEXTENDED_FILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
);
1178 //AdPrint((" ext-fe %x\n", fe));
1179 fe
->informationLength
= Size
;
1181 /* if(DirIndex = UDFDirIndex(UDFGetDirIndexByFileInfo(FileInfo),FileInfo->Index) ) {
1182 DirIndex->FileSize = Size;
1184 //AdPrint(("UDFSetFileSize: ok\n"));
1186 } // end UDFSetFileSize()
1189 UDFSetFileSizeInDirNdx(
1191 IN PUDF_FILE_INFO FileInfo
,
1196 PDIR_INDEX_ITEM DirIndex
;
1198 ValidateFileInfo(FileInfo
);
1200 AdPrint(("UDFSetFileSizeInDirNdx: %I64x\n", *ASize
));
1202 AdPrint(("UDFSetFileSizeInDirNdx: sync\n"));
1205 DirIndex
= UDFDirIndex(UDFGetDirIndexByFileInfo(FileInfo
),FileInfo
->Index
);
1209 Ident
= FileInfo
->Dloc
->FileEntry
->tagIdent
;
1210 if(Ident
== TID_FILE_ENTRY
) {
1211 PFILE_ENTRY fe
= (PFILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
);
1212 DirIndex
->FileSize
= fe
->informationLength
;
1214 DirIndex
->AllocationSize
= *ASize
;
1216 // DirIndex->AllocationSize = (fe->informationLength + Vcb->LBlockSize - 1) & ~(Vcb->LBlockSize - 1);
1218 } else if(Ident
== TID_EXTENDED_FILE_ENTRY
) {
1219 PEXTENDED_FILE_ENTRY fe
= (PEXTENDED_FILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
);
1220 DirIndex
->FileSize
= fe
->informationLength
;
1222 DirIndex
->AllocationSize
= *ASize
;
1224 // DirIndex->AllocationSize = (fe->informationLength + Vcb->LBlockSize - 1) & ~(Vcb->LBlockSize - 1);
1228 } // end UDFSetFileSizeInDirNdx()
1229 #endif //UDF_READ_ONLY_BUILD
1232 This routine gets informationLength field in (Ext)FileEntry
1236 IN PUDF_FILE_INFO FileInfo
1241 ValidateFileInfo(FileInfo
);
1243 Ident
= FileInfo
->Dloc
->FileEntry
->tagIdent
;
1244 if(Ident
== TID_FILE_ENTRY
) {
1245 PFILE_ENTRY fe
= (PFILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
);
1246 return fe
->informationLength
;
1247 } else if(Ident
== TID_EXTENDED_FILE_ENTRY
) {
1248 PEXTENDED_FILE_ENTRY fe
= (PEXTENDED_FILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
);
1249 return fe
->informationLength
;
1252 } // end UDFGetFileSize()
1255 UDFGetFileSizeFromDirNdx(
1257 IN PUDF_FILE_INFO FileInfo
1260 PDIR_INDEX_ITEM DirIndex
;
1262 ValidateFileInfo(FileInfo
);
1264 DirIndex
= UDFDirIndex(UDFGetDirIndexByFileInfo(FileInfo
),FileInfo
->Index
);
1268 return DirIndex
->FileSize
;
1269 } // end UDFGetFileSizeFromDirNdx()
1271 #ifndef UDF_READ_ONLY_BUILD
1273 This routine sets lengthAllocDesc field in (Ext)FileEntry
1278 IN PUDF_FILE_INFO FileInfo
1283 ValidateFileInfo(FileInfo
);
1285 FileInfo
->Dloc
->FE_Flags
|= UDF_FE_FLAG_FE_MODIFIED
;
1286 Ident
= FileInfo
->Dloc
->FileEntry
->tagIdent
;
1287 if(Ident
== TID_FILE_ENTRY
) {
1288 PFILE_ENTRY fe
= (PFILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
);
1289 if(FileInfo
->Dloc
->AllocLoc
.Length
) {
1290 fe
->lengthAllocDescs
= min(FileInfo
->Dloc
->AllocLoc
.Mapping
[0].extLength
-
1291 FileInfo
->Dloc
->AllocLoc
.Offset
,
1292 (uint32
)(FileInfo
->Dloc
->AllocLoc
.Length
));
1294 if(Vcb
->CompatFlags
& UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS
) {
1295 fe
->lengthAllocDescs
= (uint32
)(FileInfo
->Dloc
->DataLoc
.Length
);
1297 } else if(Ident
== TID_EXTENDED_FILE_ENTRY
) {
1298 PEXTENDED_FILE_ENTRY fe
= (PEXTENDED_FILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
);
1299 if(FileInfo
->Dloc
->AllocLoc
.Length
) {
1300 fe
->lengthAllocDescs
= min(FileInfo
->Dloc
->AllocLoc
.Mapping
[0].extLength
-
1301 FileInfo
->Dloc
->AllocLoc
.Offset
,
1302 (uint32
)(FileInfo
->Dloc
->AllocLoc
.Length
));
1304 if(Vcb
->CompatFlags
& UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS
) {
1305 fe
->lengthAllocDescs
= (uint32
)(FileInfo
->Dloc
->DataLoc
.Length
);
1308 } // end UDFSetAllocDescLen()
1311 This routine changes fileLinkCount field in (Ext)FileEntry
1314 UDFChangeFileLinkCount(
1315 IN PUDF_FILE_INFO FileInfo
,
1321 ValidateFileInfo(FileInfo
);
1323 FileInfo
->Dloc
->FE_Flags
|= UDF_FE_FLAG_FE_MODIFIED
;
1324 Ident
= FileInfo
->Dloc
->FileEntry
->tagIdent
;
1325 if(Ident
== TID_FILE_ENTRY
) {
1326 PFILE_ENTRY fe
= (PFILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
);
1328 fe
->fileLinkCount
++;
1330 fe
->fileLinkCount
--;
1332 if(fe
->fileLinkCount
& 0x8000)
1333 fe
->fileLinkCount
= 0xffff;
1335 } else if(Ident
== TID_EXTENDED_FILE_ENTRY
) {
1336 PEXTENDED_FILE_ENTRY fe
= (PEXTENDED_FILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
);
1338 fe
->fileLinkCount
++;
1340 fe
->fileLinkCount
--;
1342 if(fe
->fileLinkCount
& 0x8000)
1343 fe
->fileLinkCount
= 0xffff;
1347 } // end UDFChangeFileLinkCount()
1348 #endif //UDF_READ_ONLY_BUILD
1351 This routine gets fileLinkCount field from (Ext)FileEntry
1354 UDFGetFileLinkCount(
1355 IN PUDF_FILE_INFO FileInfo
1361 ValidateFileInfo(FileInfo
);
1363 if(!FileInfo
->Dloc
->FileEntry
)
1365 Ident
= FileInfo
->Dloc
->FileEntry
->tagIdent
;
1366 // UDF engine assumes that LinkCount is a counter
1367 // of FileIdents, referencing this FE.
1368 // UDF 2.0 states, that it should be counter of ALL
1369 // references (including SDir) - 1.
1370 // Thus we'll write to media UDF-required value, but return
1371 // cooked value to callers
1372 d
= UDFHasAStreamDir(FileInfo
) ? 0 : 1;
1373 if(Ident
== TID_FILE_ENTRY
) {
1374 return ((PFILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
))->fileLinkCount
+ d
;
1375 } else if(Ident
== TID_EXTENDED_FILE_ENTRY
) {
1376 return ((PEXTENDED_FILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
))->fileLinkCount
+ d
;
1378 return UDF_INVALID_LINK_COUNT
;
1379 } // end UDFGetFileLinkCount()
1381 #ifdef UDF_CHECK_UTIL
1383 This routine sets fileLinkCount field in (Ext)FileEntry
1386 UDFSetFileLinkCount(
1387 IN PUDF_FILE_INFO FileInfo
,
1394 ValidateFileInfo(FileInfo
);
1396 if(!FileInfo
->Dloc
->FileEntry
)
1398 Ident
= FileInfo
->Dloc
->FileEntry
->tagIdent
;
1399 // UDF engine assumes that LinkCount is a counter
1400 // of FileIdents, referencing this FE.
1401 // UDF 2.0 states, that it should be counter of ALL
1402 // references (including SDir) - 1.
1403 // Thus we'll write to media UDF-required value, but return
1404 // cooked value to callers
1405 d
= UDFHasAStreamDir(FileInfo
) ? 0 : 1;
1406 if(Ident
== TID_FILE_ENTRY
) {
1407 ((PFILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
))->fileLinkCount
= LinkCount
- d
;
1408 } else if(Ident
== TID_EXTENDED_FILE_ENTRY
) {
1409 ((PEXTENDED_FILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
))->fileLinkCount
= LinkCount
- d
;
1412 } // end UDFGetFileLinkCount()
1413 #endif //UDF_CHECK_UTIL
1416 This routine gets lengthExtendedAttr field in (Ext)FileEntry
1420 IN PUDF_FILE_INFO FileInfo
1425 ValidateFileInfo(FileInfo
);
1427 if(!FileInfo
->Dloc
->FileEntry
)
1429 Ident
= FileInfo
->Dloc
->FileEntry
->tagIdent
;
1431 if(Ident
== TID_FILE_ENTRY
) {
1432 return ((PFILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
))->lengthExtendedAttr
;
1433 } else if(Ident
== TID_EXTENDED_FILE_ENTRY
) {
1434 return ((PEXTENDED_FILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
))->lengthExtendedAttr
;
1437 } // end UDFGetFileEALength()
1439 #ifndef UDF_READ_ONLY_BUILD
1441 This routine sets UniqueID field in (Ext)FileEntry
1448 Vcb
->NextUniqueId
++;
1449 if(!((uint32
)(Vcb
->NextUniqueId
)))
1450 Vcb
->NextUniqueId
+= 16;
1451 return Vcb
->NextUniqueId
;
1457 IN PUDF_FILE_INFO FileInfo
1463 ValidateFileInfo(FileInfo
);
1465 UID
= UDFAssingNewFUID(Vcb
);
1467 /* UID = FileInfo->Dloc->FELoc.Mapping[0].extLocation |
1468 ( FileInfo->ParentFile ? (((int64)(FileInfo->ParentFile->Dloc->FELoc.Mapping[0].extLocation)) << 32) : 0);*/
1470 FileInfo
->Dloc
->FE_Flags
|= UDF_FE_FLAG_FE_MODIFIED
;
1471 Ident
= FileInfo
->Dloc
->FileEntry
->tagIdent
;
1472 if(Ident
== TID_FILE_ENTRY
) {
1473 PFILE_ENTRY fe
= (PFILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
);
1475 } else if(Ident
== TID_EXTENDED_FILE_ENTRY
) {
1476 PEXTENDED_FILE_ENTRY fe
= (PEXTENDED_FILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
);
1479 if(FileInfo
->FileIdent
)
1480 ((FidADImpUse
*)&(FileInfo
->FileIdent
->icb
.impUse
))->uniqueID
= (uint32
)UID
;
1482 } // end UDFSetFileUID()
1483 #endif //UDF_READ_ONLY_BUILD
1486 This routine gets UniqueID field in (Ext)FileEntry
1496 Ident
= FileEntry
->tagIdent
;
1497 if(Ident
== TID_FILE_ENTRY
) {
1498 PFILE_ENTRY fe
= (PFILE_ENTRY
)(FileEntry
);
1499 return fe
->uniqueID
;
1500 } else if(Ident
== TID_EXTENDED_FILE_ENTRY
) {
1501 PEXTENDED_FILE_ENTRY fe
= (PEXTENDED_FILE_ENTRY
)(FileEntry
);
1502 return fe
->uniqueID
;
1505 } // end UDFGetFileUID()
1509 IN PUDF_FILE_INFO FileInfo
1512 ValidateFileInfo(FileInfo
);
1514 return UDFGetFileUID_(FileInfo
->Dloc
->FileEntry
);
1515 } // end UDFGetFileUID()
1517 #ifndef UDF_READ_ONLY_BUILD
1519 UDFChangeFileCounter(
1521 IN BOOLEAN FileCounter
,
1527 counter
= FileCounter
?
1530 if(*counter
== (ULONG
)-1)
1533 UDFInterlockedIncrement((int32
*)counter
);
1535 UDFInterlockedDecrement((int32
*)counter
);
1538 } // end UDFChangeFileCounter()
1541 UDFSetEntityID_imp_(
1547 impIdentSuffix
* iis
;
1549 RtlCopyMemory( (int8
*)&(eID
->ident
), Str
, Len
);
1550 iis
= (impIdentSuffix
*)&(eID
->identSuffix
);
1551 iis
->OSClass
= UDF_OS_CLASS_WINNT
;
1552 iis
->OSIdent
= UDF_OS_ID_WINNT
;
1554 } // end UDFSetEntityID_imp_()
1555 #endif //UDF_READ_ONLY_BUILD
1558 UDFReadEntityID_Domain(
1563 domainIdentSuffix
* dis
;
1566 dis
= (domainIdentSuffix
*)&(eID
->identSuffix
);
1568 KdPrint(("UDF: Entity Id:\n"));
1569 KdPrint(("flags: %x\n", eID
->flags
));
1570 KdPrint(("ident[0]: %x\n", eID
->ident
[0]));
1571 KdPrint(("ident[1]: %x\n", eID
->ident
[1]));
1572 KdPrint(("ident[2]: %x\n", eID
->ident
[2]));
1573 KdPrint(("ident[3]: %x\n", eID
->ident
[3]));
1574 KdPrint(("UDF: Entity Id Domain:\n"));
1575 // Get current UDF revision
1576 Vcb
->CurrentUDFRev
= max(dis
->currentRev
, Vcb
->CurrentUDFRev
);
1577 KdPrint(("Effective Revision: %x\n", Vcb
->CurrentUDFRev
));
1578 // Get Read-Only flags
1580 KdPrint(("Flags: %x\n", flags
));
1581 if((flags
& ENTITYID_FLAGS_SOFT_RO
) &&
1582 (Vcb
->CompatFlags
& UDF_VCB_IC_SOFT_RO
)) {
1583 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
1584 Vcb
->UserFSFlags
|= UDF_USER_FS_FLAGS_SOFT_RO
;
1585 KdPrint((" Soft-RO\n"));
1587 if((flags
& ENTITYID_FLAGS_HARD_RO
) &&
1588 (Vcb
->CompatFlags
& UDF_VCB_IC_HW_RO
)) {
1589 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_MEDIA_READ_ONLY
;
1590 Vcb
->UserFSFlags
|= UDF_USER_FS_FLAGS_HW_RO
;
1591 KdPrint((" Hard-RO\n"));
1594 } // end UDFReadEntityID_Domain()
1596 #ifndef UDF_READ_ONLY_BUILD
1598 This routine writes data to file & increases it if necessary.
1599 In case of increasing AllocDescs will be rebuilt & flushed to disc
1600 (via driver's cache, of cource). Free space map will be updated only
1601 durring global media flush.
1606 IN PUDF_FILE_INFO FileInfo
,
1611 OUT uint32
* WrittenBytes
1616 int8
* OldInIcb
= NULL
;
1617 ValidateFileInfo(FileInfo
);
1619 uint32 _WrittenBytes
;
1620 PUDF_DATALOC_INFO Dloc
;
1622 BOOLEAN WasInIcb
= FALSE
;
1625 // ASSERT(FileInfo->RefCount >= 1);
1627 Dloc
= FileInfo
->Dloc
;
1628 ASSERT(Dloc
->FELoc
.Mapping
[0].extLocation
);
1629 uint32 PartNum
= UDFGetPartNumByPhysLba(Vcb
, Dloc
->FELoc
.Mapping
[0].extLocation
);
1630 (*WrittenBytes
) = 0;
1632 AdPrint(("UDFWriteFile__ FE %x, FileInfo %x, ExtInfo %x, Mapping %x\n",
1633 Dloc
->FELoc
.Mapping
[0].extLocation
, FileInfo
, &(Dloc
->DataLoc
), Dloc
->DataLoc
.Mapping
));
1635 t
= Offset
+ Length
;
1636 // UDFUpdateModifyTime(Vcb, FileInfo);
1637 if(t
<= Dloc
->DataLoc
.Length
) {
1638 // write Alloc-Rec area
1639 ExtPrint((" WAlloc-Rec: %I64x <= %I64x\n", t
, Dloc
->DataLoc
.Length
));
1640 status
= UDFWriteExtent(Vcb
, &(Dloc
->DataLoc
), Offset
, Length
, Direct
, Buffer
, WrittenBytes
);
1643 elen
= UDFGetExtentLength(Dloc
->DataLoc
.Mapping
);
1644 ExtPrint((" DataLoc Offs %x, Len %I64x\n",
1645 Dloc
->DataLoc
.Offset
, Dloc
->DataLoc
.Length
));
1646 if(t
<= (elen
- Dloc
->DataLoc
.Offset
)) {
1647 // write Alloc-Not-Rec area
1648 ExtPrint((" WAlloc-Not-Rec: %I64x <= %I64x (%I64x - %I64x)\n",
1649 t
, elen
- Dloc
->DataLoc
.Offset
- Dloc
->DataLoc
.Length
,
1650 elen
- Dloc
->DataLoc
.Offset
,
1651 Dloc
->DataLoc
.Length
));
1652 UDFSetFileSize(FileInfo
, t
);
1653 if(Vcb
->CompatFlags
& UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS
) {
1654 ExtPrint((" w2k-compat -> rebuild allocs\n"));
1655 Dloc
->DataLoc
.Modified
= TRUE
;
1657 if((ULONG
)((elen
+Vcb
->LBlockSize
-1) >> Vcb
->LBlockSizeBits
) != (ULONG
)((t
+Vcb
->LBlockSize
-1) >> Vcb
->LBlockSizeBits
)) {
1658 ExtPrint((" LBS boundary crossed -> rebuild allocs\n"));
1659 Dloc
->DataLoc
.Modified
= TRUE
;
1661 Dloc
->DataLoc
.Length
= t
;
1662 return UDFWriteExtent(Vcb
, &(Dloc
->DataLoc
), Offset
, Length
, Direct
, Buffer
, WrittenBytes
);
1664 // We should not get here if Direct=TRUE
1665 if(Direct
) return STATUS_INVALID_PARAMETER
;
1666 OldLen
= Dloc
->DataLoc
.Length
;
1667 if(Dloc
->DataLoc
.Offset
&& Dloc
->DataLoc
.Length
) {
1668 // read in-icb data. it'll be replaced after resize
1669 ExtPrint((" read in-icb data\n"));
1670 OldInIcb
= (int8
*)MyAllocatePool__(NonPagedPool
, (uint32
)(Dloc
->DataLoc
.Length
));
1671 if(!OldInIcb
) return STATUS_INSUFFICIENT_RESOURCES
;
1672 status
= UDFReadExtent(Vcb
, &(Dloc
->DataLoc
), 0, (uint32
)OldLen
, FALSE
, OldInIcb
, &ReadBytes
);
1673 if(!OS_SUCCESS(status
)) {
1674 MyFreePool__(OldInIcb
);
1679 ExtPrint((" init Alloc mode\n"));
1680 if((((PFILE_ENTRY
)(Dloc
->FileEntry
))->icbTag
.flags
& ICB_FLAG_ALLOC_MASK
) == ICB_FLAG_AD_IN_ICB
) {
1681 ((PFILE_ENTRY
)(Dloc
->FileEntry
))->icbTag
.flags
&= ~ICB_FLAG_ALLOC_MASK
;
1682 ((PFILE_ENTRY
)(Dloc
->FileEntry
))->icbTag
.flags
|= Vcb
->DefaultAllocMode
;
1686 ExtPrint((" %s %s %s\n",
1687 UDFIsADirectory(FileInfo
) ? "DIR" : "FILE",
1688 WasInIcb
? "In-Icb" : "",
1689 Vcb
->LowFreeSpace
? "LowSpace" : ""));
1690 if(UDFIsADirectory(FileInfo
) && !WasInIcb
&& !Vcb
->LowFreeSpace
) {
1691 FileInfo
->Dloc
->DataLoc
.Flags
|= EXTENT_FLAG_ALLOC_SEQUENTIAL
;
1692 status
= UDFResizeExtent(Vcb
, PartNum
, (t
*2+Vcb
->WriteBlockSize
-1) & ~(Vcb
->WriteBlockSize
-1), FALSE
, &(Dloc
->DataLoc
));
1693 if(OS_SUCCESS(status
)) {
1694 AdPrint((" preallocated space for Dir\n"));
1695 FileInfo
->Dloc
->DataLoc
.Flags
|= EXTENT_FLAG_PREALLOCATED
;
1696 //UDFSetFileSize(FileInfo, t);
1697 Dloc
->DataLoc
.Length
= t
;
1699 if(status
== STATUS_DISK_FULL
) {
1700 status
= UDFResizeExtent(Vcb
, PartNum
, t
, FALSE
, &(Dloc
->DataLoc
));
1703 status
= UDFResizeExtent(Vcb
, PartNum
, t
, FALSE
, &(Dloc
->DataLoc
));
1705 ExtPrint((" DataLoc Offs %x, Len %I64x\n",
1706 Dloc
->DataLoc
.Offset
, Dloc
->DataLoc
.Length
));
1707 AdPrint(("UDFWriteFile__ (2) FileInfo %x, ExtInfo %x, Mapping %x\n", FileInfo
, &(Dloc
->DataLoc
), Dloc
->DataLoc
.Mapping
));
1708 if(!OS_SUCCESS(status
)) {
1710 ExtPrint((" err -> rollback\n"));
1712 // restore Alloc mode
1713 ((PFILE_ENTRY
)(Dloc
->FileEntry
))->icbTag
.flags
&= ~ICB_FLAG_ALLOC_MASK
;
1714 ((PFILE_ENTRY
)(Dloc
->FileEntry
))->icbTag
.flags
|= ICB_FLAG_AD_IN_ICB
;
1715 if(Dloc
->AllocLoc
.Mapping
) {
1716 MyFreePool__(Dloc
->AllocLoc
.Mapping
);
1717 Dloc
->AllocLoc
.Mapping
= NULL
;
1721 MyFreePool__(OldInIcb
);
1722 UDFWriteExtent(Vcb
, &(Dloc
->DataLoc
), 0, (uint32
)OldLen
, FALSE
, OldInIcb
, &_WrittenBytes
);
1724 if((int64
)OldLen
!= Dloc
->DataLoc
.Length
) {
1725 // restore file size
1726 AdPrint((" restore alloc\n"));
1727 FileInfo
->Dloc
->DataLoc
.Flags
|= EXTENT_FLAG_CUT_PREALLOCATED
;
1728 UDFResizeExtent(Vcb
, PartNum
, OldLen
, FALSE
, &(Dloc
->DataLoc
));
1729 FileInfo
->Dloc
->DataLoc
.Flags
&= ~EXTENT_FLAG_CUT_PREALLOCATED
;
1734 // replace data from ICB (if any) & free buffer
1735 ExtPrint((" write old in-icd data\n"));
1736 status
= UDFWriteExtent(Vcb
, &(Dloc
->DataLoc
), 0, (uint32
)OldLen
, FALSE
, OldInIcb
, &_WrittenBytes
);
1737 MyFreePool__(OldInIcb
);
1738 if(!OS_SUCCESS(status
))
1742 // & now we'll write out data to well prepared extent...
1743 // ... like all normal people do...
1744 ExtPrint((" write user data\n"));
1745 if(!OS_SUCCESS(status
= UDFWriteExtent(Vcb
, &(Dloc
->DataLoc
), Offset
, Length
, FALSE
, Buffer
, WrittenBytes
)))
1747 UDFSetFileSize(FileInfo
, t
);
1748 Dloc
->DataLoc
.Modified
= TRUE
;
1750 if(Vcb
->CompatFlags
& UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS
) {
1751 ASSERT(UDFGetFileSize(FileInfo
) <= UDFGetExtentLength(FileInfo
->Dloc
->DataLoc
.Mapping
));
1753 ASSERT(((UDFGetFileSize(FileInfo
)+Vcb
->LBlockSize
-1) & (Vcb
->LBlockSize
-1)) ==
1754 ((UDFGetExtentLength(FileInfo
->Dloc
->DataLoc
.Mapping
)+Vcb
->LBlockSize
-1) & (Vcb
->LBlockSize
-1)));
1757 return STATUS_SUCCESS
;
1758 } // end UDFWriteFile__()
1761 This routine marks file as deleted & decrements file link counter.
1762 It can optionaly free allocation space
1767 IN PUDF_FILE_INFO FileInfo
,
1768 IN BOOLEAN FreeSpace
1771 uint_di Index
; // index of file to be deleted
1773 PUDF_DATALOC_INFO Dloc
;
1774 PUDF_FILE_INFO DirInfo
;
1775 PUDF_FILE_INFO SDirInfo
;
1776 PDIR_INDEX_HDR hDirNdx
;
1777 PDIR_INDEX_HDR hCurDirNdx
;
1778 PDIR_INDEX_ITEM DirNdx
;
1782 AdPrint(("UDFUnlinkFile__:\n"));
1783 if(!FileInfo
) return STATUS_SUCCESS
;
1785 ValidateFileInfo(FileInfo
);
1788 // now we can't call this if there is no OS-specific File Desc. present
1790 UDFRemoveFileId__(Vcb
, FileInfo
);
1793 Dloc
= FileInfo
->Dloc
;
1794 if((FileInfo
->OpenCount
/*> (uint32)(UDFHasAStreamDir(FileInfo) ? 1 : 0)*/) ||
1795 (FileInfo
->RefCount
>1)) return STATUS_CANNOT_DELETE
;
1797 return STATUS_CANNOT_DELETE
;
1798 ASSERT(FileInfo
->RefCount
== 1);
1799 DirInfo
= FileInfo
->ParentFile
;
1801 if(!DirInfo
|| ((FileInfo
->Index
< 2) && !UDFIsAStreamDir(FileInfo
))) return STATUS_CANNOT_DELETE
;
1802 hDirNdx
= DirInfo
->Dloc
->DirIndex
;
1803 Index
= FileInfo
->Index
;
1804 // we can't delete modified file
1805 // it should be closed & reopened (or flushed) before deletion
1806 DirNdx
= UDFDirIndex(hDirNdx
,Index
);
1807 #if defined UDF_DBG || defined PRINT_ALWAYS
1808 if(DirNdx
&& DirNdx
->FName
.Buffer
) {
1809 AdPrint(("Unlink: %ws\n",DirNdx
->FName
.Buffer
));
1813 ((Dloc
->FE_Flags
& UDF_FE_FLAG_FE_MODIFIED
) ||
1814 Dloc
->DataLoc
.Modified
||
1815 Dloc
->AllocLoc
.Modified
||
1816 Dloc
->FELoc
.Modified
||
1817 (DirNdx
&& (DirNdx
->FI_Flags
& UDF_FI_FLAG_FI_MODIFIED
)) )) {
1819 return STATUS_CANNOT_DELETE
;
1821 SDirInfo
= Dloc
->SDirInfo
;
1822 /* if(FreeSpace && SDirInfo) {
1823 KdPrint(("Unlink: SDirInfo should be NULL !!!\n"));
1825 return STATUS_CANNOT_DELETE;
1827 // stream directory can be deleted even being not empty
1828 // otherwise we should perform some checks
1829 if(!(IsSDir
= UDFIsAStreamDir(FileInfo
))) {
1830 // check if not empty direcory
1831 if((DirNdx
->FileCharacteristics
& FILE_DIRECTORY
) &&
1832 (hCurDirNdx
= Dloc
->DirIndex
) &&
1834 if(!UDFIsDirEmpty(hCurDirNdx
))
1835 return STATUS_DIRECTORY_NOT_EMPTY
;
1837 DirNdx
->FI_Flags
|= UDF_FI_FLAG_FI_MODIFIED
;
1838 DirNdx
->FileCharacteristics
|= FILE_DELETED
;
1839 FileInfo
->FileIdent
->fileCharacteristics
|= FILE_DELETED
;
1840 hDirNdx
->DelCount
++;
1841 UDFChangeFileCounter(Vcb
, !UDFIsADirectory(FileInfo
), FALSE
);
1843 UDFDecFileLinkCount(FileInfo
); // decrease
1844 lc
= UDFGetFileLinkCount(FileInfo
);
1845 if(DirNdx
&& FreeSpace
) {
1846 // FileIdent marked as 'deleted' should have an empty ICB
1847 // We shall do it only if object has parent Dir
1848 // (for ex. SDir has parent object, but has no parent Dir)
1849 DirNdx
->FI_Flags
|= UDF_FI_FLAG_FI_MODIFIED
;
1850 DirNdx
->FI_Flags
&= ~UDF_FI_FLAG_SYS_ATTR
;
1851 // Root Files (Root/SDir/Vat/etc.) has no FileIdent...
1852 if(FileInfo
->FileIdent
)
1853 RtlZeroMemory(&(FileInfo
->FileIdent
->icb
), sizeof(long_ad
));
1855 // caller wishes to free allocation, but we can't do it due to
1856 // alive links. In this case we should just remove reference
1857 if(FreeSpace
&& lc
) {
1858 ((icbtag
*)(Dloc
->FileEntry
+1))->parentICBLocation
.logicalBlockNum
= 0;
1859 ((icbtag
*)(Dloc
->FileEntry
+1))->parentICBLocation
.partitionReferenceNum
= 0;
1860 Dloc
->FE_Flags
|= UDF_FE_FLAG_FE_MODIFIED
;
1862 // if caller wishes to free file allocation &
1863 // there are no more references(links) to this file, lets do it >;->
1864 if(FreeSpace
&& !lc
) {
1865 if(UDFHasAStreamDir(FileInfo
) &&
1866 !UDFIsSDirDeleted(Dloc
->SDirInfo
) ) {
1867 // we have a Stream Dir associated...
1868 PUDF_FILE_INFO SFileInfo
;
1869 // ... try to open it
1870 if(Dloc
->SDirInfo
) {
1871 UDFFlushFile__(Vcb
, FileInfo
);
1872 return STATUS_CANNOT_DELETE
;
1875 status
= UDFOpenStreamDir__(Vcb
, FileInfo
, &(Dloc
->SDirInfo
));
1876 if(!OS_SUCCESS(status
)) {
1877 // abort Unlink on error
1878 SFileInfo
= Dloc
->SDirInfo
;
1880 UDFCleanUpFile__(Vcb
, SFileInfo
);
1881 if(SFileInfo
) MyFreePool__(SFileInfo
);
1882 UDFFlushFile__(Vcb
, FileInfo
);
1885 SDirInfo
= Dloc
->SDirInfo
;
1886 // try to perform deltree for Streams
1887 status
= UDFUnlinkAllFilesInDir(Vcb
, SDirInfo
);
1888 if(!OS_SUCCESS(status
)) {
1889 // abort Unlink on error
1890 UDFCloseFile__(Vcb
, SDirInfo
);
1891 SFileInfo
= SDirInfo
;
1896 UDFFlushFile__(Vcb
, SDirInfo
);
1898 UDFUnlinkFile__(Vcb
, SDirInfo
, TRUE
);
1900 UDFCloseFile__(Vcb
, SDirInfo
);
1901 if(UDFCleanUpFile__(Vcb
, SDirInfo
)) {
1902 MyFreePool__(SDirInfo
);
1909 ASSERT(Dloc
->FileEntry
);
1910 RtlZeroMemory( &(((PEXTENDED_FILE_ENTRY
)(Dloc
->FileEntry
))->streamDirectoryICB
), sizeof(long_ad
));
1911 FileInfo
->Dloc
->FE_Flags
|= UDF_FE_FLAG_FE_MODIFIED
;
1914 // do deltree for Streams
1915 status
= UDFUnlinkAllFilesInDir(Vcb
, FileInfo
);
1916 if(!OS_SUCCESS(status
)) {
1917 UDFFlushFile__(Vcb
, FileInfo
);
1920 // update parent FileInfo
1921 ASSERT(FileInfo
->ParentFile
->Dloc
->FileEntry
);
1922 RtlZeroMemory( &(((PEXTENDED_FILE_ENTRY
)(FileInfo
->ParentFile
->Dloc
->FileEntry
))->streamDirectoryICB
), sizeof(long_ad
));
1923 FileInfo
->ParentFile
->Dloc
->FE_Flags
&= ~UDF_FE_FLAG_HAS_SDIR
;
1924 FileInfo
->ParentFile
->Dloc
->FE_Flags
|= (UDF_FE_FLAG_FE_MODIFIED
|
1925 UDF_FE_FLAG_HAS_DEL_SDIR
);
1926 FileInfo
->Dloc
->FE_Flags
|= UDF_FE_FLAG_IS_DEL_SDIR
;
1927 UDFDecFileLinkCount(FileInfo
->ParentFile
);
1929 if(Dloc
->DirIndex
) {
1930 UDFFlushFESpace(Vcb
, Dloc
, FLUSH_FE_FOR_DEL
);
1933 UDFFlushFile__(Vcb
, FileInfo
);
1934 UDFUnlinkDloc(Vcb
, Dloc
);
1936 UDFFreeFileAllocation(Vcb
, DirInfo
, FileInfo
);
1937 ASSERT(!(FileInfo
->Dloc
->FE_Flags
& UDF_FE_FLAG_FE_MODIFIED
));
1938 FileInfo
->Dloc
->FE_Flags
&= ~UDF_FE_FLAG_FE_MODIFIED
;
1940 return STATUS_SUCCESS
;
1941 } // end UDFUnlinkFile__()
1944 UDFUnlinkAllFilesInDir(
1946 IN PUDF_FILE_INFO DirInfo
1949 PDIR_INDEX_HDR hCurDirNdx
;
1950 PDIR_INDEX_ITEM CurDirNdx
;
1951 PUDF_FILE_INFO FileInfo
;
1955 hCurDirNdx
= DirInfo
->Dloc
->DirIndex
;
1956 // check if we can delete all files
1957 for(i
=2; (CurDirNdx
= UDFDirIndex(hCurDirNdx
,i
)); i
++) {
1958 // try to open Stream
1959 if(CurDirNdx
->FileInfo
)
1960 return STATUS_CANNOT_DELETE
;
1963 for(i
=2; (CurDirNdx
= UDFDirIndex(hCurDirNdx
,i
)); i
++) {
1964 // try to open Stream
1965 status
= UDFOpenFile__(Vcb
, FALSE
, TRUE
, NULL
, DirInfo
, &FileInfo
, &i
);
1966 if(status
== STATUS_FILE_DELETED
) {
1967 // we should not release on-disk allocation for
1968 // deleted streams twice
1969 if(CurDirNdx
->FileInfo
) {
1971 goto err_del_stream
;
1973 goto skip_del_stream
;
1975 if(!OS_SUCCESS(status
)) {
1978 UDFCleanUpFile__(Vcb
, FileInfo
);
1980 MyFreePool__(FileInfo
);
1984 UDFFlushFile__(Vcb
, FileInfo
);
1986 UDFUnlinkFile__(Vcb
, FileInfo
, TRUE
);
1987 UDFCloseFile__(Vcb
, FileInfo
);
1989 if(FileInfo
&& UDFCleanUpFile__(Vcb
, FileInfo
)) {
1990 MyFreePool__(FileInfo
);
1993 return STATUS_SUCCESS
;
1994 } // end UDFUnlinkAllFilesInDir()
1995 #endif //UDF_READ_ONLY_BUILD
1998 This routine inits UDF_FILE_INFO structure for specified file
1999 If it returns status != STATUS_SUCCESS caller should call UDFCleanUpFile__
2000 for returned pointer *WITHOUT* using UDFCloseFile__
2005 IN BOOLEAN IgnoreCase
,
2006 IN BOOLEAN NotDeleted
,
2007 IN PUNICODE_STRING fn
,
2008 IN PUDF_FILE_INFO DirInfo
,
2009 OUT PUDF_FILE_INFO
* _FileInfo
,// this is to be filled & doesn't contain
2011 IN uint_di
* IndexToOpen
2018 PDIR_INDEX_HDR hDirNdx
= DirInfo
->Dloc
->DirIndex
;
2019 PDIR_INDEX_ITEM DirNdx
;
2020 PUDF_FILE_INFO FileInfo
;
2021 PUDF_FILE_INFO ParFileInfo
;
2024 if(!hDirNdx
) return STATUS_NOT_A_DIRECTORY
;
2026 // find specified file in directory index
2027 // if it is already known, skip this foolish code
2031 if(!OS_SUCCESS(status
= UDFFindFile(Vcb
, IgnoreCase
, NotDeleted
, fn
, DirInfo
, &i
)))
2033 // do this check for OpenByIndex
2034 // some routines may send invalid Index
2035 if(!(DirNdx
= UDFDirIndex(hDirNdx
,i
)))
2036 return STATUS_OBJECT_NAME_NOT_FOUND
;
2037 if((FileInfo
= DirNdx
->FileInfo
)) {
2038 // file is already opened.
2039 if((DirNdx
->FileCharacteristics
& FILE_DELETED
) && NotDeleted
) {
2040 AdPrint((" FILE_DELETED on open\n"));
2041 return STATUS_FILE_DELETED
;
2043 if((FileInfo
->ParentFile
!= DirInfo
) &&
2044 (FileInfo
->Index
>= 2)) {
2045 ParFileInfo
= UDFLocateParallelFI(DirInfo
, i
, FileInfo
);
2047 if(ParFileInfo
->ParentFile
!= DirInfo
) {
2048 FileInfo
= (PUDF_FILE_INFO
)MyAllocatePoolTag__(UDF_FILE_INFO_MT
,sizeof(UDF_FILE_INFO
), MEM_FINF_TAG
);
2049 *_FileInfo
= FileInfo
;
2050 if(!FileInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
2051 RtlCopyMemory(FileInfo
, DirNdx
->FileInfo
, sizeof(UDF_FILE_INFO
));
2052 // FileInfo->NextLinkedFile = DirNdx->FileInfo->NextLinkedFile; // is already done
2053 UDFInsertLinkedFile(FileInfo
, DirNdx
->FileInfo
);
2054 DirNdx
->FI_Flags
|= UDF_FI_FLAG_LINKED
;
2055 FileInfo
->RefCount
= 0;
2056 FileInfo
->ParentFile
= DirInfo
;
2057 FileInfo
->Fcb
= NULL
;
2059 FileInfo
= ParFileInfo
;
2062 // Just increase some counters & exit
2063 UDFReferenceFile__(FileInfo
);
2065 ASSERT(FileInfo
->ParentFile
== DirInfo
);
2066 ValidateFileInfo(FileInfo
);
2068 *_FileInfo
= FileInfo
;
2069 return STATUS_SUCCESS
;
2072 if((DirNdx
->FileCharacteristics
& FILE_DELETED
) && NotDeleted
) {
2073 AdPrint((" FILE_DELETED on open (2)\n"));
2074 return STATUS_FILE_DELETED
;
2077 FileInfo
= (PUDF_FILE_INFO
)MyAllocatePoolTag__(UDF_FILE_INFO_MT
,sizeof(UDF_FILE_INFO
), MEM_FINF_TAG
);
2078 *_FileInfo
= FileInfo
;
2079 if(!FileInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
2080 RtlZeroMemory(FileInfo
, sizeof(UDF_FILE_INFO
));
2081 // init horizontal links
2082 FileInfo
->NextLinkedFile
=
2083 FileInfo
->PrevLinkedFile
= FileInfo
;
2085 FileInfo
->FileIdent
= (PFILE_IDENT_DESC
)MyAllocatePoolTag__(NonPagedPool
, DirNdx
->Length
, MEM_FID_TAG
);
2086 if(!(FileInfo
->FileIdent
)) return STATUS_INSUFFICIENT_RESOURCES
;
2087 FileInfo
->FileIdentLen
= DirNdx
->Length
;
2088 if(!OS_SUCCESS(status
= UDFReadExtent(Vcb
, &(DirInfo
->Dloc
->DataLoc
), DirNdx
->Offset
,
2089 DirNdx
->Length
, FALSE
, (int8
*)(FileInfo
->FileIdent
), &ReadBytes
) ))
2091 if(FileInfo
->FileIdent
->descTag
.tagIdent
!= TID_FILE_IDENT_DESC
) {
2093 return STATUS_FILE_CORRUPT_ERROR
;
2095 // check for opened links
2096 if(!OS_SUCCESS(status
= UDFStoreDloc(Vcb
, FileInfo
, UDFPartLbaToPhys(Vcb
, &(FileInfo
->FileIdent
->icb
.extLocation
)))))
2098 // init pointer to parent object
2099 FileInfo
->Index
= i
;
2100 FileInfo
->ParentFile
= DirInfo
;
2101 // init pointers to linked files (if any)
2102 if(FileInfo
->Dloc
->LinkedFileInfo
!= FileInfo
)
2103 UDFInsertLinkedFile(FileInfo
, FileInfo
->Dloc
->LinkedFileInfo
);
2104 if(FileInfo
->Dloc
->FileEntry
)
2105 goto init_tree_entry
;
2106 // read (Ex)FileEntry
2107 FileInfo
->Dloc
->FileEntry
= (tag
*)MyAllocatePoolTag__(NonPagedPool
, Vcb
->LBlockSize
, MEM_FE_TAG
);
2108 if(!(FileInfo
->Dloc
->FileEntry
)) return STATUS_INSUFFICIENT_RESOURCES
;
2109 if(!OS_SUCCESS(status
= UDFReadFileEntry(Vcb
, &(FileInfo
->FileIdent
->icb
), (PFILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
), &Ident
)))
2111 // build mappings for Data & AllocDescs
2112 if(!FileInfo
->Dloc
->AllocLoc
.Mapping
) {
2113 FEExt
.extLength
= FileInfo
->FileIdent
->icb
.extLength
;
2114 FEExt
.extLocation
= UDFPartLbaToPhys(Vcb
, &(FileInfo
->FileIdent
->icb
.extLocation
) );
2115 if(FEExt
.extLocation
== LBA_OUT_OF_EXTENT
)
2116 return STATUS_FILE_CORRUPT_ERROR
;
2117 FileInfo
->Dloc
->AllocLoc
.Mapping
= UDFExtentToMapping(&FEExt
);
2118 if(!(FileInfo
->Dloc
->AllocLoc
.Mapping
))
2119 return STATUS_INSUFFICIENT_RESOURCES
;
2121 // read location info
2122 status
= UDFLoadExtInfo(Vcb
, (PFILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
), &(FileInfo
->FileIdent
->icb
),
2123 &(FileInfo
->Dloc
->DataLoc
), &(FileInfo
->Dloc
->AllocLoc
) );
2124 if(!OS_SUCCESS(status
))
2126 // init (Ex)FileEntry mapping
2127 FileInfo
->Dloc
->FELoc
.Length
= (FileInfo
->Dloc
->DataLoc
.Offset
) ? FileInfo
->Dloc
->DataLoc
.Offset
:
2128 FileInfo
->Dloc
->AllocLoc
.Offset
;
2129 // FileInfo->Dloc->FELoc.Offset = 0;
2130 FileInfo
->Dloc
->FELoc
.Mapping
= UDFExtentToMapping(&FEExt
);
2131 FileInfo
->Dloc
->FileEntryLen
= (uint32
)(FileInfo
->Dloc
->FELoc
.Length
);
2132 // we get here immediately when opened link encountered
2134 // init back pointer from parent object
2135 ASSERT(!DirNdx
->FileInfo
);
2136 DirNdx
->FileInfo
= FileInfo
;
2138 if(UDFGetFileLinkCount(FileInfo
) > 1) {
2139 DirNdx
->FI_Flags
|= UDF_FI_FLAG_LINKED
;
2141 DirNdx
->FI_Flags
&= ~UDF_FI_FLAG_LINKED
;
2143 // resize FE cache (0x800 instead of 0x40 is not a good idea)
2144 if(!MyReallocPool__((int8
*)((FileInfo
->Dloc
->FileEntry
)), Vcb
->LBlockSize
,
2145 (int8
**)&((FileInfo
->Dloc
->FileEntry
)), FileInfo
->Dloc
->FileEntryLen
))
2146 return STATUS_INSUFFICIENT_RESOURCES
;
2147 // check if this file has a SDir
2148 if((FileInfo
->Dloc
->FileEntry
->tagIdent
== TID_EXTENDED_FILE_ENTRY
) &&
2149 ((PEXTENDED_FILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
))->streamDirectoryICB
.extLength
)
2150 FileInfo
->Dloc
->FE_Flags
|= UDF_FE_FLAG_HAS_SDIR
;
2151 if(!(FileInfo
->FileIdent
->fileCharacteristics
& FILE_DIRECTORY
)) {
2152 UDFReferenceFile__(FileInfo
);
2153 ASSERT(FileInfo
->ParentFile
== DirInfo
);
2154 UDFReleaseDloc(Vcb
, FileInfo
->Dloc
);
2155 return STATUS_SUCCESS
;
2158 UDFCheckSpaceAllocation(Vcb
, 0, FileInfo
->Dloc
->DataLoc
.Mapping
, AS_USED
); // check if used
2160 // build index for directories
2161 if(!FileInfo
->Dloc
->DirIndex
) {
2162 status
= UDFIndexDirectory(Vcb
, FileInfo
);
2163 if(!OS_SUCCESS(status
))
2165 #ifndef UDF_READ_ONLY_BUILD
2166 if((FileInfo
->Dloc
->DirIndex
->DelCount
> Vcb
->PackDirThreshold
) &&
2167 !(Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_READ_ONLY
)) {
2168 status
= UDFPackDirectory__(Vcb
, FileInfo
);
2169 if(!OS_SUCCESS(status
))
2172 #endif //UDF_READ_ONLY_BUILD
2174 UDFReferenceFile__(FileInfo
);
2175 UDFReleaseDloc(Vcb
, FileInfo
->Dloc
);
2176 ASSERT(FileInfo
->ParentFile
== DirInfo
);
2179 } // end UDFOpenFile__()
2183 This routine inits UDF_FILE_INFO structure for root directory
2188 IN lb_addr
* RootLoc
,
2189 OUT PUDF_FILE_INFO FileInfo
2194 // uint32 PartNum = RootLoc->partitionReferenceNum;
2195 uint32 LBS
= Vcb
->LBlockSize
;
2201 RtlZeroMemory(FileInfo
, sizeof(UDF_FILE_INFO
));
2202 RootLBA
= UDFPartLbaToPhys(Vcb
,RootLoc
);
2203 if(RootLBA
== LBA_OUT_OF_EXTENT
)
2204 return STATUS_FILE_CORRUPT_ERROR
;
2205 FELoc
.extLocation
= *RootLoc
;
2206 FELoc
.extLength
= LBS
;
2207 // init horizontal links
2208 FileInfo
->NextLinkedFile
=
2209 FileInfo
->PrevLinkedFile
= FileInfo
;
2210 // check for opened links
2211 if(!OS_SUCCESS(status
= UDFStoreDloc(Vcb
, FileInfo
, RootLBA
)))
2213 if(FileInfo
->Dloc
->FileEntry
)
2214 goto init_tree_entry
;
2215 // read (Ex)FileEntry
2216 FileInfo
->Dloc
->FileEntry
= (tag
*)MyAllocatePoolTag__(NonPagedPool
, LBS
, MEM_FE_TAG
);
2217 if(!(FileInfo
->Dloc
->FileEntry
)) return STATUS_INSUFFICIENT_RESOURCES
;
2219 if(!OS_SUCCESS(status
= UDFReadFileEntry(Vcb
, &FELoc
, (PFILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
), &Ident
)))
2221 // build mappings for Data & AllocDescs
2222 FEExt
.extLength
= LBS
;
2223 FEExt
.extLocation
= UDFPartLbaToPhys(Vcb
, &(FELoc
.extLocation
) );
2224 if(FEExt
.extLocation
== LBA_OUT_OF_EXTENT
)
2225 return STATUS_FILE_CORRUPT_ERROR
;
2226 FileInfo
->Dloc
->FELoc
.Mapping
= UDFExtentToMapping(&FEExt
);
2227 if(!(FileInfo
->Dloc
->FELoc
.Mapping
)) return STATUS_INSUFFICIENT_RESOURCES
;
2228 // build mappings for AllocDescs
2229 if(!FileInfo
->Dloc
->AllocLoc
.Mapping
) {
2230 FileInfo
->Dloc
->AllocLoc
.Mapping
= UDFExtentToMapping(&FEExt
);
2231 if(!(FileInfo
->Dloc
->AllocLoc
.Mapping
)) return STATUS_INSUFFICIENT_RESOURCES
;
2233 if(!OS_SUCCESS(status
= UDFLoadExtInfo(Vcb
, (PFILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
), &FELoc
,
2234 &(FileInfo
->Dloc
->DataLoc
), &(FileInfo
->Dloc
->AllocLoc
) ) ))
2236 FileInfo
->Dloc
->FileEntryLen
= (uint32
)
2237 (FileInfo
->Dloc
->FELoc
.Length
= (FileInfo
->Dloc
->DataLoc
.Offset
) ? FileInfo
->Dloc
->DataLoc
.Offset
:
2238 FileInfo
->Dloc
->AllocLoc
.Offset
);
2240 // resize FE cache (0x800 instead of 0x40 is not a good idea)
2241 if(!MyReallocPool__((int8
*)((FileInfo
->Dloc
->FileEntry
)), LBS
,
2242 (int8
**)&((FileInfo
->Dloc
->FileEntry
)), FileInfo
->Dloc
->FileEntryLen
))
2243 return STATUS_INSUFFICIENT_RESOURCES
;
2245 if( (FileType
= ((icbtag
*)((FileInfo
->Dloc
->FileEntry
)+1))->fileType
) != UDF_FILE_TYPE_DIRECTORY
&&
2246 (FileType
!= UDF_FILE_TYPE_STREAMDIR
) ) {
2247 UDFReferenceFile__(FileInfo
);
2248 UDFReleaseDloc(Vcb
, FileInfo
->Dloc
);
2249 return STATUS_SUCCESS
;
2251 // build index for directories
2252 if(!FileInfo
->Dloc
->DirIndex
) {
2253 status
= UDFIndexDirectory(Vcb
, FileInfo
);
2254 if(!OS_SUCCESS(status
))
2256 #ifndef UDF_READ_ONLY_BUILD
2257 if((FileInfo
->Dloc
->DirIndex
->DelCount
> Vcb
->PackDirThreshold
) &&
2258 !(Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_READ_ONLY
)) {
2259 status
= UDFPackDirectory__(Vcb
, FileInfo
);
2260 if(!OS_SUCCESS(status
))
2263 #endif //UDF_READ_ONLY_BUILD
2265 UDFReferenceFile__(FileInfo
);
2266 UDFReleaseDloc(Vcb
, FileInfo
->Dloc
);
2269 } // end UDFOpenRootFile__()
2272 This routine frees all memory blocks referenced by given FileInfo
2277 IN PUDF_FILE_INFO FileInfo
2280 PUDF_DATALOC_INFO Dloc
;
2284 PDIR_INDEX_ITEM DirNdx
, DirNdx2
;
2285 BOOLEAN Parallel
= FALSE
;
2286 BOOLEAN Linked
= FALSE
;
2288 BOOLEAN Modified
= FALSE
;
2289 PDIR_INDEX_HDR hDirNdx
;
2291 PUDF_FILE_INFO DirInfo
;
2294 if(!FileInfo
) return UDF_FREE_FILEINFO
;
2296 ValidateFileInfo(FileInfo
);
2298 if(FileInfo
->OpenCount
|| FileInfo
->RefCount
) {
2299 KdPrint(("UDF: not all references are closed\n"));
2300 KdPrint((" Skipping cleanup\n"));
2301 KdPrint(("UDF: OpenCount = %x, RefCount = %x, LinkRefCount = %x\n",
2302 FileInfo
->OpenCount
,FileInfo
->RefCount
,FileInfo
->Dloc
->LinkRefCount
));
2303 return UDF_FREE_NOTHING
;
2306 KdPrint(("Operating System still has references to this file\n"));
2307 KdPrint((" Skipping cleanup\n"));
2309 return UDF_FREE_NOTHING
;
2312 IsASDir
= UDFIsAStreamDir(FileInfo
);
2314 if((Dloc
= FileInfo
->Dloc
)) {
2317 DirInfo
= FileInfo
->ParentFile
;
2319 hDirNdx
= DirInfo
->Dloc
->DirIndex
;
2320 Index
= FileInfo
->Index
;
2321 // we can't delete modified file
2322 // it should be closed & reopened (or flushed) before deletion
2323 DirNdx
= UDFDirIndex(hDirNdx
,Index
);
2324 KdPrint(("Cleanup Mod: %s%s%s%s%s%s\n",
2325 (Dloc
->FE_Flags
& UDF_FE_FLAG_FE_MODIFIED
) ? "FE " : "",
2326 (Dloc
->DataLoc
.Modified
) ? "DataLoc " : "",
2327 (Dloc
->DataLoc
.Flags
& EXTENT_FLAG_PREALLOCATED
) ? "Data-PreAlloc " : "",
2328 (Dloc
->AllocLoc
.Modified
) ? "AllocLoc " : "",
2329 (Dloc
->FELoc
.Modified
) ? "FELoc " : "",
2330 (DirNdx
&& (DirNdx
->FI_Flags
& UDF_FI_FLAG_FI_MODIFIED
)) ? "FI " : ""
2332 Modified
= ((Dloc
->FE_Flags
& UDF_FE_FLAG_FE_MODIFIED
) ||
2333 Dloc
->DataLoc
.Modified
||
2334 (Dloc
->DataLoc
.Flags
& EXTENT_FLAG_PREALLOCATED
) ||
2335 Dloc
->AllocLoc
.Modified
||
2336 Dloc
->FELoc
.Modified
||
2337 (DirNdx
&& (DirNdx
->FI_Flags
& UDF_FI_FLAG_FI_MODIFIED
)) );
2341 PUDF_FILE_INFO ParFileInfo
= UDFLocateAnyParallelFI(FileInfo
);
2343 Parallel
= (ParFileInfo
!= NULL
);
2344 Linked
= (FileInfo
->NextLinkedFile
!= FileInfo
);
2346 // Parallel = (FileInfo->NextLinkedFile != FileInfo);
2347 ASSERT(FileInfo
->NextLinkedFile
);
2348 // ASSERT(!Parallel);
2349 KeepDloc
= (Dloc
->LinkRefCount
||
2354 if(Dloc
->DirIndex
) {
2356 for(i
=2; (DirNdx
= UDFDirIndex(Dloc
->DirIndex
,i
)); i
++) {
2357 if(DirNdx
->FileInfo
) {
2360 KdPrint(("UDF: Found not cleaned up reference.\n"));
2361 KdPrint((" Skipping cleanup (1)\n"));
2363 return UDF_FREE_NOTHING
;
2365 // The file being cleaned up may have not closed Dirs
2366 // (linked Dir). In this case each of them may have
2367 // reference to FileInfo in DirIndex[1]
2368 // Here we'll check it and change for valid value if
2369 // necessary (Update Child Objects - I)
2370 if(DirNdx
->FileInfo
->Dloc
) {
2371 // we can get here only when (Parallel == TRUE)
2372 DirNdx2
= UDFDirIndex(DirNdx
->FileInfo
->Dloc
->DirIndex
, 1);
2373 // It is enough to check DirNdx2->FileInfo only.
2374 // If one of Parallel FI's has reference (and equal)
2375 // to the FI being removed, it'll be removed from
2376 // the chain & nothing wrong will happen.
2377 if(DirNdx2
&& (DirNdx2
->FileInfo
== FileInfo
)) {
2378 if(FileInfo
->PrevLinkedFile
== FileInfo
) {
2380 DirNdx2
->FileInfo
= NULL
;
2382 DirNdx2
->FileInfo
= Parallel
?
2383 ParFileInfo
: FileInfo
->PrevLinkedFile
;
2385 ASSERT(!DirNdx2
->FileInfo
->RefCount
);
2391 if(Dloc
->SDirInfo
) {
2392 KdPrint(("UDF: Found not cleaned up reference (SDir).\n"));
2394 // (Update Child Objects - II)
2395 if(Dloc
->SDirInfo
->ParentFile
== FileInfo
) {
2397 ASSERT(ParFileInfo
);
2398 Dloc
->SDirInfo
->ParentFile
= ParFileInfo
;
2400 // We should break Cleanup process if alive reference detected
2401 // and there is no possibility to store pointer in some other
2402 // place (in parallel object)
2405 KdPrint((" Skipping cleanup\n"));
2406 return UDF_FREE_NOTHING
;
2409 if(!UDFIsSDirDeleted(Dloc
->SDirInfo
) &&
2410 Dloc
->SDirInfo
->Dloc
) {
2411 DirNdx2
= UDFDirIndex(Dloc
->SDirInfo
->Dloc
->DirIndex
, 1);
2412 if(DirNdx2
&& (DirNdx2
->FileInfo
== FileInfo
)) {
2414 Parallel
? ParFileInfo
: NULL
;
2415 ASSERT(!DirNdx2
->FileInfo
->RefCount
);
2426 #ifndef UDF_TRACK_ONDISK_ALLOCATION
2427 if(Dloc
->DataLoc
.Mapping
) MyFreePool__(Dloc
->DataLoc
.Mapping
);
2428 if(Dloc
->AllocLoc
.Mapping
) MyFreePool__(Dloc
->AllocLoc
.Mapping
);
2429 if(Dloc
->FELoc
.Mapping
) MyFreePool__(Dloc
->FELoc
.Mapping
);
2430 if(Dloc
->FileEntry
) {
2432 lc
= UDFGetFileLinkCount(FileInfo
);
2433 MyFreePool__(Dloc
->FileEntry
);
2434 Dloc
->FileEntry
= NULL
;
2435 } else if(FileInfo
->Index
>= 2) {
2436 // error durring open operation
2437 lc
= UDF_INVALID_LINK_COUNT
;
2439 #endif //UDF_TRACK_ONDISK_ALLOCATION
2440 if(FileInfo
->Dloc
->DirIndex
) {
2442 for(i
=2; (DirNdx
= UDFDirIndex(Dloc
->DirIndex
,i
)); i
++) {
2443 ASSERT(!DirNdx
->FileInfo
);
2444 if(DirNdx
->FName
.Buffer
)
2445 MyFreePool__(DirNdx
->FName
.Buffer
);
2447 // The only place where we can free FE_Charge extent is here
2448 UDFFlushFESpace(Vcb
, Dloc
);
2449 UDFDirIndexFree(Dloc
->DirIndex
);
2450 Dloc
->DirIndex
= NULL
;
2451 #ifdef UDF_TRACK_ONDISK_ALLOCATION
2452 UDFIndexDirectory(Vcb
, FileInfo
);
2453 if(FileInfo
->Dloc
->DirIndex
) {
2454 for(i
=2; DirNdx
= UDFDirIndex(Dloc
->DirIndex
,i
); i
++) {
2455 ASSERT(!DirNdx
->FileInfo
);
2456 if(DirNdx
->FName
.Buffer
)
2457 MyFreePool__(DirNdx
->FName
.Buffer
);
2459 UDFDirIndexFree(Dloc
->DirIndex
);
2460 Dloc
->DirIndex
= NULL
;
2462 #endif //UDF_TRACK_ONDISK_ALLOCATION
2465 #ifdef UDF_TRACK_ONDISK_ALLOCATION
2466 if(Dloc
->AllocLoc
.Mapping
) MyFreePool__(Dloc
->AllocLoc
.Mapping
);
2467 if(Dloc
->FELoc
.Mapping
) MyFreePool__(Dloc
->FELoc
.Mapping
);
2468 if(Dloc
->FileEntry
) {
2470 lc
= UDFGetFileLinkCount(FileInfo
);
2471 MyFreePool__(Dloc
->FileEntry
);
2472 Dloc
->FileEntry
= NULL
;
2473 } else if(FileInfo
->Index
>= 2) {
2474 // error durring open operation
2475 lc
= UDF_INVALID_LINK_COUNT
;
2477 if(Dloc
->DataLoc
.Mapping
) {
2478 if(lc
&& (lc
!= UDF_INVALID_LINK_COUNT
)) {
2479 UDFCheckSpaceAllocation(Vcb
, 0, Dloc
->DataLoc
.Mapping
, AS_USED
); // check if used
2481 UDFCheckSpaceAllocation(Vcb
, 0, Dloc
->DataLoc
.Mapping
, AS_FREE
); // check if free
2483 MyFreePool__(Dloc
->DataLoc
.Mapping
);
2485 #endif //UDF_TRACK_ONDISK_ALLOCATION
2487 if(lc
&& (lc
!= UDF_INVALID_LINK_COUNT
)) {
2488 UDFRemoveDloc(Vcb
, Dloc
);
2490 UDFFreeDloc(Vcb
, Dloc
);
2492 } else // KeepDloc cannot be FALSE if (Linked == TRUE)
2495 // Update pointers in ParentObject (if any)
2496 if(FileInfo
->ParentFile
->Dloc
->SDirInfo
== FileInfo
)
2497 FileInfo
->ParentFile
->Dloc
->SDirInfo
= FileInfo
->PrevLinkedFile
;
2498 DirNdx
= UDFDirIndex(FileInfo
->Dloc
->DirIndex
, 0);
2499 if(DirNdx
&& (DirNdx
->FileInfo
== FileInfo
))
2500 DirNdx
->FileInfo
= FileInfo
->PrevLinkedFile
;
2501 DirNdx
= UDFDirIndex(FileInfo
->ParentFile
->Dloc
->DirIndex
, FileInfo
->Index
);
2502 if(DirNdx
&& (DirNdx
->FileInfo
== FileInfo
))
2503 DirNdx
->FileInfo
= ParFileInfo
;
2504 // remove from linked chain
2505 FileInfo
->NextLinkedFile
->PrevLinkedFile
= FileInfo
->PrevLinkedFile
;
2506 FileInfo
->PrevLinkedFile
->NextLinkedFile
= FileInfo
->NextLinkedFile
;
2507 // update pointer in Dloc
2508 if(FileInfo
->Dloc
->LinkedFileInfo
== FileInfo
)
2509 FileInfo
->Dloc
->LinkedFileInfo
= FileInfo
->PrevLinkedFile
;
2511 FileInfo
->Dloc
= NULL
;
2516 // Cleanup pointers in ParentObject (if any)
2518 if(FileInfo
->ParentFile
->Dloc
->SDirInfo
== FileInfo
) {
2520 FileInfo
->ParentFile
->Dloc
->SDirInfo
= NULL
;
2521 FileInfo
->ParentFile
->Dloc
->FE_Flags
&= ~UDF_FE_FLAG_HAS_DEL_SDIR
;
2524 if(FileInfo
->ParentFile
) {
2525 ASSERT(FileInfo
->ParentFile
->Dloc
);
2526 DirNdx
= UDFDirIndex(FileInfo
->ParentFile
->Dloc
->DirIndex
, FileInfo
->Index
);
2529 PUDF_FILE_INFO OldFI
;
2531 ASSERT(!DirNdx
|| !(OldFI
= DirNdx
->FileInfo
) ||
2532 !(OldFI
== FileInfo
));
2534 ASSERT(!DirNdx
|| !(OldFI
= DirNdx
->FileInfo
) ||
2535 (OldFI
== FileInfo
));
2538 if( DirNdx
&& (DirNdx
->FileInfo
== FileInfo
) ) {
2540 DirNdx
->FileInfo
= NULL
;
2543 // We can get here after incomplete Open
2544 if(!Parallel
&& DirNdx
->FileInfo
)
2554 if(!Parallel
&& FileInfo
->FileIdent
)
2555 MyFreePool__(FileInfo
->FileIdent
);
2556 FileInfo
->FileIdent
= NULL
;
2557 // Kill reference to parent object
2558 FileInfo
->ParentFile
= NULL
;
2559 // Kill references to parallel object(s) since it has no reference to
2561 FileInfo
->NextLinkedFile
=
2562 FileInfo
->PrevLinkedFile
= FileInfo
;
2563 if(FileInfo
->ListPtr
)
2564 FileInfo
->ListPtr
->FileInfo
= NULL
;;
2565 return KeepDloc
? UDF_FREE_FILEINFO
: (UDF_FREE_FILEINFO
| UDF_FREE_DLOC
);
2566 } // end UDFCleanUpFile__()
2568 #ifndef UDF_READ_ONLY_BUILD
2570 This routine creates FileIdent record in destination directory &
2571 allocates FileEntry with in-ICB zero-sized data
2572 If it returns status != STATUS_SUCCESS caller should call UDFCleanUpFile__
2573 for returned pointer *WITHOUT* using UDFCloseFile__
2578 // IN uint16 AllocMode, // short/long/ext/in-icb // always in-ICB
2579 IN BOOLEAN IgnoreCase
,
2580 IN PUNICODE_STRING _fn
,
2581 IN uint32 ExtAttrSz
,
2582 IN uint32 ImpUseLen
,
2583 IN BOOLEAN Extended
,
2584 IN BOOLEAN CreateNew
,
2585 IN OUT PUDF_FILE_INFO DirInfo
,
2586 OUT PUDF_FILE_INFO
* _FileInfo
2593 UDF_DIR_SCAN_CONTEXT ScanContext
;
2594 PDIR_INDEX_HDR hDirNdx
= DirInfo
->Dloc
->DirIndex
;
2595 PDIR_INDEX_ITEM DirNdx
;
2596 uint32 LBS
= Vcb
->LBlockSize
;
2597 PUDF_FILE_INFO FileInfo
;
2599 BOOLEAN undel
= FALSE
;
2601 // BOOLEAN PackDir = FALSE;
2602 BOOLEAN FEAllocated
= FALSE
;
2604 ValidateFileInfo(DirInfo
);
2607 ASSERT(DirInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
);
2608 uint32 PartNum
= UDFGetPartNumByPhysLba(Vcb
, DirInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
);
2609 if(!hDirNdx
) return STATUS_NOT_A_DIRECTORY
;
2615 status
= UDFFindFile(Vcb
, IgnoreCase
, FALSE
, _fn
, DirInfo
, &i
);
2616 DirNdx
= UDFDirIndex(hDirNdx
,i
);
2617 if(OS_SUCCESS(status
)) {
2618 // file is a Cur(Parent)Dir
2619 if(i
<2) try_return (status
= STATUS_ACCESS_DENIED
);
2621 if(UDFIsDeleted(DirNdx
)) {
2623 if(OS_SUCCESS(UDFFindFile(Vcb
, IgnoreCase
, TRUE
, _fn
, DirInfo
, &j
))) {
2625 DirNdx
= UDFDirIndex(hDirNdx
,i
);
2626 goto CreateBothFound
;
2628 // we needn't allocating new FileIdent inside Dir stream
2630 if(DirNdx
->FileInfo
) {
2632 status
= UDFPretendFileDeleted__(Vcb
, DirNdx
->FileInfo
);
2633 if(!OS_SUCCESS(status
))
2634 try_return (status
= STATUS_FILE_DELETED
);
2642 // file already exists
2643 if(CreateNew
) try_return (status
= STATUS_ACCESS_DENIED
);
2646 status
= UDFOpenFile__(Vcb
, IgnoreCase
, TRUE
, _fn
, DirInfo
, _FileInfo
,&i
);
2647 // *_FileInfo = FileInfo; // OpenFile__ has already done it, so update it...
2648 DirNdx
= UDFDirIndex(hDirNdx
,i
);
2649 DirNdx
->FI_Flags
&= ~UDF_FI_FLAG_SYS_ATTR
;
2650 FileInfo
= *_FileInfo
;
2651 if(!OS_SUCCESS(status
)) {
2652 // :(( can't open....
2653 if(FileInfo
&& UDFCleanUpFile__(Vcb
, FileInfo
)) {
2654 MyFreePool__(FileInfo
);
2658 try_return (status
);
2660 // check if we can delete this file
2661 if(FileInfo
->OpenCount
|| (FileInfo
->RefCount
> 1)) {
2663 UDFCloseFile__(Vcb
, FileInfo
);
2664 try_return (status
= STATUS_CANNOT_DELETE
);
2667 // remove DIRECTORY flag
2668 DirNdx
->FileCharacteristics
&= ~FILE_DIRECTORY
;
2669 FileInfo
->FileIdent
->fileCharacteristics
&= ~FILE_DIRECTORY
;
2670 DirNdx
->FI_Flags
|= UDF_FI_FLAG_FI_MODIFIED
;
2671 // truncate file size to ZERO
2672 status
= UDFResizeFile__(Vcb
, FileInfo
, 0);
2673 if(!OS_SUCCESS(status
)) {
2675 UDFCloseFile__(Vcb
, FileInfo
);
2678 FileInfo
->FileIdent
->fileCharacteristics
= 0;
2679 DirNdx
->FileCharacteristics
= 0;
2680 // update DeletedFiles counter in Directory... (for PackDir)
2681 if(undel
&& OS_SUCCESS(status
))
2682 hDirNdx
->DelCount
--;
2683 try_return (status
);
2688 // allocate FileInfo
2689 FileInfo
= (PUDF_FILE_INFO
)MyAllocatePoolTag__(UDF_FILE_INFO_MT
,sizeof(UDF_FILE_INFO
), MEM_FE_TAG
);
2690 *_FileInfo
= FileInfo
;
2692 try_return (status
= STATUS_INSUFFICIENT_RESOURCES
);
2693 ImpUseLen
= (ImpUseLen
+ 3) & ~((uint16
)3);
2695 RtlZeroMemory(FileInfo
, sizeof(UDF_FILE_INFO
));
2696 // init horizontal links
2697 FileInfo
->NextLinkedFile
=
2698 FileInfo
->PrevLinkedFile
= FileInfo
;
2699 // allocate space for FileEntry
2700 if(!OS_SUCCESS(status
=
2701 UDFBuildFileEntry(Vcb
, DirInfo
, FileInfo
, PartNum
, ICB_FLAG_AD_IN_ICB
, ExtAttrSz
, Extended
) )) {
2703 try_return (status
);
2706 FEicb
.extLength
= LBS
;
2707 ASSERT(FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
);
2708 FEicb
.extLocation
.logicalBlockNum
= UDFPhysLbaToPart(Vcb
, PartNum
, FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
);
2709 FEicb
.extLocation
.partitionReferenceNum
= (uint16
)PartNum
;
2710 RtlZeroMemory(&(FEicb
.impUse
), sizeof(FEicb
.impUse
));
2714 if(!OS_SUCCESS(status
=
2715 UDFBuildFileIdent(Vcb
, _fn
, &FEicb
, ImpUseLen
,
2716 &(FileInfo
->FileIdent
), &(FileInfo
->FileIdentLen
)) ))
2717 try_return (status
);
2720 FileInfo
->FileIdent
= (PFILE_IDENT_DESC
)MyAllocatePoolTag__(NonPagedPool
, DirNdx
->Length
, MEM_FID_TAG
);
2721 if(!(FileInfo
->FileIdent
)) try_return (status
= STATUS_INSUFFICIENT_RESOURCES
);
2722 FileInfo
->FileIdentLen
= DirNdx
->Length
;
2723 if(!OS_SUCCESS(status
= UDFReadExtent(Vcb
, &(DirInfo
->Dloc
->DataLoc
), DirNdx
->Offset
,
2724 DirNdx
->Length
, FALSE
, (int8
*)(FileInfo
->FileIdent
), &ReadBytes
) ))
2725 try_return (status
);
2726 FileInfo
->FileIdent
->fileCharacteristics
= 0;
2727 FileInfo
->FileIdent
->icb
= FEicb
;
2728 ImpUseLen
= FileInfo
->FileIdent
->lengthOfImpUse
;
2729 DirNdx
->FileCharacteristics
= 0;
2731 // init 'parentICBLocation' & so on in FE
2732 ((icbtag
*)(FileInfo
->Dloc
->FileEntry
+1))->parentICBLocation
.logicalBlockNum
=
2733 UDFPhysLbaToPart(Vcb
, PartNum
, DirInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
);
2734 ((icbtag
*)(FileInfo
->Dloc
->FileEntry
+1))->parentICBLocation
.partitionReferenceNum
= (uint16
)PartNum
;
2735 // ((icbtag*)(FileInfo->Dloc->FileEntry+1))->strategyType = 4;
2736 // ((icbtag*)(FileInfo->Dloc->FileEntry+1))->numEntries = 1;
2737 // try to find suitable unused FileIdent in DirIndex
2738 l
= FileInfo
->FileIdentLen
;
2739 if(undel
) goto CrF__2
;
2740 #ifndef UDF_LIMIT_DIR_SIZE
2742 #endif // UDF_LIMIT_DIR_SIZE
2743 // search for suitable unused entry
2744 if(UDFDirIndexInitScan(DirInfo
, &ScanContext
, 2)) {
2745 while((DirNdx
= UDFDirIndexScan(&ScanContext
, NULL
))) {
2746 if((DirNdx
->Length
== l
) && UDFIsDeleted(DirNdx
) &&
2747 !DirNdx
->FileInfo
) {
2748 // free unicode-buffer with old name
2749 if(DirNdx
->FName
.Buffer
) {
2750 MyFreePool__(DirNdx
->FName
.Buffer
);
2751 DirNdx
->FName
.Buffer
= NULL
;
2758 #ifndef UDF_LIMIT_DIR_SIZE
2760 #endif // UDF_LIMIT_DIR_SIZE
2761 i
= UDFDirIndexGetLastIndex(hDirNdx
); // 'i' points beyond EO DirIndex
2762 #ifndef UDF_LIMIT_DIR_SIZE
2764 #endif // UDF_LIMIT_DIR_SIZE
2767 if(!OS_SUCCESS(status
= UDFDirIndexGrow(&(DirInfo
->Dloc
->DirIndex
), 1))) {
2768 try_return (status
);
2771 // init offset of new FileIdent in directory Data extent
2772 hDirNdx
= DirInfo
->Dloc
->DirIndex
;
2774 DirNdx
= UDFDirIndex(hDirNdx
,i
-1);
2775 UDFDirIndex(hDirNdx
,i
)->Offset
= DirNdx
->Offset
+ DirNdx
->Length
;
2776 DirNdx
= UDFDirIndex(hDirNdx
,i
);
2778 DirNdx
= UDFDirIndex(hDirNdx
,i
);
2781 // new terminator is recorded by UDFDirIndexGrow()
2782 if( ((d
= ((LBS
- (DirNdx
->Offset
+ l
+ DirInfo
->Dloc
->DataLoc
.Offset
)) & (LBS
-1) )) < sizeof(FILE_IDENT_DESC
)) &&
2784 // insufficient space at the end of last sector for
2785 // next FileIdent's tag. fill it with ImpUse data
2787 // generally, all data should be DWORD-aligned, but if it is not so
2788 // this opearation will help us to avoid glitches
2789 d
= (d
+3) & ~((uint32
)3);
2792 if(!MyReallocPool__((int8
*)(FileInfo
->FileIdent
), l
,
2793 (int8
**)&(FileInfo
->FileIdent
), (l
+d
+3) & ~((uint32
)(3)) ))
2794 try_return (status
= STATUS_INSUFFICIENT_RESOURCES
);
2796 IUl
= FileInfo
->FileIdent
->lengthOfImpUse
;
2797 FIl
= FileInfo
->FileIdent
->lengthFileIdent
;
2798 // move filename to higher addr
2799 RtlMoveMemory(((int8
*)(FileInfo
->FileIdent
+1))+IUl
+d
,
2800 ((int8
*)(FileInfo
->FileIdent
+1))+IUl
, FIl
);
2801 RtlZeroMemory(((int8
*)(FileInfo
->FileIdent
+1))+IUl
, d
);
2802 FileInfo
->FileIdent
->lengthOfImpUse
+= (uint16
)d
;
2803 FileInfo
->FileIdentLen
= l
;
2807 // clone unicode string
2808 // it **<<MUST>>** be allocated with internal memory manager
2809 DirNdx
->FName
.Buffer
= (PWCHAR
)MyAllocatePoolTag__(UDF_FILENAME_MT
, (DirNdx
->FName
.MaximumLength
= _fn
->Length
+ sizeof(WCHAR
)), MEM_FNAMECPY_TAG
);
2810 DirNdx
->FName
.Length
= _fn
->Length
;
2811 if(!DirNdx
->FName
.Buffer
)
2812 try_return (status
= STATUS_INSUFFICIENT_RESOURCES
);
2813 RtlCopyMemory(DirNdx
->FName
.Buffer
, _fn
->Buffer
, _fn
->Length
);
2814 DirNdx
->FName
.Buffer
[_fn
->Length
/sizeof(WCHAR
)] = 0;
2816 DirNdx
->FI_Flags
|= UDFBuildHashEntry(Vcb
, &(DirNdx
->FName
), &(DirNdx
->hashes
), HASH_ALL
);
2817 // we get here immediately when 'undel' occured
2818 FileInfo
->Index
= i
;
2819 DirNdx
->FI_Flags
|= UDF_FI_FLAG_FI_MODIFIED
;
2820 DirNdx
->FI_Flags
&= ~UDF_FI_FLAG_SYS_ATTR
;
2821 ASSERT(!DirNdx
->FileInfo
);
2822 DirNdx
->FileInfo
= FileInfo
;
2823 DirNdx
->FileEntryLoc
= FEicb
.extLocation
;
2824 // mark file as 'deleted' for now
2825 DirNdx
->FileCharacteristics
= FILE_DELETED
;
2826 FileInfo
->FileIdent
->fileCharacteristics
|= FILE_DELETED