@@ -21,6 +21,24 @@ Namespace DiskImage
2121 End Enum
2222
2323 Public Class DirectoryEntry
24+ Private Shared ReadOnly CP437LookupTable As Integer () = New Integer ( 255 ) {
25+ 0 , 9786 , 9787 , 9829 , 9830 , 9827 , 9824 , 8226 , 9688 , 9675 , 9689 , 9794 , 9792 , 9834 , 9835 , 9788 ,
26+ 9658 , 9668 , 8597 , 8252 , 182 , 167 , 9644 , 8616 , 8593 , 8595 , 8594 , 8592 , 8735 , 8596 , 9650 , 9660 ,
27+ 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 ,
28+ 48 , 49 , 50 , 51 , 52 , 53 , 54 , 55 , 56 , 57 , 58 , 59 , 60 , 61 , 62 , 63 ,
29+ 64 , 65 , 66 , 67 , 68 , 69 , 70 , 71 , 72 , 73 , 74 , 75 , 76 , 77 , 78 , 79 ,
30+ 80 , 81 , 82 , 83 , 84 , 85 , 86 , 87 , 88 , 89 , 90 , 91 , 92 , 93 , 94 , 95 ,
31+ 96 , 97 , 98 , 99 , 100 , 101 , 102 , 103 , 104 , 105 , 106 , 107 , 108 , 109 , 110 , 111 ,
32+ 112 , 113 , 114 , 115 , 116 , 117 , 118 , 119 , 120 , 121 , 122 , 123 , 124 , 125 , 126 , 8962 ,
33+ 199 , 252 , 233 , 226 , 228 , 224 , 229 , 231 , 234 , 235 , 232 , 239 , 238 , 236 , 196 , 197 ,
34+ 201 , 230 , 198 , 244 , 246 , 242 , 251 , 249 , 255 , 214 , 220 , 162 , 163 , 165 , 8359 , 402 ,
35+ 225 , 237 , 243 , 250 , 241 , 209 , 170 , 186 , 191 , 8976 , 172 , 189 , 188 , 161 , 171 , 187 ,
36+ 9617 , 9618 , 9619 , 9474 , 9508 , 9569 , 9570 , 9558 , 9557 , 9571 , 9553 , 9559 , 9565 , 9564 , 9563 , 9488 ,
37+ 9492 , 9524 , 9516 , 9500 , 9472 , 9532 , 9566 , 9567 , 9562 , 9556 , 9577 , 9574 , 9568 , 9552 , 9580 , 9575 ,
38+ 9576 , 9572 , 9573 , 9561 , 9560 , 9554 , 9555 , 9579 , 9578 , 9496 , 9484 , 9608 , 9604 , 9612 , 9616 , 9600 ,
39+ 945 , 223 , 915 , 960 , 931 , 963 , 181 , 964 , 934 , 920 , 937 , 948 , 8734 , 966 , 949 , 8745 ,
40+ 8801 , 177 , 8805 , 8804 , 8992 , 8993 , 247 , 8776 , 176 , 8729 , 183 , 8730 , 8319 , 178 , 9632 , 160
41+ }
2442 Private Const DIRECTORY_ENTRY_SIZE As Byte = 32
2543 Private Const CHAR_SPACE As Byte = 32
2644 Public Enum AttributeFlags
@@ -61,26 +79,43 @@ Namespace DiskImage
6179 LFNFilePart3 = 4
6280 End Enum
6381
64- Private ReadOnly _FatClusterList As List( Of UShort)
6582 Private _Data() As Byte
6683 Private ReadOnly _Offset As UInteger
84+ Private ReadOnly _FatChain As FATChain
6785 Private WithEvents Parent As Disk
6886 Private _SubDirectory As Directory
6987
7088 Sub New (Parent As Disk, Offset As UInteger)
7189 Me .Parent = Parent
7290 _Offset = Offset
91+
7392 LoadData()
7493
75- If IsDeleted( ) Then
76- _FatClusterList = New List( Of UShort )
94+ If _Parent.FATChains.ContainsKey(Offset ) Then
95+ _FatChain = _Parent.FATChains.Item(Offset )
7796 Else
78- _FatClusterList = GetFATClusterList()
97+ If IsDeleted() Then
98+ _FatChain = _Parent.InitFATChain(Offset, 0 )
99+ ElseIf IsDirectory() AndAlso { "." , ".." }.Contains(GetFullFileName) Then
100+ _FatChain = _Parent.InitFATChain(Offset, 0 )
101+ Else
102+ _FatChain = _Parent.InitFATChain(Offset, StartingCluster)
103+ End If
79104 End If
80105
81106 InitSubDirectory()
82107 End Sub
83108
109+ Public Shared Function CP437ToUnicode(b() As Byte ) As String
110+ Dim b2(b.Length - 1 ) As UShort
111+ For counter = 0 To b.Length - 1
112+ b2(counter) = CP437LookupTable(b(counter))
113+ Next
114+ ReDim b(b2.Length * 2 - 1 )
115+ Buffer.BlockCopy(b2, 0 , b, 0 , b.Length)
116+ Return Encoding.Unicode.GetString(b)
117+ End Function
118+
84119 Public Shared Function DateToFATDate(D As Date ) As UShort
85120 Dim FATDate As UShort = D.Year - 1980
86121
@@ -224,11 +259,11 @@ Namespace DiskImage
224259 End Function
225260
226261 Public Function GetDataBlocks() As List( Of DataBlock)
227- Return Parent.GetDataBlocksFromFATClusterList(_FatClusterList )
262+ Return Parent.GetDataBlocksFromFATClusterList(_FatChain.Chain )
228263 End Function
229264
230265 Public Function GetContent() As Byte ()
231- Dim Content = Parent.GetDataFromFATClusterList(_FatClusterList )
266+ Dim Content = Parent.GetDataFromFATClusterList(_FatChain.Chain )
232267
233268 If Content.Length <> FileSize Then
234269 Array.Resize( Of Byte )(Content, FileSize)
@@ -237,39 +272,16 @@ Namespace DiskImage
237272 Return Content
238273 End Function
239274
240- Private Function GetFATClusterList() As List( Of UShort)
241- Dim FATClusterList = New List( Of UShort)
242- Dim Cluster As UShort = StartingCluster
243- Dim AssignedClusters As New Hashtable
244- Do
245- If Cluster > 1 And Cluster <= UBound(Parent.FAT12) Then
246- If AssignedClusters.ContainsKey(Cluster) Then
247- Exit Do
248- End If
249- AssignedClusters.Add(Cluster, Cluster)
250- FATClusterList.Add(Cluster)
251- If Not Parent.FileAllocation.ContainsKey(Cluster) Then
252- Parent.FileAllocation.Add(Cluster, _Offset)
253- End If
254- Cluster = Parent.FAT12(Cluster)
255- Else
256- Cluster = 0
257- End If
258- Loop Until Cluster < &H2 Or Cluster > &HFEF
259-
260- Return FATClusterList
261- End Function
262-
263275 Public Function GetFileExtension() As String
264- Return Encoding.UTF8.GetString (Extension).TrimEnd(" " )
276+ Return CP437ToUnicode (Extension).TrimEnd(" " )
265277 End Function
266278
267279 Public Function GetFileName() As String
268- Return Encoding.UTF8.GetString (FileName).TrimEnd(" " )
280+ Return CP437ToUnicode (FileName).TrimEnd(" " )
269281 End Function
270282
271283 Public Function GetVolumeName() As String
272- Return Encoding.UTF8.GetString (FileName) & Encoding.UTF8.GetString (Extension).TrimEnd(" " )
284+ Return CP437ToUnicode (FileName) & CP437ToUnicode (Extension).TrimEnd(" " )
273285 End Function
274286
275287 Public Function GetFullFileName() As String
@@ -328,13 +340,17 @@ Namespace DiskImage
328340 Return FileSize > Parent.BootSector.ImageSize
329341 End Function
330342
343+ Public Function HasInvalidStartingCluster() As Boolean
344+ Return StartingCluster = 1 Or StartingCluster > _Parent.BootSector.NumberOfFATEntries + 1
345+ End Function
346+
331347 Public Function HasIncorrectFileSize() As Boolean
332348 If IsDirectory() Then
333349 Return False
334350 End If
335351
336352 Dim AllocatedSize As UInteger = Math.Ceiling(FileSize / _Parent.BootSector.BytesPerCluster) * _Parent.BootSector.BytesPerCluster
337- Dim AllocatedSizeFromFAT As UInteger = _FatClusterList .Count * _Parent.BootSector.BytesPerCluster
353+ Dim AllocatedSizeFromFAT As UInteger = _FatChain.Chain .Count * _Parent.BootSector.BytesPerCluster
338354
339355 Return AllocatedSize <> AllocatedSizeFromFAT
340356 End Function
@@ -345,7 +361,7 @@ Namespace DiskImage
345361
346362 Private Sub InitSubDirectory()
347363 If IsDirectory() And Not IsDeleted() Then
348- _SubDirectory = New Directory(Parent, _FatClusterList , FileSize)
364+ _SubDirectory = New Directory(Parent, _FatChain.Chain , FileSize)
349365 Else
350366 _SubDirectory = Nothing
351367 End If
@@ -355,6 +371,10 @@ Namespace DiskImage
355371 Return (Attributes And AttributeFlags.ArchiveFlag) > 0
356372 End Function
357373
374+ Public Function IsCrossLinked() As Boolean
375+ Return _FatChain.CrossLinks.Count > 0
376+ End Function
377+
358378 Public Function IsDeleted() As Boolean
359379 Return FileName( 0 ) = &HE5
360380 End Function
@@ -374,8 +394,8 @@ Namespace DiskImage
374394 Public Function IsModified() As Boolean
375395 Dim HasModification As Boolean = Parent.HasModification(_Offset)
376396 If Not HasModification Then
377- If _FatClusterList .Count > 0 Then
378- Dim ClusterOffset = _Parent.ClusterToOffset(_FatClusterList ( 0 ))
397+ If _FatChain.Chain .Count > 0 Then
398+ Dim ClusterOffset = _Parent.ClusterToOffset(_FatChain.Chain ( 0 ))
379399 HasModification = Parent.HasModification(ClusterOffset)
380400 End If
381401 End If
@@ -453,6 +473,12 @@ Namespace DiskImage
453473 End Set
454474 End Property
455475
476+ Public ReadOnly Property CrossLinks() As List( Of UInteger)
477+ Get
478+ Return _FatChain.CrossLinks
479+ End Get
480+ End Property
481+
456482 Public Property Extension() As Byte ()
457483 Get
458484 Return GetBytes(DirectoryEntryOffset.Extension, DirectoryEntrySize.Extension)
@@ -462,9 +488,9 @@ Namespace DiskImage
462488 End Set
463489 End Property
464490
465- Public ReadOnly Property FatClusterList As List( Of UShort)
491+ Public ReadOnly Property FATChain As List( Of UShort)
466492 Get
467- Return _FatClusterList
493+ Return _FatChain.Chain
468494 End Get
469495 End Property
470496
@@ -486,6 +512,12 @@ Namespace DiskImage
486512 End Set
487513 End Property
488514
515+ Public ReadOnly Property HasCircularChain As Boolean
516+ Get
517+ Return _FatChain.HasCircularChain
518+ End Get
519+ End Property
520+
489521 Public Property LastAccessDate() As UShort
490522 Get
491523 Return GetBytesShort(DirectoryEntryOffset.LastAccessDate)
0 commit comments