1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 
7 #ifndef __UDF_STRUCT_SUPPORT_H__
8 #define __UDF_STRUCT_SUPPORT_H__
9 
10 #include "ecma_167.h"
11 #include "osta_misc.h"
12 #include "udf_rel.h"
13 #include "wcache.h"
14 
15 // memory re-allocation (returns new buffer size)
16 uint32    UDFMemRealloc(IN int8* OldBuff,     // old buffer
17                        IN uint32 OldLength,   // old buffer size
18                        OUT int8** NewBuff,   // address to store new pointer
19                        IN uint32 NewLength);  // required size
20 // convert offset in extent to Lba & calculate block parameters
21 // it also returns pointer to last valid entry & flags
22 uint32
23 UDFExtentOffsetToLba(IN PVCB Vcb,
24                      IN PEXTENT_AD Extent,   // Extent array
25                      IN int64 Offset,     // offset in extent
26                      OUT uint32* SectorOffset,
27                      OUT PSIZE_T AvailLength, // available data in this block
28                      OUT uint32* Flags,
29                      OUT uint32* Index);
30 
31 // locate frag containing specified Lba in extent
32 ULONG
33 UDFLocateLbaInExtent(
34     IN PVCB Vcb,
35     IN PEXTENT_MAP Extent,   // Extent array
36     IN lba_t lba
37     );
38 
39 // see udf_rel.h
40 //#define LBA_OUT_OF_EXTENT       ((LONG)(-1))
41 //#define LBA_NOT_ALLOCATED       ((LONG)(-2))
42 
43 // read data at any offset from extent
44 OSSTATUS UDFReadExtent(IN PVCB Vcb,
45                        IN PEXTENT_INFO ExtInfo, // Extent array
46                        IN int64 Offset,   // offset in extent
47                        IN SIZE_T Length,
48                        IN BOOLEAN Direct,
49                        OUT int8* Buffer,
50                        OUT PSIZE_T ReadBytes);
51 // builds mapping for specified amount of data at any offset from specified extent.
52 OSSTATUS
53 UDFReadExtentLocation(IN PVCB Vcb,
54                       IN PEXTENT_INFO ExtInfo,      // Extent array
55                       IN int64 Offset,              // offset in extent to start SubExtent from
56                       OUT PEXTENT_MAP* _SubExtInfo, // SubExtent mapping array
57                    IN OUT uint32* _SubExtInfoSz,     // IN:  maximum number fragments to get
58                                                     // OUT: actually obtained fragments
59                       OUT int64* _NextOffset        // offset, caller can start from to continue
60                       );
61 // calculate total length of extent
62 int64 UDFGetExtentLength(IN PEXTENT_MAP Extent);  // Extent array
63 // convert compressed Unicode to standard
64 void
65 __fastcall UDFDecompressUnicode(IN OUT PUNICODE_STRING UName,
66                               IN uint8* CS0,
67                               IN SIZE_T Length,
68                               OUT uint16* valueCRC);
69 // calculate hashes for directory search
70 uint8    UDFBuildHashEntry(IN PVCB Vcb,
71                            IN PUNICODE_STRING Name,
72                           OUT PHASH_ENTRY hashes,
73                            IN uint8 Mask);
74 
75 #define HASH_POSIX 0x01
76 #define HASH_ULFN  0x02
77 #define HASH_DOS   0x04
78 #define HASH_ALL   0x07
79 #define HASH_KEEP_NAME 0x08  // keep DOS '.' and '..' intact
80 
81 // get dirindex's frame
82 PDIR_INDEX_ITEM UDFDirIndexGetFrame(IN PDIR_INDEX_HDR hDirNdx,
83                                     IN uint32 Frame,
84                                    OUT uint32* FrameLen,
85                                    OUT uint_di* Index,
86                                     IN uint_di Rel);
87 // release DirIndex
88 void UDFDirIndexFree(PDIR_INDEX_HDR hDirNdx);
89 // grow DirIndex
90 OSSTATUS UDFDirIndexGrow(IN PDIR_INDEX_HDR* _hDirNdx,
91                          IN uint_di d);
92 // truncate DirIndex
93 OSSTATUS UDFDirIndexTrunc(IN PDIR_INDEX_HDR* _hDirNdx,
94                           IN uint_di d);
95 // init variables for scan (using knowledge about internal structure)
96 BOOLEAN UDFDirIndexInitScan(IN PUDF_FILE_INFO DirInfo,   //
97                            OUT PUDF_DIR_SCAN_CONTEXT Context,
98                             IN uint_di Index);
99 //
100 PDIR_INDEX_ITEM UDFDirIndexScan(PUDF_DIR_SCAN_CONTEXT Context,
101                                 PUDF_FILE_INFO* _FileInfo);
102 // build directory index
103 OSSTATUS UDFIndexDirectory(IN PVCB Vcb,
104                         IN OUT PUDF_FILE_INFO FileInfo);
105 // search for specified file in specified directory &
106 // returns corresponding offset in extent if found.
107 OSSTATUS UDFFindFile(IN PVCB Vcb,
108                      IN BOOLEAN IgnoreCase,
109                      IN BOOLEAN NotDeleted,
110                      IN PUNICODE_STRING Name,
111                      IN PUDF_FILE_INFO DirInfo,
112                   IN OUT uint_di* Index);
113 
UDFFindFile__(IN PVCB Vcb,IN BOOLEAN IgnoreCase,IN PUNICODE_STRING Name,IN PUDF_FILE_INFO DirInfo)114 __inline OSSTATUS UDFFindFile__(IN PVCB Vcb,
115                                 IN BOOLEAN IgnoreCase,
116                                 IN PUNICODE_STRING Name,
117                                 IN PUDF_FILE_INFO DirInfo)
118 {
119     if(!DirInfo->Dloc->DirIndex)
120         return STATUS_NOT_A_DIRECTORY;
121     uint_di i=0;
122     return UDFFindFile(Vcb, IgnoreCase, TRUE, Name, DirInfo, &i);
123 }
124 
125 // calculate file mapping length (in bytes) including ZERO-terminator
126 uint32   UDFGetMappingLength(IN PEXTENT_MAP Extent);
127 // merge 2 sequencial file mappings
128 PEXTENT_MAP
129 __fastcall UDFMergeMappings(IN PEXTENT_MAP Extent,
130                              IN PEXTENT_MAP Extent2);
131 // build file mapping according to ShortAllocDesc (SHORT_AD) array
132 PEXTENT_MAP UDFShortAllocDescToMapping(IN PVCB Vcb,
133                                       IN uint32 PartNum,
134                                       IN PLONG_AD AllocDesc,
135                                       IN uint32 AllocDescLength,
136                                       IN uint32 SubCallCount,
137                                       OUT PEXTENT_INFO AllocLoc);
138 // build file mapping according to LongAllocDesc (LONG_AD) array
139 PEXTENT_MAP UDFLongAllocDescToMapping(IN PVCB Vcb,
140                                       IN PLONG_AD AllocDesc,
141                                       IN uint32 AllocDescLength,
142                                       IN uint32 SubCallCount,
143                                       OUT PEXTENT_INFO AllocLoc);
144 // build file mapping according to ExtendedAllocDesc (EXT_AD) array
145 PEXTENT_MAP UDFExtAllocDescToMapping(IN PVCB Vcb,
146                                       IN PLONG_AD AllocDesc,
147                                       IN uint32 AllocDescLength,
148                                       IN uint32 SubCallCount,
149                                       OUT PEXTENT_INFO AllocLoc);
150 // build file mapping according to (Extended)FileEntry
151 PEXTENT_MAP UDFReadMappingFromXEntry(IN PVCB Vcb,
152                                      IN uint32 PartNum,
153                                      IN tag* XEntry,
154                                      IN OUT uint32* Offset,
155                                      OUT PEXTENT_INFO AllocLoc);
156 // read FileEntry described in FileIdentDesc
157 OSSTATUS UDFReadFileEntry(IN PVCB Vcb,
158 //                          IN PFILE_IDENT_DESC FileDesc,
159                           IN long_ad* Icb,
160                        IN OUT PFILE_ENTRY FileEntry, // here we can also get ExtendedFileEntry
161                        IN OUT uint16* Ident);
162 // scan FileSet sequence & return last valid FileSet
163 OSSTATUS UDFFindLastFileSet(IN PVCB Vcb,
164                             IN lb_addr *Addr,  // Addr for the 1st FileSet
165                             IN OUT PFILE_SET_DESC FileSetDesc);
166 // read all sparing tables & stores them in contiguos memory
167 OSSTATUS UDFLoadSparingTable(IN PVCB Vcb,
168                               IN PSPARABLE_PARTITION_MAP PartMap);
169 // build mapping for extent
170 PEXTENT_MAP
171 __fastcall UDFExtentToMapping_(IN PEXTENT_AD Extent
172 #ifdef UDF_TRACK_EXTENT_TO_MAPPING
173                               ,IN ULONG src,
174                                IN ULONG line
175 #endif //UDF_TRACK_EXTENT_TO_MAPPING
176                               );
177 
178 #ifdef UDF_TRACK_EXTENT_TO_MAPPING
179   #define UDFExtentToMapping(e)  UDFExtentToMapping_(e, UDF_BUG_CHECK_ID, __LINE__)
180 #else //UDF_TRACK_EXTENT_TO_MAPPING
181   #define UDFExtentToMapping(e)  UDFExtentToMapping_(e)
182 #endif //UDF_TRACK_EXTENT_TO_MAPPING
183 
184 //    This routine remaps sectors from bad packet
185 OSSTATUS
186 __fastcall UDFRemapPacket(IN PVCB Vcb,
187                         IN uint32 Lba,
188                         IN BOOLEAN RemapSpared);
189 
190 //    This routine releases sector mapping when entire packet is marked as free
191 OSSTATUS
192 __fastcall UDFUnmapRange(IN PVCB Vcb,
193                         IN uint32 Lba,
194                         IN uint32 BCount);
195 
196 // return physical address for relocated sector
197 uint32
198 __fastcall UDFRelocateSector(IN PVCB Vcb,
199                           IN uint32 Lba);
200 // check
201 BOOLEAN
202 __fastcall UDFAreSectorsRelocated(IN PVCB Vcb,
203                                   IN uint32 Lba,
204                                   IN uint32 BlockCount);
205 // build mapping for relocated extent
206 PEXTENT_MAP
207 __fastcall UDFRelocateSectors(IN PVCB Vcb,
208                                IN uint32 Lba,
209                                IN uint32 BlockCount);
210 // check for presence of given char among specified ones
211 BOOLEAN  UDFUnicodeInString(IN uint8* string,
212                             IN WCHAR ch);     // Unicode char to search for.
213 // validate char
214 BOOLEAN
215 __fastcall UDFIsIllegalChar(IN WCHAR ch);
216 // translate udfName to dosName using OSTA compliant.
217 #define  UDFDOSName__(Vcb, DosName, UdfName, FileInfo) \
218     UDFDOSName(Vcb, DosName, UdfName, (FileInfo) && ((FileInfo)->Index < 2));
219 
220 void
221 __fastcall UDFDOSName(IN PVCB Vcb,
222                     IN OUT PUNICODE_STRING DosName,
223                     IN PUNICODE_STRING UdfName,
224                     IN BOOLEAN KeepIntact);
225 
226 void
227 __fastcall UDFDOSName201(IN OUT PUNICODE_STRING DosName,
228                        IN PUNICODE_STRING UdfName,
229                        IN BOOLEAN KeepIntact);
230 
231 void
232 __fastcall UDFDOSName200(IN OUT PUNICODE_STRING DosName,
233                        IN PUNICODE_STRING UdfName,
234                        IN BOOLEAN KeepIntact,
235                        IN BOOLEAN Mode150);
236 
237 void
238 __fastcall UDFDOSName100(IN OUT PUNICODE_STRING DosName,
239                        IN PUNICODE_STRING UdfName,
240                        IN BOOLEAN KeepIntact);
241 
242 // return length of bit-chain starting from Offs bit
243 #ifdef _X86_
244 SIZE_T
245 __stdcall
246 UDFGetBitmapLen(
247 #else   // NO X86 optimization , use generic C/C++
248 SIZE_T    UDFGetBitmapLen(
249 #endif // _X86_
250                          uint32* Bitmap,
251                          SIZE_T Offs,
252                          SIZE_T Lim);
253 // scan disc free space bitmap for minimal suitable extent
254 SIZE_T    UDFFindMinSuitableExtent(IN PVCB Vcb,
255                                    IN uint32 Length, // in blocks
256                                    IN uint32 SearchStart,
257                                    IN uint32 SearchLim,
258                                    OUT uint32* MaxExtLen,
259                                    IN uint8  AllocFlags);
260 
261 #ifdef UDF_CHECK_DISK_ALLOCATION
262 // mark space described by Mapping as Used/Freed (optionaly)
263 void     UDFCheckSpaceAllocation_(IN PVCB Vcb,
264                                   IN PEXTENT_MAP Map,
265                                   IN uint32 asXXX
266 #ifdef UDF_TRACK_ONDISK_ALLOCATION
267                                  ,IN uint32 FE_lba,
268                                   IN uint32 BugCheckId,
269                                   IN uint32 Line
270 #endif //UDF_TRACK_ONDISK_ALLOCATION
271                                   );
272 
273 #ifdef UDF_TRACK_ONDISK_ALLOCATION
274 #define UDFCheckSpaceAllocation(Vcb, FileInfo, Map, asXXX) \
275     UDFCheckSpaceAllocation_(Vcb, Map, asXXX, (uint32)FileInfo, UDF_BUG_CHECK_ID,__LINE__);
276 #else //UDF_TRACK_ONDISK_ALLOCATION
277 #define UDFCheckSpaceAllocation(Vcb, FileInfo, Map, asXXX) \
278     UDFCheckSpaceAllocation_(Vcb, Map, asXXX);
279 #endif //UDF_TRACK_ONDISK_ALLOCATION
280 #else // UDF_CHECK_DISK_ALLOCATION
281 #define UDFCheckSpaceAllocation(Vcb, FileInfo, Map, asXXX) {;}
282 #endif //UDF_CHECK_DISK_ALLOCATION
283 
284 // mark space described by Mapping as Used/Freed (optionaly)
285 // this routine doesn't acquire any resource
286 void
287 UDFMarkSpaceAsXXXNoProtect_(
288     IN PVCB Vcb,
289     IN PEXTENT_MAP Map,
290     IN uint32 asXXX
291 #ifdef UDF_TRACK_ONDISK_ALLOCATION
292    ,IN uint32 FE_lba,
293     IN uint32 BugCheckId,
294     IN uint32 Line
295 #endif //UDF_TRACK_ONDISK_ALLOCATION
296     );
297 
298 #ifdef UDF_TRACK_ONDISK_ALLOCATION
299 #define UDFMarkSpaceAsXXXNoProtect(Vcb, FileInfo, Map, asXXX) \
300     UDFMarkSpaceAsXXXNoProtect_(Vcb, Map, asXXX, (uint32)FileInfo, UDF_BUG_CHECK_ID,__LINE__);
301 #else //UDF_TRACK_ONDISK_ALLOCATION
302 #define UDFMarkSpaceAsXXXNoProtect(Vcb, FileInfo, Map, asXXX) \
303     UDFMarkSpaceAsXXXNoProtect_(Vcb, Map, asXXX);
304 #endif //UDF_TRACK_ONDISK_ALLOCATION
305 
306 
307 // mark space described by Mapping as Used/Freed (optionaly)
308 void     UDFMarkSpaceAsXXX_(IN PVCB Vcb,
309                             IN PEXTENT_MAP Map,
310                             IN uint32 asXXX
311 #ifdef UDF_TRACK_ONDISK_ALLOCATION
312                            ,IN uint32 FE_lba,
313                             IN uint32 BugCheckId,
314                             IN uint32 Line
315 #endif //UDF_TRACK_ONDISK_ALLOCATION
316                             );
317 
318 #ifdef UDF_TRACK_ONDISK_ALLOCATION
319 #define UDFMarkSpaceAsXXX(Vcb, FileInfo, Map, asXXX) \
320     UDFMarkSpaceAsXXX_(Vcb, Map, asXXX, (uint32)FileInfo, UDF_BUG_CHECK_ID,__LINE__);
321 #else //UDF_TRACK_ONDISK_ALLOCATION
322 #define UDFMarkSpaceAsXXX(Vcb, FileInfo, Map, asXXX) \
323     UDFMarkSpaceAsXXX_(Vcb, Map, asXXX);
324 #endif //UDF_TRACK_ONDISK_ALLOCATION
325 
326 #define AS_FREE         0x00
327 #define AS_USED         0x01
328 #define AS_DISCARDED    0x02
329 #define AS_BAD          0x04
330 
331 // build mapping for Length bytes in FreeSpace
332 OSSTATUS UDFAllocFreeExtent_(IN PVCB Vcb,
333                             IN int64 Length,
334                             IN uint32 SearchStart,
335                             IN uint32 SearchLim,
336                             OUT PEXTENT_INFO Extent,
337                             IN uint8 AllocFlags
338 #ifdef UDF_TRACK_ALLOC_FREE_EXTENT
339                            ,IN uint32 src,
340                             IN uint32 line
341 #endif //UDF_TRACK_ALLOC_FREE_EXTENT
342                             );
343 
344 #ifdef UDF_TRACK_ALLOC_FREE_EXTENT
345 #define UDFAllocFreeExtent(v, l, ss, sl, e, af)  UDFAllocFreeExtent_(v, l, ss, sl, e, af, UDF_BUG_CHECK_ID, __LINE__)
346 #else //UDF_TRACK_ALLOC_FREE_EXTENT
347 #define UDFAllocFreeExtent(v, l, ss, sl, e, af)  UDFAllocFreeExtent_(v, l, ss, sl, e, af)
348 #endif //UDF_TRACK_ALLOC_FREE_EXTENT
349 //
350 
351 uint32 __fastcall
352 UDFGetPartFreeSpace(IN PVCB Vcb,
353                            IN uint32 partNum);
354 
355 #define UDF_PREALLOC_CLASS_FE    0x00
356 #define UDF_PREALLOC_CLASS_DIR   0x01
357 
358 // try to find cached allocation
359 OSSTATUS
360 UDFGetCachedAllocation(
361     IN PVCB Vcb,
362     IN uint32 ParentLocation,
363    OUT PEXTENT_INFO Ext,
364    OUT uint32* Items, // optional
365     IN uint32 AllocClass
366     );
367 // put released pre-allocation to cache
368 OSSTATUS
369 UDFStoreCachedAllocation(
370     IN PVCB Vcb,
371     IN uint32 ParentLocation,
372     IN PEXTENT_INFO Ext,
373     IN uint32 Items,
374     IN uint32 AllocClass
375     );
376 // discard all cached allocations
377 OSSTATUS
378 UDFFlushAllCachedAllocations(
379     IN PVCB Vcb,
380     IN uint32 AllocClass
381     );
382 // allocate space for FE
383 OSSTATUS UDFAllocateFESpace(IN PVCB Vcb,
384                             IN PUDF_FILE_INFO DirInfo,
385                             IN uint32 PartNum,
386                             IN PEXTENT_INFO FEExtInfo,
387                             IN uint32 Len);
388 #ifndef UDF_READ_ONLY_BUILD
389 // free space FE's allocation
390 void UDFFreeFESpace(IN PVCB Vcb,
391                     IN PUDF_FILE_INFO DirInfo,
392                     IN PEXTENT_INFO FEExtInfo);
393 #endif //UDF_READ_ONLY_BUILD
394 
395 #define FLUSH_FE_KEEP       FALSE
396 #define FLUSH_FE_FOR_DEL    TRUE
397 
398 // flush FE charge
399 void UDFFlushFESpace(IN PVCB Vcb,
400                      IN PUDF_DATALOC_INFO Dloc,
401                      IN BOOLEAN Discard = FLUSH_FE_KEEP);
402 // discard file allocation
403 void UDFFreeFileAllocation(IN PVCB Vcb,
404                            IN PUDF_FILE_INFO DirInfo,
405                            IN PUDF_FILE_INFO FileInfo);
406 // convert physical address to logical in specified partition
407 uint32    UDFPhysLbaToPart(IN PVCB Vcb,
408                           IN uint32 PartNum,
409                           IN uint32 Addr);
410 /*#define UDFPhysLbaToPart(Vcb, PartNum, Addr) \
411     ((Addr - Vcb->Partitions[PartNum].PartitionRoot) >> Vcb->LB2B_Bits)*/
412 // initialize Tag structure.
413 void     UDFSetUpTag(IN PVCB Vcb,
414                      IN tag* Tag,
415                      IN uint16 DataLen,
416                      IN uint32 TagLoc);
417 // build content for AllocDesc sequence for specified extent
418 OSSTATUS UDFBuildShortAllocDescs(IN PVCB Vcb,
419                                  IN uint32 PartNum,
420                                  OUT int8** Buff,  // data for AllocLoc
421                                  IN uint32 InitSz,
422                               IN OUT PUDF_FILE_INFO FileInfo);
423 // build data for AllocDesc sequence for specified
424 OSSTATUS UDFBuildLongAllocDescs(IN PVCB Vcb,
425                                 IN uint32 PartNum,
426                                 OUT int8** Buff,  // data for AllocLoc
427                                 IN uint32 InitSz,
428                              IN OUT PUDF_FILE_INFO FileInfo);
429 // builds FileEntry & associated AllocDescs for specified extent.
430 OSSTATUS UDFBuildFileEntry(IN PVCB Vcb,
431                            IN PUDF_FILE_INFO DirInfo,
432                            IN PUDF_FILE_INFO FileInfo,
433                            IN uint32 PartNum,
434                            IN uint16 AllocMode, // short/long/ext/in-icb
435                            IN uint32 ExtAttrSz,
436                            IN BOOLEAN Extended/*,
437                            OUT PFILE_ENTRY* FEBuff,
438                            OUT uint32* FELen,
439                            OUT PEXTENT_INFO FEExtInfo*/);
440 // find partition containing given physical sector
441 uint32
442 __fastcall UDFGetPartNumByPhysLba(IN PVCB Vcb,
443                                 IN uint32 Lba);
444 // add given bitmap to existing one
445 #define UDF_FSPACE_BM    0x00
446 #define UDF_ZSPACE_BM    0x01
447 
448 OSSTATUS UDFAddXSpaceBitmap(IN PVCB Vcb,
449                             IN uint32 PartNum,
450                             IN PSHORT_AD bm,
451                             IN ULONG bm_type);
452 // subtract given Bitmap to existing one
453 OSSTATUS UDFDelXSpaceBitmap(IN PVCB Vcb,
454                             IN uint32 PartNum,
455                             IN PSHORT_AD bm);
456 // build FreeSpaceBitmap (internal) according to media parameters & input data
457 OSSTATUS UDFBuildFreeSpaceBitmap(IN PVCB Vcb,
458                                 IN uint32 PartNdx,
459                                 IN PPARTITION_HEADER_DESC phd,
460                                 IN uint32 Lba);
461 // fill ExtentInfo for specified FileEntry
462 OSSTATUS UDFLoadExtInfo(IN PVCB Vcb,
463                         IN PFILE_ENTRY fe,
464                         IN PLONG_AD fe_loc,
465                         IN OUT PEXTENT_INFO FExtInfo,
466                         IN OUT PEXTENT_INFO AExtInfo);
467 // convert standard Unicode to compressed
468 void
469 __fastcall UDFCompressUnicode(IN PUNICODE_STRING UName,
470                             IN OUT uint8** _CS0,
471                             IN OUT PSIZE_T Length);
472 // build FileIdent for specified FileEntry.
473 OSSTATUS UDFBuildFileIdent(IN PVCB Vcb,
474                            IN PUNICODE_STRING fn,
475                            IN PLONG_AD FileEntryIcb,       // virtual address of FileEntry
476                            IN uint32 ImpUseLen,
477                            OUT PFILE_IDENT_DESC* _FileId,
478                            OUT uint32* FileIdLen);
479 // rebuild mapping on write attempts to Alloc-Not-Rec area.
480 OSSTATUS UDFMarkAllocatedAsRecorded(IN PVCB Vcb,
481                                     IN int64 Offset,
482                                     IN uint32 Length,
483                                     IN PEXTENT_INFO ExtInfo);   // Extent array
484 // rebuild mapping on write attempts to Not-Alloc-Not-Rec area
485 OSSTATUS UDFMarkNotAllocatedAsAllocated(IN PVCB Vcb,
486                                         IN int64 Offset,
487                                         IN uint32 Length,
488                                         IN PEXTENT_INFO ExtInfo);   // Extent array
489 OSSTATUS UDFMarkAllocatedAsNotXXX(IN PVCB Vcb,
490                                   IN int64 Offset,
491                                   IN uint32 Length,
492                                   IN PEXTENT_INFO ExtInfo,   // Extent array
493                                   IN BOOLEAN Deallocate);
494 #ifdef DBG
UDFMarkAllocatedAsNotAllocated(IN PVCB Vcb,IN int64 Offset,IN uint32 Length,IN PEXTENT_INFO ExtInfo)495 __inline OSSTATUS UDFMarkAllocatedAsNotAllocated(IN PVCB Vcb,
496                                   IN int64 Offset,
497                                   IN uint32 Length,
498                                   IN PEXTENT_INFO ExtInfo)
499 {
500     return UDFMarkAllocatedAsNotXXX(Vcb, Offset, Length, ExtInfo, TRUE);
501 }
502 #else
503 #define UDFMarkAllocatedAsNotAllocated(Vcb, Off, Len, Ext) \
504     UDFMarkAllocatedAsNotXXX(Vcb, Off, Len, Ext, TRUE)
505 #endif //DBG
506 
507 #ifdef DBG
UDFMarkRecordedAsAllocated(IN PVCB Vcb,IN int64 Offset,IN uint32 Length,IN PEXTENT_INFO ExtInfo)508 __inline OSSTATUS UDFMarkRecordedAsAllocated(IN PVCB Vcb,
509                                   IN int64 Offset,
510                                   IN uint32 Length,
511                                   IN PEXTENT_INFO ExtInfo)
512 {
513     return UDFMarkAllocatedAsNotXXX(Vcb, Offset, Length, ExtInfo, FALSE);
514 }
515 #else
516 #define UDFMarkRecordedAsAllocated(Vcb, Off, Len, Ext) \
517     UDFMarkAllocatedAsNotXXX(Vcb, Off, Len, Ext, FALSE)
518 #endif //DBG
519 // write data at any offset from specified extent.
520 OSSTATUS UDFWriteExtent(IN PVCB Vcb,
521                         IN PEXTENT_INFO ExtInfo,   // Extent array
522                         IN int64 Offset,           // offset in extent
523                         IN SIZE_T Length,
524                         IN BOOLEAN Direct,         // setting this flag delays flushing of given
525                                                    // data to indefinite term
526                         IN int8* Buffer,
527                         OUT PSIZE_T WrittenBytes);
528 
529 // deallocate/zero data at any offset from specified extent.
530 OSSTATUS UDFZeroExtent(IN PVCB Vcb,
531                        IN PEXTENT_INFO ExtInfo,   // Extent array
532                        IN int64 Offset,           // offset in extent
533                        IN SIZE_T Length,
534                        IN BOOLEAN Deallocate,     // deallocate frag or just mark as unrecorded
535                        IN BOOLEAN Direct,         // setting this flag delays flushing of given
536                                                   // data to indefinite term
537                        OUT PSIZE_T WrittenBytes);
538 
539 #define UDFZeroExtent__(Vcb, Ext, Off, Len, Dir, WB) \
540   UDFZeroExtent(Vcb, Ext, Off, Len, FALSE, Dir, WB)
541 
542 #define UDFSparseExtent__(Vcb, Ext, Off, Len, Dir, WB) \
543   UDFZeroExtent(Vcb, Ext, Off, Len, TRUE, Dir, WB)
544 
545 uint32
546 __fastcall UDFPartStart(PVCB Vcb,
547                         uint32 PartNum);
548 uint32
549 __fastcall UDFPartEnd(PVCB Vcb,
550                       uint32 PartNum);
551 // resize extent & associated mapping
552 OSSTATUS UDFResizeExtent(IN PVCB Vcb,
553                          IN uint32 PartNum,
554                          IN int64 Length,
555                          IN BOOLEAN AlwaysInIcb,   // must be TRUE for AllocDescs
556                          OUT PEXTENT_INFO ExtInfo);
557 // (re)build AllocDescs data  & resize associated extent
558 OSSTATUS UDFBuildAllocDescs(IN PVCB Vcb,
559                             IN uint32 PartNum,
560                          IN OUT PUDF_FILE_INFO FileInfo,
561                             OUT int8** AllocData);
562 // set informationLength field in (Ext)FileEntry
563 void     UDFSetFileSize(IN PUDF_FILE_INFO FileInfo,
564                         IN int64 Size);
565 // sync cached FileSize from DirNdx and actual FileSize from FE
566 void     UDFSetFileSizeInDirNdx(IN PVCB Vcb,
567                                 IN PUDF_FILE_INFO FileInfo,
568                                 IN int64* ASize);
569 // get informationLength field in (Ext)FileEntry
570 int64 UDFGetFileSize(IN PUDF_FILE_INFO FileInfo);
571 //
572 int64 UDFGetFileSizeFromDirNdx(IN PVCB Vcb,
573                                   IN PUDF_FILE_INFO FileInfo);
574 // set lengthAllocDesc field in (Ext)FileEntry
575 void     UDFSetAllocDescLen(IN PVCB Vcb,
576                             IN PUDF_FILE_INFO FileInfo);
577 // change fileLinkCount field in (Ext)FileEntry
578 void     UDFChangeFileLinkCount(IN PUDF_FILE_INFO FileInfo,
579                                 IN BOOLEAN Increase);
580 #define  UDFIncFileLinkCount(fi)  UDFChangeFileLinkCount(fi, TRUE)
581 #define  UDFDecFileLinkCount(fi)  UDFChangeFileLinkCount(fi, FALSE)
582 // ee
583 void     UDFSetEntityID_imp_(IN EntityID* eID,
584                              IN uint8* Str,
585                              IN uint32 Len);
586 
587 // get fileLinkCount field from (Ext)FileEntry
588 uint16   UDFGetFileLinkCount(IN PUDF_FILE_INFO FileInfo);
589 #ifdef UDF_CHECK_UTIL
590 // set fileLinkCount field in (Ext)FileEntry
591 void
592 UDFSetFileLinkCount(
593     IN PUDF_FILE_INFO FileInfo,
594     uint16 LinkCount
595     );
596 #endif //UDF_CHECK_UTIL
597 
598 #define  UDFSetEntityID_imp(eID, Str) \
599     UDFSetEntityID_imp_(eID, (uint8*)(Str), sizeof(Str));
600 //
601 void     UDFReadEntityID_Domain(PVCB Vcb,
602                                 EntityID* eID);
603 // get lengthExtendedAttr field in (Ext)FileEntry
604 uint32    UDFGetFileEALength(IN PUDF_FILE_INFO FileInfo);
605 // set UniqueID field in (Ext)FileEntry
606 void     UDFSetFileUID(IN PVCB Vcb,
607                        IN PUDF_FILE_INFO FileInfo);
608 // get UniqueID field in (Ext)FileEntry
609 int64 UDFGetFileUID(IN PUDF_FILE_INFO FileInfo);
610 // change counters in LVID
611 void  UDFChangeFileCounter(IN PVCB Vcb,
612                            IN BOOLEAN FileCounter,
613                            IN BOOLEAN Increase);
614 #define UDFIncFileCounter(Vcb) UDFChangeFileCounter(Vcb, TRUE, TRUE);
615 #define UDFDecFileCounter(Vcb) UDFChangeFileCounter(Vcb, TRUE, FALSE);
616 #define UDFIncDirCounter(Vcb)  UDFChangeFileCounter(Vcb, FALSE, TRUE);
617 #define UDFDecDirCounter(Vcb)  UDFChangeFileCounter(Vcb, FALSE, FALSE);
618 // write to file
619 OSSTATUS UDFWriteFile__(IN PVCB Vcb,
620                         IN PUDF_FILE_INFO FileInfo,
621                         IN int64 Offset,
622                         IN SIZE_T Length,
623                         IN BOOLEAN Direct,
624                         IN int8* Buffer,
625                         OUT PSIZE_T WrittenBytes);
626 // mark file as deleted & decrease file link counter.
627 OSSTATUS UDFUnlinkFile__(IN PVCB Vcb,
628                          IN PUDF_FILE_INFO FileInfo,
629                          IN BOOLEAN FreeSpace);
630 // delete all files in directory (FreeSpace = TRUE)
631 OSSTATUS UDFUnlinkAllFilesInDir(IN PVCB Vcb,
632                                 IN PUDF_FILE_INFO DirInfo);
633 // init UDF_FILE_INFO structure for specifiend file
634 OSSTATUS UDFOpenFile__(IN PVCB Vcb,
635                        IN BOOLEAN IgnoreCase,
636                        IN BOOLEAN NotDeleted,
637                        IN PUNICODE_STRING fn,
638                        IN PUDF_FILE_INFO DirInfo,
639                        OUT PUDF_FILE_INFO* _FileInfo,
640                        IN uint_di* IndexToOpen);
641 // init UDF_FILE_INFO structure for root directory
642 OSSTATUS UDFOpenRootFile__(IN PVCB Vcb,
643                           IN lb_addr* RootLoc,
644                           OUT PUDF_FILE_INFO FileInfo);
645 // free all memory blocks referenced by given FileInfo
646 uint32    UDFCleanUpFile__(IN PVCB Vcb,
647                           IN PUDF_FILE_INFO FileInfo);
648 #define  UDF_FREE_NOTHING     0x00
649 #define  UDF_FREE_FILEINFO    0x01
650 #define  UDF_FREE_DLOC        0x02
651 // create zero-sized file
652 OSSTATUS UDFCreateFile__(IN PVCB Vcb,
653                          IN BOOLEAN IgnoreCase,
654                          IN PUNICODE_STRING fn,
655                          IN uint32 ExtAttrSz,
656                          IN uint32 ImpUseLen,
657                          IN BOOLEAN Extended,
658                          IN BOOLEAN CreateNew,
659                       IN OUT PUDF_FILE_INFO DirInfo,
660                          OUT PUDF_FILE_INFO* _FileInfo);
661 // read data from file described with FileInfo
662 /*
663     This routine reads data from file described by FileInfo
664  */
665 __inline
UDFReadFile__(IN PVCB Vcb,IN PUDF_FILE_INFO FileInfo,IN int64 Offset,IN SIZE_T Length,IN BOOLEAN Direct,OUT int8 * Buffer,OUT PSIZE_T ReadBytes)666 OSSTATUS UDFReadFile__(IN PVCB Vcb,
667                        IN PUDF_FILE_INFO FileInfo,
668                        IN int64 Offset,   // offset in extent
669                        IN SIZE_T Length,
670                        IN BOOLEAN Direct,
671                        OUT int8* Buffer,
672                        OUT PSIZE_T ReadBytes)
673 {
674     ValidateFileInfo(FileInfo);
675 
676     return UDFReadExtent(Vcb, &(FileInfo->Dloc->DataLoc), Offset, Length, Direct, Buffer, ReadBytes);
677 } // end UDFReadFile__()*/
678 
679 /*
680     This routine reads data from file described by FileInfo
681  */
682 __inline
UDFReadFileLocation__(IN PVCB Vcb,IN PUDF_FILE_INFO FileInfo,IN int64 Offset,OUT PEXTENT_MAP * SubExtInfo,IN OUT uint32 * SubExtInfoSz,OUT int64 * NextOffset)683 OSSTATUS UDFReadFileLocation__(IN PVCB Vcb,
684                                IN PUDF_FILE_INFO FileInfo,
685                                IN int64 Offset,              // offset in extent to start SubExtent from
686                                OUT PEXTENT_MAP* SubExtInfo,  // SubExtent mapping array
687                             IN OUT uint32* SubExtInfoSz,      // IN:  maximum number fragments to get
688                                                              // OUT: actually obtained fragments
689                                OUT int64* NextOffset         // offset, caller can start from to continue
690                                )
691 {
692     ValidateFileInfo(FileInfo);
693 
694     return UDFReadExtentLocation(Vcb, &(FileInfo->Dloc->DataLoc), Offset, SubExtInfo, SubExtInfoSz, NextOffset);
695 } // end UDFReadFile__()*/
696 
697 /*
698 #define UDFReadFile__(Vcb, FileInfo, Offset, Length, Direct, Buffer, ReadBytes)  \
699     (UDFReadExtent(Vcb, &((FileInfo)->Dloc->DataLoc), Offset, Length, Direct, Buffer, ReadBytes))
700 */
701 
702 // zero data in file described by FileInfo
703 __inline
704 OSSTATUS UDFZeroFile__(IN PVCB Vcb,
705                        IN PUDF_FILE_INFO FileInfo,
706                        IN int64 Offset,   // offset in extent
707                        IN uint32 Length,
708                        IN BOOLEAN Direct,
709                        OUT uint32* ReadBytes);
710 // make sparse area in file described by FileInfo
711 __inline
712 OSSTATUS UDFSparseFile__(IN PVCB Vcb,
713                          IN PUDF_FILE_INFO FileInfo,
714                          IN int64 Offset,   // offset in extent
715                          IN uint32 Length,
716                          IN BOOLEAN Direct,
717                          OUT uint32* ReadBytes);
718 // pad sector tail with zeros
719 OSSTATUS UDFPadLastSector(IN PVCB Vcb,
720                           IN PEXTENT_INFO ExtInfo);
721 // update AllocDesc sequence, FileIdent & FileEntry
722 OSSTATUS UDFCloseFile__(IN PVCB Vcb,
723                         IN PUDF_FILE_INFO FileInfo);
724 // load specified bitmap.
725 OSSTATUS UDFPrepareXSpaceBitmap(IN PVCB Vcb,
726                              IN OUT PSHORT_AD XSpaceBitmap,
727                              IN OUT PEXTENT_INFO XSBMExtInfo,
728                              IN OUT int8** XSBM,
729                              IN OUT uint32* XSl);
730 // update Freed & Unallocated space bitmaps
731 OSSTATUS UDFUpdateXSpaceBitmaps(IN PVCB Vcb,
732                                 IN uint32 PartNum,
733                                 IN PPARTITION_HEADER_DESC phd); // partition header pointing to Bitmaps
734 // update Partition Desc & associated data structures
735 OSSTATUS UDFUpdatePartDesc(PVCB Vcb,
736                            int8* Buf);
737 // update Logical volume integrity descriptor
738 OSSTATUS UDFUpdateLogicalVolInt(PVCB            Vcb,
739                                 BOOLEAN         Close);
740 // blank Unalloc Space Desc
741 OSSTATUS UDFUpdateUSpaceDesc(IN PVCB Vcb,
742                              int8* Buf);
743 // update Volume Descriptor Sequence
744 OSSTATUS UDFUpdateVDS(IN PVCB Vcb,
745                       IN uint32 block,
746                       IN uint32 lastblock,
747                       IN uint32 flags);
748 // rebuild & flushes all system areas
749 OSSTATUS UDFUmount__(IN PVCB Vcb);
750 // move file from DirInfo1 to DirInfo2 & renames it to fn
751 OSSTATUS UDFRenameMoveFile__(IN PVCB Vcb,
752                              IN BOOLEAN IgnoreCase,
753                           IN OUT BOOLEAN* Replace,   // replace if destination file exists
754                              IN PUNICODE_STRING fn,  // destination
755                          //    IN uint32 ExtAttrSz,
756                           IN OUT PUDF_FILE_INFO DirInfo1,
757                           IN OUT PUDF_FILE_INFO DirInfo2,
758                           IN OUT PUDF_FILE_INFO FileInfo); // source (opened)
759 // change file size (on disc)
760 OSSTATUS UDFResizeFile__(IN PVCB Vcb,
761                       IN OUT PUDF_FILE_INFO FileInfo,
762                          IN int64 NewLength);
763 // transform zero-sized file to directory
764 OSSTATUS UDFRecordDirectory__(IN PVCB Vcb,
765                            IN OUT PUDF_FILE_INFO DirInfo); // source (opened)
766 // remove all DELETED entries from Dir & resize it.
767 #ifndef UDF_READ_ONLY_BUILD
768 OSSTATUS UDFPackDirectory__(IN PVCB Vcb,
769                          IN OUT PUDF_FILE_INFO FileInfo);   // source (opened)
770 // rebuild tags for all entries from Dir.
771 OSSTATUS
772 UDFReTagDirectory(IN PVCB Vcb,
773                   IN OUT PUDF_FILE_INFO FileInfo);   // source (opened)
774 #endif //UDF_READ_ONLY_BUILD
775 // load VAT.
776 OSSTATUS UDFLoadVAT(IN PVCB Vcb,
777                      IN uint32 PartNdx);
778 // get volume free space
779 int64
780 __fastcall UDFGetFreeSpace(IN PVCB Vcb);
781 // get volume total space
782 int64
783 __fastcall UDFGetTotalSpace(IN PVCB Vcb);
784 // get DirIndex for specified FileInfo
785 PDIR_INDEX_HDR UDFGetDirIndexByFileInfo(IN PUDF_FILE_INFO FileInfo);
786 // check if the file has been found is deleted
787 /*BOOLEAN  UDFIsDeleted(IN PDIR_INDEX_ITEM DirNdx);*/
788 #define UDFIsDeleted(DirNdx) \
789     (((DirNdx)->FileCharacteristics & FILE_DELETED) ? TRUE : FALSE)
790 // check Directory flag
791 /*BOOLEAN  UDFIsADirectory(IN PUDF_FILE_INFO FileInfo);*/
792 #define UDFIsADirectory(FileInfo) \
793     (((FileInfo) && ((FileInfo)->Dloc) && ((FileInfo)->Dloc->DirIndex || ((FileInfo)->FileIdent && ((FileInfo)->FileIdent->fileCharacteristics & FILE_DIRECTORY)))) ? TRUE : FALSE)
794 // calculate actual allocation size
795 /*int64 UDFGetFileAllocationSize(IN PVCB Vcb,
796                                   IN PUDF_FILE_INFO FileInfo);*/
797 #define UDFGetFileAllocationSize(Vcb, FileInfo)  \
798     (((FileInfo)->Dloc->DataLoc.Mapping) ? UDFGetExtentLength((FileInfo)->Dloc->DataLoc.Mapping) : Vcb->LBlockSize)
799 // check if the directory is empty
800 BOOLEAN  UDFIsDirEmpty(IN PDIR_INDEX_HDR hCurDirNdx);
801 // flush FE
802 OSSTATUS UDFFlushFE(IN PVCB Vcb,
803                     IN PUDF_FILE_INFO FileInfo,
804                     IN uint32 PartNum);
805 // flush FI
806 OSSTATUS UDFFlushFI(IN PVCB Vcb,
807                     IN PUDF_FILE_INFO FileInfo,
808                     IN uint32 PartNum);
809 // flush all metadata & update counters
810 OSSTATUS UDFFlushFile__(IN PVCB Vcb,
811                         IN PUDF_FILE_INFO FileInfo,
812                         IN ULONG FlushFlags = 0);
813 // check if the file is flushed
814 #define UDFIsFlushed(FI) \
815     (   FI &&                    \
816       !(FI->Dloc->FE_Flags & UDF_FE_FLAG_FE_MODIFIED) &&      \
817       !(FI->Dloc->DataLoc.Modified) && \
818       !(FI->Dloc->AllocLoc.Modified) &&\
819       !(FI->Dloc->FELoc.Modified) &&   \
820       !(UDFGetDirIndexByFileInfo(FI)[FI->Index].FI_Flags & UDF_FI_FLAG_FI_MODIFIED) )
821 // compare opened directories
822 BOOLEAN  UDFCompareFileInfo(IN PUDF_FILE_INFO f1,
823                            IN PUDF_FILE_INFO f2);
824 // pack mappings
825 void
826 __fastcall UDFPackMapping(IN PVCB Vcb,
827                         IN PEXTENT_INFO ExtInfo);   // Extent array
828 // check if all the data is in cache.
829 BOOLEAN  UDFIsExtentCached(IN PVCB Vcb,
830                            IN PEXTENT_INFO ExtInfo, // Extent array
831                            IN int64 Offset,      // offset in extent
832                            IN uint32 Length,
833                            IN BOOLEAN ForWrite);
834 /*BOOLEAN  UDFIsFileCached__(IN PVCB Vcb,
835                        IN PUDF_FILE_INFO FileInfo,
836                        IN int64 Offset,   // offset in extent
837                        IN uint32 Length,
838                        IN BOOLEAN ForWrite);*/
839 #define UDFIsFileCached__(Vcb, FileInfo, Offset, Length, ForWrite)  \
840     (UDFIsExtentCached(Vcb, &((FileInfo)->Dloc->DataLoc), Offset, Length, ForWrite))
841 // check if specified sector belongs to a file
842 ULONG  UDFIsBlockAllocated(IN void* _Vcb,
843                            IN uint32 Lba);
844 // record VolIdent
845 OSSTATUS UDFUpdateVolIdent(IN PVCB Vcb,
846                            IN UDF_VDS_RECORD Lba,
847                            IN PUNICODE_STRING VolIdent);
848 // calculate checksum for unicode string (for DOS-names)
849 uint16
850 __fastcall UDFUnicodeCksum(PWCHAR s,
851                          uint32 n);
852 //#define UDFUnicodeCksum(s,n)  UDFCrc((uint8*)(s), (n)*sizeof(WCHAR))
853 //
854 uint16
855 __fastcall
856 UDFUnicodeCksum150(PWCHAR s,
857                 uint32 n);
858 
859 uint32
860 __fastcall crc32(IN uint8* s,
861             IN uint32 len);
862 // calculate a 16-bit CRC checksum using ITU-T V.41 polynomial
863 uint16
864 __fastcall UDFCrc(IN uint8* Data,
865                 IN SIZE_T Size);
866 // read the first block of a tagged descriptor & check it
867 OSSTATUS UDFReadTagged(IN PVCB Vcb,
868                        IN int8* Buf,
869                        IN uint32 Block,
870                        IN uint32 Location,
871                        OUT uint16 *Ident);
872 // get physycal Lba for partition-relative addr
873 uint32
874 __fastcall UDFPartLbaToPhys(IN PVCB Vcb,
875                             IN lb_addr* Addr);
876 // look for Anchor(s) at all possible locations
877 lba_t  UDFFindAnchor(PVCB           Vcb);         // Volume control block
878 // look for Volume recognition sequence
879 uint32    UDFFindVRS(PVCB           Vcb);
880 // process Primary volume descriptor
881 void     UDFLoadPVolDesc(PVCB Vcb,
882                          int8* Buf); // pointer to buffer containing PVD
883 //
884 #define UDFGetLVIDiUse(Vcb) \
885     ( ((Vcb) && (Vcb)->LVid) ? \
886         ( (LogicalVolIntegrityDescImpUse*) \
887                      ( ((int8*)(Vcb->LVid+1)) + \
888                        Vcb->LVid->numOfPartitions*2*sizeof(uint32))) \
889        : NULL)
890 
891 // load Logical volume integrity descriptor
892 OSSTATUS UDFLoadLogicalVolInt(PDEVICE_OBJECT DeviceObject,
893                               PVCB           Vcb,
894                               extent_ad      loc);
895 // load Logical volume descriptor
896 OSSTATUS UDFLoadLogicalVol(PDEVICE_OBJECT DeviceObject,
897                            PVCB           Vcb,
898                            int8*          Buf,
899                            lb_addr        *fileset);
900 // process Partition descriptor
901 OSSTATUS UDFLoadPartDesc(PVCB      Vcb,
902                          int8*     Buf);
903 // scan VDS & fill special array
904 OSSTATUS UDFReadVDS(IN PVCB Vcb,
905                     IN uint32 block,
906                     IN uint32 lastblock,
907                     IN PUDF_VDS_RECORD vds,
908                     IN int8* Buf);
909 // process a main/reserve volume descriptor sequence.
910 OSSTATUS UDFProcessSequence(IN PDEVICE_OBJECT DeviceObject,
911                             IN PVCB           Vcb,
912                             IN uint32          block,
913                             IN uint32          lastblock,
914                            OUT lb_addr        *fileset);
915 // Verifies a main/reserve volume descriptor sequence.
916 OSSTATUS UDFVerifySequence(IN PDEVICE_OBJECT    DeviceObject,
917                            IN PVCB              Vcb,
918                            IN uint32             block,
919                            IN uint32             lastblock,
920                           OUT lb_addr           *fileset);
921 // remember some useful info about FileSet & RootDir location
922 void     UDFLoadFileset(IN PVCB            Vcb,
923                         IN PFILE_SET_DESC  fset,
924                        OUT lb_addr         *root,
925                        OUT lb_addr         *sysstream);
926 // load partition info
927 OSSTATUS UDFLoadPartition(IN PDEVICE_OBJECT  DeviceObject,
928                           IN PVCB            Vcb,
929                          OUT lb_addr         *fileset);
930 // check if this is an UDF-formatted disk
931 OSSTATUS UDFGetDiskInfoAndVerify(IN PDEVICE_OBJECT DeviceObject, // the target device object
932                                  IN PVCB           Vcb);         // Volume control block from this DevObj
933 // create hard link for the file
934 OSSTATUS UDFHardLinkFile__(IN PVCB Vcb,
935                            IN BOOLEAN IgnoreCase,
936                         IN OUT BOOLEAN* Replace,      // replace if destination file exists
937                            IN PUNICODE_STRING fn,     // destination
938                         IN OUT PUDF_FILE_INFO DirInfo1,
939                         IN OUT PUDF_FILE_INFO DirInfo2,
940                         IN OUT PUDF_FILE_INFO FileInfo);  // source (opened)
941 //
942 LONG     UDFFindDloc(IN PVCB Vcb,
943                      IN uint32 Lba);
944 //
945 LONG     UDFFindFreeDloc(IN PVCB Vcb,
946                          IN uint32 Lba);
947 //
948 OSSTATUS UDFAcquireDloc(IN PVCB Vcb,
949                         IN PUDF_DATALOC_INFO Dloc);
950 //
951 OSSTATUS UDFReleaseDloc(IN PVCB Vcb,
952                         IN PUDF_DATALOC_INFO Dloc);
953 //
954 OSSTATUS UDFStoreDloc(IN PVCB Vcb,
955                       IN PUDF_FILE_INFO fi,
956                       IN uint32 Lba);
957 //
958 OSSTATUS UDFRemoveDloc(IN PVCB Vcb,
959                        IN PUDF_DATALOC_INFO Dloc);
960 //
961 OSSTATUS UDFUnlinkDloc(IN PVCB Vcb,
962                        IN PUDF_DATALOC_INFO Dloc);
963 //
964 void     UDFFreeDloc(IN PVCB Vcb,
965                      IN PUDF_DATALOC_INFO Dloc);
966 //
967 void     UDFRelocateDloc(IN PVCB Vcb,
968                          IN PUDF_DATALOC_INFO Dloc,
969                          IN uint32 NewLba);
970 //
971 void     UDFReleaseDlocList(IN PVCB Vcb);
972 //
973 PUDF_FILE_INFO UDFLocateParallelFI(PUDF_FILE_INFO di,  // parent FileInfo
974                                    uint_di i,            // Index
975                                    PUDF_FILE_INFO fi);
976 //
977 PUDF_FILE_INFO UDFLocateAnyParallelFI(PUDF_FILE_INFO fi);   // FileInfo to start search from
978 //
979 void UDFInsertLinkedFile(PUDF_FILE_INFO fi,   // FileInfo to be added to chain
980                          PUDF_FILE_INFO fi2);   // any FileInfo fro the chain
981 //
982 OSSTATUS UDFCreateRootFile__(IN PVCB Vcb,
983                          //    IN uint16 AllocMode, // short/long/ext/in-icb  // always in-ICB
984                              IN uint32 PartNum,
985                              IN uint32 ExtAttrSz,
986                              IN uint32 ImpUseLen,
987                              IN BOOLEAN Extended,
988                              OUT PUDF_FILE_INFO* _FileInfo);
989 // try to create StreamDirectory associated with given file
990 OSSTATUS UDFCreateStreamDir__(IN PVCB Vcb,
991                               IN PUDF_FILE_INFO FileInfo,    // file containing stream-dir
992                               OUT PUDF_FILE_INFO* _SDirInfo);
993 //
994 OSSTATUS UDFOpenStreamDir__(IN PVCB Vcb,
995                             IN PUDF_FILE_INFO FileInfo,    // file containing stream-dir
996                             OUT PUDF_FILE_INFO* _SDirInfo);
997 //
998 #define UDFIsAStreamDir(FI)  ((FI) && ((FI)->Dloc) && ((FI)->Dloc->FE_Flags & UDF_FE_FLAG_IS_SDIR))
999 //
1000 #define UDFHasAStreamDir(FI)  ((FI) && ((FI)->Dloc) && ((FI)->Dloc->FE_Flags & UDF_FE_FLAG_HAS_SDIR))
1001 //
1002 #define UDFIsAStream(FI)  ((FI) && UDFIsAStreamDir((FI)->ParentFile))
1003 //
1004 #define UDFIsSDirDeleted(FI)  ((FI) && (FI)->Dloc && ((FI)->Dloc->FE_Flags & UDF_FE_FLAG_IS_DEL_SDIR))
1005 // Record updated VAT (if updated)
1006 OSSTATUS UDFRecordVAT(IN PVCB Vcb);
1007 //
1008 OSSTATUS UDFModifyVAT(IN PVCB Vcb,
1009                       IN uint32 Lba,
1010                       IN uint32 Length);
1011 //
1012 OSSTATUS UDFUpdateVAT(IN void* _Vcb,
1013                       IN uint32 Lba,
1014                       IN uint32* RelocTab,
1015                       IN uint32 BCount);
1016 //
1017 OSSTATUS
1018 __fastcall UDFUnPackMapping(IN PVCB Vcb,
1019                           IN PEXTENT_INFO ExtInfo);   // Extent array
1020 //
1021 OSSTATUS UDFConvertFEToNonInICB(IN PVCB Vcb,
1022                                 IN PUDF_FILE_INFO FileInfo,
1023                                 IN uint8 NewAllocMode);
1024 //
1025 OSSTATUS UDFConvertFEToExtended(IN PVCB Vcb,
1026                                 IN PUDF_FILE_INFO FileInfo);
1027 //
1028 #define UDFGetPartNumByPartNdx(Vcb, pi) (Vcb->Partitions[pi].PartitionNum)
1029 //
1030 uint32
1031 __fastcall UDFPartLen(PVCB Vcb,
1032                       uint32 PartNum);
1033 //
1034 OSSTATUS UDFPretendFileDeleted__(IN PVCB Vcb,
1035                                  IN PUDF_FILE_INFO FileInfo);
1036 
1037 #define UDFStreamsSupported(Vcb) \
1038     (Vcb->maxUDFWriteRev >= 0x0200)
1039 
1040 #define UDFNtAclSupported(Vcb) \
1041     (Vcb->maxUDFWriteRev >= 0x0200)
1042 
1043 #define UDFReferenceFile__(fi)                       \
1044 {                                                    \
1045     UDFInterlockedIncrement((PLONG)&((fi)->RefCount));  \
1046     UDFInterlockedIncrement((PLONG)&((fi)->Dloc->LinkRefCount));  \
1047     if((fi)->ParentFile) {                           \
1048         UDFInterlockedIncrement((PLONG)&((fi)->ParentFile->OpenCount));  \
1049     }                                                \
1050 }
1051 
1052 #define UDFReferenceFileEx__(fi,i)                   \
1053 {                                                    \
1054     UDFInterlockedExchangeAdd((PLONG)&((fi)->RefCount),i);  \
1055     UDFInterlockedExchangeAdd((PLONG)&((fi)->Dloc->LinkRefCount),i);  \
1056     if((fi)->ParentFile) {                           \
1057         UDFInterlockedExchangeAdd((PLONG)&((fi)->ParentFile->OpenCount),i);  \
1058     }                                                \
1059 }
1060 
1061 #define UDFDereferenceFile__(fi)                     \
1062 {                                                    \
1063     UDFInterlockedDecrement((PLONG)&((fi)->RefCount));  \
1064     UDFInterlockedDecrement((PLONG)&((fi)->Dloc->LinkRefCount));  \
1065     if((fi)->ParentFile) {                           \
1066         UDFInterlockedDecrement((PLONG)&((fi)->ParentFile->OpenCount));  \
1067     }                                                \
1068 }
1069 
1070 #define UDFIsDirEmpty__(fi) UDFIsDirEmpty((fi)->Dloc->DirIndex)
1071 #define UDFIsDirOpened__(fi) (fi->OpenCount)
1072 
1073 #define UDFSetFileAllocMode__(fi, mode)  \
1074 {                                       \
1075     (fi)->Dloc->DataLoc.Flags = \
1076         ((fi)->Dloc->DataLoc.Flags & ~EXTENT_FLAG_ALLOC_MASK) | (mode & EXTENT_FLAG_ALLOC_MASK);     \
1077 }
1078 
1079 #define UDFGetFileAllocMode__(fi)  ((fi)->Dloc->DataLoc.Flags & EXTENT_FLAG_ALLOC_MASK)
1080 
1081 #define UDFGetFileICBAllocMode__(fi)  (((PFILE_ENTRY)((fi)->Dloc->FileEntry))->icbTag.flags & ICB_FLAG_ALLOC_MASK)
1082 
1083 #ifndef UDF_LIMIT_DIR_SIZE // release
1084 #define UDF_DIR_INDEX_FRAME_SH   9
1085 #else   //  demo
1086 #define UDF_DIR_INDEX_FRAME_SH   7
1087 #endif
1088 
1089 #define UDF_DIR_INDEX_FRAME      ((uint_di)(1 << UDF_DIR_INDEX_FRAME_SH))
1090 
1091 #define UDF_DIR_INDEX_FRAME_GRAN (32)
1092 #define UDF_DIR_INDEX_FRAME_GRAN_MASK (UDF_DIR_INDEX_FRAME_GRAN-1)
1093 #define AlignDirIndex(n)   ((n+UDF_DIR_INDEX_FRAME_GRAN_MASK) & ~(UDF_DIR_INDEX_FRAME_GRAN_MASK))
1094 
1095 #if defined _X86_ && !defined UDF_LIMIT_DIR_SIZE
1096 
1097 PDIR_INDEX_ITEM
1098 __fastcall
1099 UDFDirIndex(
1100     IN PDIR_INDEX_HDR hDirNdx,
1101     IN uint32 i
1102     );
1103 
1104 #else   // NO X86 optimization , use generic C/C++
UDFDirIndex(IN PDIR_INDEX_HDR hDirNdx,IN uint_di i)1105 __inline PDIR_INDEX_ITEM UDFDirIndex(IN PDIR_INDEX_HDR hDirNdx,
1106                                      IN uint_di i)
1107 {
1108 #ifdef UDF_LIMIT_DIR_SIZE
1109     if( hDirNdx && (i < hDirNdx->LastFrameCount))
1110         return &( (((PDIR_INDEX_ITEM*)(hDirNdx+1))[0])[i] );
1111 #else //UDF_LIMIT_DIR_SIZE
1112     uint_di j, k;
1113     if( hDirNdx &&
1114         ((j = (i >> UDF_DIR_INDEX_FRAME_SH)) < (k = hDirNdx->FrameCount) ) &&
1115         ((i = (i & (UDF_DIR_INDEX_FRAME-1))) < ((j < (k-1)) ? UDF_DIR_INDEX_FRAME : hDirNdx->LastFrameCount)) )
1116         return &( (((PDIR_INDEX_ITEM*)(hDirNdx+1))[j])[i] );
1117 #endif // UDF_LIMIT_DIR_SIZE
1118     return NULL;
1119 }
1120 #endif // _X86_
1121 
1122 #define UDFDirIndexGetLastIndex(di)  ((((di)->FrameCount - 1) << UDF_DIR_INDEX_FRAME_SH) + (di)->LastFrameCount)
1123 
1124 // arr - bit array,  bit - number of bit
1125 #ifdef _X86_
1126 
1127 #ifdef _CONSOLE
1128 #define CheckAddr(addr) {ASSERT((uint32)(addr) > 0x1000);}
1129 #else
1130 #define CheckAddr(addr) {ASSERT((uint32)(addr) & 0x80000000);}
1131 #endif
1132 
1133 #define UDFGetBit(arr, bit) UDFGetBit__((uint32*)(arr), bit)
1134 
1135 BOOLEAN
1136 __fastcall
1137 UDFGetBit__(
1138     IN uint32* arr,
1139     IN uint32 bit
1140     );
1141 
1142 #define UDFSetBit(arr, bit) UDFSetBit__((uint32*)(arr), bit)
1143 
1144 void
1145 __fastcall
1146 UDFSetBit__(
1147     IN uint32* arr,
1148     IN uint32 bit
1149     );
1150 
1151 #define UDFSetBits(arr, bit, bc) UDFSetBits__((uint32*)(arr), bit, bc)
1152 
1153 void
1154 UDFSetBits__(
1155     IN uint32* arr,
1156     IN uint32 bit,
1157     IN uint32 bc
1158     );
1159 
1160 #define UDFClrBit(arr, bit) UDFClrBit__((uint32*)(arr), bit)
1161 
1162 void
1163 __fastcall
1164 UDFClrBit__(
1165     IN uint32* arr,
1166     IN uint32 bit
1167     );
1168 
1169 #define UDFClrBits(arr, bit, bc) UDFClrBits__((uint32*)(arr), bit, bc)
1170 
1171 void
1172 UDFClrBits__(
1173     IN uint32* arr,
1174     IN uint32 bit,
1175     IN uint32 bc
1176     );
1177 
1178 #else   // NO X86 optimization , use generic C/C++
1179 
1180 #define UDFGetBit(arr, bit) (    (BOOLEAN) ( ((((uint32*)(arr))[(bit)>>5]) >> ((bit)&31)) &1 )    )
1181 #define UDFSetBit(arr, bit) ( (((uint32*)(arr))[(bit)>>5]) |= (((uint32)1) << ((bit)&31)) )
1182 #define UDFClrBit(arr, bit) ( (((uint32*)(arr))[(bit)>>5]) &= (~(((uint32)1) << ((bit)&31))) )
1183 
1184 #define UDFSetBits(arr, bit, bc) \
1185 {uint32 j;                       \
1186     for(j=0;j<bc;j++) {          \
1187         UDFSetBit(arr, (bit)+j); \
1188 }}
1189 
1190 #define UDFClrBits(arr, bit, bc) \
1191 {uint32 j;                       \
1192     for(j=0;j<bc;j++) {          \
1193         UDFClrBit(arr, (bit)+j); \
1194 }}
1195 
1196 #endif // _X86_
1197 
1198 #define UDFGetUsedBit(arr,bit)      (!UDFGetBit(arr,bit))
1199 #define UDFGetFreeBit(arr,bit)      UDFGetBit(arr,bit)
1200 #define UDFSetUsedBit(arr,bit)      UDFClrBit(arr,bit)
1201 #define UDFSetFreeBit(arr,bit)      UDFSetBit(arr,bit)
1202 #define UDFSetUsedBits(arr,bit,bc)  UDFClrBits(arr,bit,bc)
1203 #define UDFSetFreeBits(arr,bit,bc)  UDFSetBits(arr,bit,bc)
1204 
1205 #define UDFGetBadBit(arr,bit)       UDFGetBit(arr,bit)
1206 
1207 #define UDFGetZeroBit(arr,bit)      UDFGetBit(arr,bit)
1208 #define UDFSetZeroBit(arr,bit)      UDFSetBit(arr,bit)
1209 #define UDFClrZeroBit(arr,bit)      UDFClrBit(arr,bit)
1210 #define UDFSetZeroBits(arr,bit,bc)  UDFSetBits(arr,bit,bc)
1211 #define UDFClrZeroBits(arr,bit,bc)  UDFClrBits(arr,bit,bc)
1212 
1213 #if defined UDF_DBG || defined _CONSOLE
1214   #ifdef UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1215     #define UDFSetFreeBitOwner(Vcb, i) (Vcb)->FSBM_Bitmap_owners[i] = 0;
1216     #define UDFSetUsedBitOwner(Vcb, i, o) (Vcb)->FSBM_Bitmap_owners[i] = o;
1217     #define UDFGetUsedBitOwner(Vcb, i) ((Vcb)->FSBM_Bitmap_owners[i])
1218     #define UDFCheckUsedBitOwner(Vcb, i, o) { \
1219       ASSERT(i<(Vcb)->FSBM_BitCount); \
1220       if((Vcb)->FSBM_Bitmap_owners[i] != -1) { \
1221         ASSERT((Vcb)->FSBM_Bitmap_owners[i] == o); \
1222       } else { \
1223         ASSERT((Vcb)->FSBM_Bitmap_owners[i] != 0); \
1224         (Vcb)->FSBM_Bitmap_owners[i] = o; \
1225       } \
1226     }
1227     #define UDFCheckFreeBitOwner(Vcb, i) ASSERT((Vcb)->FSBM_Bitmap_owners[i] == 0);
1228   #else
1229     #define UDFSetFreeBitOwner(Vcb, i)
1230     #define UDFSetUsedBitOwner(Vcb, i, o)
1231     #define UDFCheckUsedBitOwner(Vcb, i, o)
1232     #define UDFCheckFreeBitOwner(Vcb, i)
1233   #endif //UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1234 #else
1235     #define UDFSetFreeBitOwner(Vcb, i)
1236     #define UDFSetUsedBitOwner(Vcb, i, o)
1237     #define UDFCheckUsedBitOwner(Vcb, i, o)
1238     #define UDFCheckFreeBitOwner(Vcb, i)
1239 #endif //UDF_DBG
1240 
1241 #ifdef UDF_TRACK_FS_STRUCTURES
1242 extern
1243 VOID
1244 UDFRegisterFsStructure(
1245     PVCB   Vcb,
1246     uint32 Lba,
1247     uint32 Length  // sectors
1248     );
1249 #else //UDF_TRACK_FS_STRUCTURES
1250 #define UDFRegisterFsStructure(Vcb, Lba, Length)   {NOTHING;}
1251 #endif //UDF_TRACK_FS_STRUCTURES
1252 
1253 extern const char hexChar[];
1254 
1255 #define UDF_MAX_VERIFY_CACHE   (8*1024*1024/2048)
1256 #define UDF_VERIFY_CACHE_LOW   (4*1024*1024/2048)
1257 #define UDF_VERIFY_CACHE_GRAN  (512*1024/2048)
1258 #define UDF_SYS_CACHE_STOP_THR (10*1024*1024/2048)
1259 
1260 OSSTATUS
1261 UDFVInit(
1262     IN PVCB Vcb
1263     );
1264 
1265 VOID
1266 UDFVRelease(
1267     IN PVCB Vcb
1268     );
1269 
1270 #define PH_FORGET_VERIFIED    0x00800000
1271 #define PH_READ_VERIFY_CACHE  0x00400000
1272 #define PH_KEEP_VERIFY_CACHE  0x00200000
1273 
1274 OSSTATUS
1275 UDFVWrite(
1276     IN PVCB Vcb,
1277     IN void* Buffer,     // Target buffer
1278     IN uint32 BCount,
1279     IN uint32 LBA,
1280 //    OUT PSIZE_T WrittenBytes,
1281     IN uint32 Flags
1282     );
1283 
1284 OSSTATUS
1285 UDFVRead(
1286     IN PVCB Vcb,
1287     IN void* Buffer,     // Target buffer
1288     IN uint32 BCount,
1289     IN uint32 LBA,
1290 //    OUT uint32* ReadBytes,
1291     IN uint32 Flags
1292     );
1293 
1294 OSSTATUS
1295 UDFVForget(
1296     IN PVCB Vcb,
1297     IN uint32 BCount,
1298     IN uint32 LBA,
1299     IN uint32 Flags
1300     );
1301 
1302 #define UFD_VERIFY_FLAG_FORCE   0x01
1303 #define UFD_VERIFY_FLAG_WAIT    0x02
1304 #define UFD_VERIFY_FLAG_BG      0x04
1305 #define UFD_VERIFY_FLAG_LOCKED  0x10
1306 
1307 VOID
1308 UDFVVerify(
1309     IN PVCB Vcb,
1310     IN ULONG Flags
1311     );
1312 
1313 VOID
1314 UDFVFlush(
1315     IN PVCB Vcb
1316     );
1317 
1318 __inline
1319 BOOLEAN
UDFVIsStored(IN PVCB Vcb,IN lba_t lba)1320 __fastcall UDFVIsStored(
1321     IN PVCB Vcb,
1322     IN lba_t lba
1323     )
1324 {
1325     if(!Vcb->VerifyCtx.VInited)
1326         return FALSE;
1327     return UDFGetBit(Vcb->VerifyCtx.StoredBitMap, lba);
1328 } // end UDFVIsStored()
1329 
1330 BOOLEAN
1331 __fastcall
1332 UDFCheckArea(
1333     IN PVCB Vcb,
1334     IN lba_t LBA,
1335     IN uint32 BCount
1336     );
1337 
1338 #endif // __UDF_STRUCT_SUPPORT_H__
1339