1 {--- Õðàíèëèùå ôàéëîâ --- - ýòî äèðåêòîðèÿ (æåëàòåëüíî íà äðóãîì âèí÷åñòåðå) èëè
2 ðàñøàðåííàÿ ñåòåâàÿ ïàïêà ñëåäóþùåé ñòðóêòóðû:
3 - äëÿ êàæäîé èñõîäíîé ìàøèíû ñîçäàåòñÿ ñâîÿ äèðåêòîðèÿ ñ èìåíåì êîìïüþòåðà;
4 - èñòîðèÿ äëÿ ôàéëîâ, ñîõðàíÿåòñÿ â ôàéëå ñ èìåíåì NNNNNNNN+èìÿ-ôàéëà.ext;
6 Ïðè ñîõðàíåíèè âñåé èñòîðèè ôàéëà â ôàéëå õðàíèëèùà ñ èìåíåì
7 NNNNNNNN+èìÿ-ôàéëà.ext ôîðìàò ñëåäóþùèé:
8 - äàòà ïîñëåäíåé ìîäèôèêàöèè íà ìîìåíò ñîõðàíåíèÿ (TFileTime, 8 áàéò);
9 - ðàçìåð ôàéëà íå ñæàòûé, 4 áàéòà;
10 - êîíòðîëüíàÿ ñóììà, 4 áàéòà;
11 - òèï çàïèñè: áèò0: 0 - ñàì ôàéë, 1 - äàííûå äëÿ èçìåíåíèÿ
12 áèò1: 0 - áåç ñæàòèÿ, 1 - èñïîëüçóåòñÿ ñæàòèå (UPX)
13 - äëèíà áëîêà = Lc: 4 áàéòà (åñëè ñæàò, òî ñëåäêþùèå 4 áàéòà ñþäà âõîäÿò)
14 - åñëè áëîê ñæàò, òî äëèíà íåñæàòîãî ñîäåðæèìîãî áëîêà Ln: 4 áàéòà
15 - áëîê: Lc-4 áàéò åñëè íå ñæàòî, èíà÷å Ln
21 uses Windows
, KOL
, FileVersionUnit
;
24 TEnumSectionsProc
= procedure( FileStream
: PStream
; const FI
: TFileVersionInfo
;
25 SectionType
: Byte; SectionLen
: DWORD
; var Continue
: Boolean ) of object;
28 TStorage
= object( TObj
)
32 procedure SetPath(const Value
: String);
35 procedure Init
; virtual;
37 destructor Destroy
; virtual;
38 property Path
: String read FPath write SetPath
;
39 property OK
: Boolean read FOK
;
41 DirsIndex
: PStrListEx
;
42 function DirPrefix( const DirPath
: String ): String; // 8 öèôð ïî èìåíè äèðåêòîðèè
44 function CheckFile( const SrcFilePath
: String; var ChkSum
: DWORD
): Boolean;
45 // ôàéë èçìåíèëñÿ ñ ïîñëåäíåãî ñîõðàíåíèÿ? Åñëè êîíòðîëüíàÿ ñóììà áûëà
46 // ïîñ÷èòàíà, òî îíà âîçâðàùàåòñÿ <> 0
47 procedure UpdateFile( const SrcFilePath
: String; ChkSum
: DWORD
; Action
: Integer );
48 // îáíîâèòü ôàéë â áàçå
49 function SaveFileHistory( const SrcFilePath
: String ): Boolean;
50 // ïðîñìîòð ñåêöèé àðõèâà îäíîãî ôàéëà
52 FoundLastFullVersionPos
: DWORD
;
53 LastInfo
: TFileVersionInfo
;
56 UnpackingFile
: String;
57 procedure EnumSections( FileStream
: PStream
; EnumProc
: TEnumSectionsProc
);
58 // ïîèñê ïîñëåäíåé ïîëíîé ñåêöèè, ñ êîòîðîé ìîæíî íà÷àòü âîññòàíîâëåíèå
59 // ïîñëåäíåé ñîõðàíåííîé ñåêöèè
60 procedure LookForLastFullVersion( FileStream
: PStream
; const FI
: TFileVersionInfo
;
61 SecType
: Byte; SecLen
: DWORD
; var Cont
: Boolean );
62 // ïîèñê è âîññòàíîâëåíèå ñàìîé ïîñëåäíåé ñîõðàíåííîé âåðñèè ôàéëà
63 procedure LookRestoreLastVersion( FileStream
: PStream
; const FI
: TFileVersionInfo
;
64 SecType
: Byte; SecLen
: DWORD
; var Cont
: Boolean );
65 // ïîèñê èíôîðìàöèè î ïîñëåäíåé ñîõðàíåííîé âåðñèè: äàòà, êîíòðîëüíàÿ ñóììà è ðàçìåð
66 procedure LookForLastVersionInfo( FileStream
: PStream
; const FI
: TFileVersionInfo
;
67 SecType
: Byte; SecLen
: DWORD
; var Cont
: Boolean );
68 procedure ProgressHandler( Percents
, CurrentPosition
, TotalSize
: Integer;
69 var Cancel
: Boolean );
71 CacheVersionInfo
: PStrListEx
;
72 procedure ClearCacheVersionInfo
;
73 procedure PutCachedVersionInfo( const SrcFilePath
: String; var FI
: TFileVersionInfo
);
74 function GetCachedVersionInfo( const SrcFilePath
: String; var FI
: TFileVersionInfo
): Boolean;
75 procedure DelCachedVersionInfo( const SrcFilePath
: String );
76 procedure UpdCachedVersionInfo( const SrcFilePath
: String; const ft
: TFileTime
);
84 uses MainUnit
, DIUCLStreams
, UpdatesUnit
;
86 function CalcFileCheckSum( const FS
: PStream
; var ChkSum
: DWORD
): Boolean;
93 BufSize
:= Min( FS
.Size
, 65536 * 16 );
94 GetMem( Buf
, BufSize
);
97 while FS
.Position
< FS
.Size
do
99 L
:= Min( BufSize
, FS
.Size
- FS
.Position
);
100 if FS
.Read( Buf
^, L
) <> L
then Exit
;
104 ChkSum
:= (ChkSum
shl 1) xor B
^;
115 function CalcFileCheckSum( const FilePath
: String; var ChkSum
: DWORD
): Boolean;
120 FS
:= NewReadFileStream( FilePath
);
122 if FS
.Handle
= INVALID_HANDLE_VALUE
then Exit
;
123 Result
:= CalcFileCheckSum( FS
, ChkSum
);
131 function TStorage
.CheckFile(const SrcFilePath
: String; var ChkSum
: DWORD
): Boolean;
136 FI
: TFileVersionInfo
;
141 P
:= DirPrefix( ExtractFilePath( SrcFilePath
) );
142 FN
:= ExtractFileName( SrcFilePath
);
144 if not FileExists( FPath
+ P
+ '+' + FN
) then Exit
;
146 if not GetCachedVersionInfo( SrcFilePath
, FI
) then
149 Log( '-Checking: ' + SrcFilePath
);
150 FS
:= NewReadFileStream( FPath
+ P
+ '+' + FN
);
152 FillChar( LastInfo
, Sizeof( LastInfo
), 0 );
153 EnumSections( FS
, LookForLastVersionInfo
);
155 PutCachedVersionInfo( SrcFilePath
, FI
);
162 //DL := NewDirList( ExtractFilePath( SrcFilePath ), FN, FILE_ATTRIBUTE_NORMAL );
163 DL
:= NewDirList( '', '', 0 );
164 DL
.OnItem
:= fmMainGuard
.AcceptDirItem
;
165 DL
.ScanDirectory( ExtractFilePath( SrcFilePath
), FN
, FILE_ATTRIBUTE_NORMAL
);
168 for I
:= 0 to DL
.Count
-1 do
170 if not DL
.IsDirectory
[ I
] then
171 if AnsiEq( DL
.Names
[ I
], FN
) then
176 if (J
< 0) or (DL
.Items
[ J
].nFileSizeHigh
<> 0) then
178 //--- âîîáùå-òî ýòî îøèáêà êàêàÿ-òî èëè ôàéë óæå óñïåëè óáðàòü ñ èñõîäíîãî
179 // äèñêà (èëè íàïðèìåð ïåðåèìåíîâàòü). Èëè ôàéë ñëèøêîì âåëèê.
180 // Áîëüøå íà íåãî íå ñìîòðåòü è íå ñîõðàíÿòü
181 Result
:= TRUE; Exit
;
183 if FI
.Sz
<> DL
.Items
[ J
].nFileSizeLow
then
184 Exit
; // äëèíà íå ñîâïàëà
185 if CompareFileTime( DL
.Items
[ J
].ftLastWriteTime
, FI
.FT
) <> 0 then
186 Exit
; // âðåìÿ ïîñëåäíåãî èçìåíåíèÿ íå ñîâïàëî
187 {if not CalcFileCheckSum( SrcFilePath, ChkSum ) then
188 begin //--- òîæå îøèáêà, èëè ôàéë óñòðàíèëñÿ
189 Result := TRUE; Exit;
191 if ChkSum <> FI.ChkSum then
192 Exit; // êîíòðîëüíàÿ ñóììà íå ñîâïàëà}
193 Result
:= TRUE; // âñå ñîâïàëî - ñ÷èòàåì, ÷òî ôàéë íå èçìåíèëñÿ!
196 Log( '-Checked(' + Int2Str( Integer( Result
) ) + '): ' + SrcFilePath
);
200 procedure TStorage
.ClearCacheVersionInfo
;
203 for I
:= CacheVersionInfo
.Count
-1 downto 0 do
204 FreeMem( Pointer( CacheVersionInfo
.Objects
[ I
] ) );
205 CacheVersionInfo
.Clear
;
208 procedure TStorage
.DelCachedVersionInfo(const SrcFilePath
: String);
212 S
:= AnsiUpperCase( IncludeTrailingPathDelimiter( SrcFilePath
) );
213 I
:= CacheVersionInfo
.IndexOf( S
);
216 FreeMem( Pointer( CacheVersionInfo
.Objects
[ I
] ) );
217 CacheVersionInfo
.Delete( I
);
221 destructor TStorage
.Destroy
;
226 ClearCacheVersionInfo
;
227 CacheVersionInfo
.Free
;
231 function TStorage
.DirPrefix(const DirPath
: String): String;
232 var I
, MaxN
: Integer;
237 for I
:= 0 to DirsIndex
.Count
-1 do
239 MaxN
:= max( MaxN
, DirsIndex
.Objects
[ I
] ) + 1;
240 if AnsiEq( DirsIndex
.Items
[ I
], DirPath
) then
242 Result
:= Format( '%.08d', [ DirsIndex
.Objects
[ I
] ] );
246 Log( '-Index ' + Format( '%.08d', [ MaxN
] ) + ' allocated for ' + DirPath
);
247 DirsIndex
.AddObject( DirPath
, MaxN
);
250 procedure TStorage
.EnumSections(FileStream
: PStream
;
251 EnumProc
: TEnumSectionsProc
);
253 FI
: TFileVersionInfo
;
258 P
:= FileStream
.Position
;
260 if FileStream
.Position
= 0 then
262 while FileStream
.Position
< FileStream
.Size
do
264 if FileStream
.Read( FI
, Sizeof( FI
) ) < Sizeof( FI
) then Exit
;
265 if FileStream
.Read( SecType
, 1 ) < 1 then Exit
;
266 if FileStream
.Read( L
, 4 ) < 4 then Exit
;
267 if FileStream
.Position
+ L
> FileStream
.Size
then Exit
;
268 if Assigned( EnumProc
) then
271 P1
:= FileStream
.Position
;
272 EnumProc( FileStream
, FI
, SecType
, L
, Cont
);
273 FileStream
.Position
:= P1
;
276 P
:= FileStream
.Position
+ L
;
280 FileStream
.Position
:= FileStream
.Position
+ L
;
281 P
:= FileStream
.Position
;
284 FileStream
.Position
:= P
;
288 function TStorage
.GetCachedVersionInfo(const SrcFilePath
: String;
289 var FI
: TFileVersionInfo
): Boolean;
293 S
:= AnsiUpperCase( IncludeTrailingPathDelimiter( SrcFilePath
) );
294 I
:= CacheVersionInfo
.IndexOf( S
);
298 FI
:= PFileVersionInfo( Pointer( CacheVersionInfo
.Objects
[ I
] ) )^;
304 procedure TStorage
.Init
;
305 var Buf
: array[ 0..MAX_COMPUTERNAME_LENGTH
] of Char;
308 Sz
:= MAX_COMPUTERNAME_LENGTH
;
309 GetComputerName( @ Buf
[ 0 ], Sz
);
312 DirsIndex
:= NewStrListEx
;
313 CacheVersionInfo
:= NewStrListEx
;
316 procedure TStorage
.LookForLastFullVersion(FileStream
: PStream
;
317 const FI
: TFileVersionInfo
; SecType
: Byte; SecLen
: DWORD
; var Cont
: Boolean);
319 if SecType
and 1 = 0 then
320 FoundLastFullVersionPos
:= FileStream
.Position
;
323 procedure TStorage
.LookForLastVersionInfo(FileStream
: PStream
;
324 const FI
: TFileVersionInfo
; SecType
: Byte; SecLen
: DWORD
;
330 procedure TStorage
.LookRestoreLastVersion(FileStream
: PStream
;
331 const FI
: TFileVersionInfo
; SecType
: Byte; SecLen
: DWORD
; var Cont
: Boolean);
334 OldVersion
, CmdStream
: PStream
;
336 if SecType
and 1 = 0 then
337 begin // ïîëíàÿ âåðñèÿ çäåñü
338 LastVersion
.Position
:= 0;
339 if SecType
and 2 = 0 then
340 Stream2Stream( LastVersion
, FileStream
, SecLen
)
342 begin // ñæàòàÿ ïîëíàÿ âåðñèÿ
343 FileStream
.Read( L
, 4 );
344 US
:= DIUCLStreams
.NewUclDStream( $80000, FileStream
, fmMainGuard
.UCLOnProgress
);
346 Stream2Stream( LastVersion
, US
, L
);
353 begin // îáíîâëåíèå îò ïðåäûäóùåé âåðñèè çäåñü
354 OldVersion
:= NewMemoryStream
;
355 CmdStream
:= NewMemoryStream
;
357 if SecType
and 2 = 0 then
358 Stream2Stream( CmdStream
, FileStream
, SecLen
)
360 begin // êîìàíäíûé ïîòîê ñæàò
361 FileStream
.Read( L
, 4 );
362 US
:= DIUCLStreams
.NewUclDStream( $80000, FileStream
, fmMainGuard
.UCLOnProgress
);
364 Stream2Stream( CmdStream
, FileStream
, L
);
369 // òåïåðü ðàñïàêîâêà íîâîé âåðñèè
370 if CmdStream
.Size
> 0 then
372 LastVersion
.Position
:= 0;
373 Stream2Stream( OldVersion
, LastVersion
, LastVersion
.Size
);
374 OldVersion
.Position
:= 0;
375 LastVersion
.Position
:= 0;
376 CmdStream
.Position
:= 0;
377 if not DoApplyUpdates( LastVersion
, OldVersion
, CmdStream
) then
379 Log( 'Error unpacking ' + UnpackingFile
);
381 OldVersion
.Position
:= 0;
382 LastVersion
.Position
:= 0;
383 Stream2Stream( LastVersion
, OldVersion
, OldVersion
.Size
);
384 LastVersion
.Size
:= LastVersion
.Position
;
385 LastVersion
.Position
:= 0;
390 LastVersion
.Position
:= LastVersion
.Size
;
396 LastVersion
.Size
:= LastVersion
.Position
;
397 LastVersion
.Position
:= 0;
400 procedure TStorage
.ProgressHandler(Percents
, CurrentPosition
,
401 TotalSize
: Integer; var Cancel
: Boolean);
403 Applet
.ProcessMessages
;
406 procedure TStorage
.PutCachedVersionInfo(const SrcFilePath
: String;
407 var FI
: TFileVersionInfo
);
409 FIData
: PFileVersionInfo
;
412 S
:= AnsiUpperCase( IncludeTrailingPathDelimiter( SrcFilePath
) );
413 I
:= CacheVersionInfo
.IndexOf( S
);
416 GetMem( FIData
, Sizeof( FI
) );
418 CacheVersionInfo
.AddObject( S
, DWORD( FIData
) );
422 function TStorage
.SaveFileHistory(const SrcFilePath
: String): Boolean;
423 var FS
, DS
, NS
, TS
: PStream
;
424 FI
: TFileVersionInfo
;
426 WriteFullVersion
, AddFullVersion
: Boolean;
432 UnpackingFile
:= SrcFilePath
;
433 FN
:= ExtractFileName( SrcFilePath
);
435 TS
:= NewReadFileStream( SrcFilePath
);
437 if TS
.Handle
= INVALID_HANDLE_VALUE
then Exit
;
438 GetFileTime( TS
.Handle
, nil, nil, @FI
.FT
);
439 FS
:= NewMemoryStream
;
440 Stream2Stream( FS
, TS
, TS
.Size
);
447 LS
:= NewMemoryStream
;
448 CS
:= NewMemoryStream
;
449 TS
:= NewMemoryStream
;
452 CalcFileCheckSum( FS
, FI
.ChkSum
);
453 P
:= DirPrefix( ExtractFilePath( SrcFilePath
) );
454 DS
:= NewReadWriteFileStream( FPath
+ P
+ '+' + FN
);
455 if DS
.Handle
= INVALID_HANDLE_VALUE
then Exit
;
456 FoundLastFullVersionPos
:= 0;
457 EnumSections( DS
, LookForLastFullVersion
);
458 WriteFullVersion
:= TRUE;
459 AddFullVersion
:= FALSE;
460 if FoundLastFullVersionPos
> 0 then
462 DS
.Position
:= FoundLastFullVersionPos
- 5 - Sizeof( FI
);
464 UnpackError
:= FALSE;
465 EnumSections( DS
, LookRestoreLastVersion
);
467 WriteFullVersion
:= TRUE
469 if DS
.Position
- FoundLastFullVersionPos
< FS
.Size
* 3 then
471 MakeUpdates( CS
, FS
, LS
, ProgressHandler
);
472 WriteFullVersion
:= CS
.Size
+ 1 >= FS
.Size
;
473 if not WriteFullVersion
then
475 NS
:= NewMemoryStream
;
478 if not DoApplyUpdates( NS
, LS
, CS
) then AddFullVersion
:= TRUE
479 else if NS
.Size
<> FS
.Size
then AddFullVersion
:= TRUE
483 Stream2Stream( TS
, FS
, FS
.Size
);
484 if not CompareMem( TS
.Memory
, NS
.Memory
, NS
.Size
) then
485 AddFullVersion
:= TRUE;
493 if not UnpackError
and (DS
.Position
= DS
.Size
) and (CS
.Size
= 0) then
495 //Result := TRUE; // íå íàäî íè÷åãî çàïèñûâàòü - ôàéë íå èçìåíèëñÿ
496 Storage
.UpdCachedVersionInfo( SrcFilePath
, FI
.FT
);
500 //--------------------------------------------------------------------------
501 // Ïîäãîòàâëèâàåì çàïèñü íîâîé âåðñèè
502 if DS
.Position
= 0 then
503 DS
.WriteStrZ( ExtractFilePath( SrcFilePath
) );
504 if WriteFullVersion
then
508 Stream2Stream( CS
, FS
, FS
.Size
);
514 US
:= DIUCLStreams
.NewUclCStream( 10, $80000, TS
, fmMainGuard
.UCLOnProgress
);
517 Stream2Stream( US
, CS
, CS
.Size
);
522 if (TS
.Size
>= CS
.Size
- 4) or (TS
.Size
= 0) then
523 begin // íå èñïîëüçîâàòü ñæàòèå
526 if not WriteFullVersion
then Inc( I
);
527 DS
.Write( FI
, Sizeof( FI
) );
529 if I
and 2 = 0 then // çàïèñü áåç ñæàòèÿ
534 Stream2Stream( DS
, CS
, L
);
537 begin // çàïèñü ñî ñæàòèåì
543 Stream2Stream( DS
, TS
, TS
.Size
);
545 if AddFullVersion
and not WriteFullVersion
then
547 Log( 'Error checking, full version added: ' + SrcFilePath
);
548 DS
.Write( FI
, Sizeof( FI
) );
551 US
:= DIUCLStreams
.NewUclCStream( 10, $80000, TS
, fmMainGuard
.UCLOnProgress
);
554 Stream2Stream( US
, FS
, FS
.Size
);
558 if (TS
.Size
>= FS
.Size
) or (TS
.Size
= 0) then
566 Stream2Stream( DS
, FS
, L
);
575 Stream2Stream( DS
, TS
, TS
.Size
);
578 DelCachedVersionInfo( SrcFilePath
);
589 procedure TStorage
.SetPath(const Value
: String);
591 Buf
: array[ 0..1023 ] of Char;
598 Log( '-Storage path: ' + Value
);
599 FPath
:= IncludeTrailingPathDelimiter( Value
);
601 if not DirectoryExists( FPath
) then Exit
;
603 if not DirectoryExists( FPath
+ FMachineName
+ '\' ) then
605 MkDir( FPath
+ FMachineName
+ '\' );
606 if not DirectoryExists( FPath
+ FMachineName
+ '\' ) then Exit
;
608 FPath
:= FPath
+ FMachineName
+ '\';
610 F
:= FileCreate( FPath
+ 'FileGuard.dir', ofOpenWrite
or ofOpenAlways
);
611 if F
= INVALID_HANDLE_VALUE
then Exit
;
613 if FileWrite( F
, Buf
, 1024 ) <> 1024 then Exit
;
617 //--- ïîñòðîåíèå èíäåêñà ñîõðàíåííûõ äèðåêòîðèé
619 //DL := NewDirList( FPath, '*.*', FILE_ATTRIBUTE_NORMAL );
620 DL
:= NewDirList( '', '', 0 );
621 DL
.OnItem
:= fmMainGuard
.AcceptDirItem
;
622 DL
.ScanDirectory( FPath
, '*.*', FILE_ATTRIBUTE_NORMAL
);
625 for I
:= 0 to DL
.Count
-1 do
626 if not DL
.IsDirectory
[ I
] then
628 Prefix
:= Str2Int( DL
.Names
[ I
] );
631 if DirsIndex
.IndexOfObj( Pointer( Prefix
) ) < 0 then
633 FS
:= NewReadFileStream( DL
.Path
+ DL
.Names
[ I
] );
636 DirsIndex
.AddObject( S
, Prefix
);
648 Log( '-Storage index built OK' );
651 procedure TStorage
.UpdateFile(const SrcFilePath
: String; ChkSum
: DWORD
;
655 Renamed_Delete
: Boolean;
656 Saved_History
: Boolean;
658 Log( '-Updating: ' + SrcFilePath
);
659 P
:= DirPrefix( ExtractFilePath( SrcFilePath
) );
660 FN
:= ExtractFileName( SrcFilePath
);
662 CalcFileCheckSum( SrcFilePath
, ChkSum
);
664 // ñîõðàíåíèå âñåé èñòîðèè
665 Saved_History
:= SaveFileHistory( SrcFilePath
)
668 Renamed_Delete
:= FALSE;
669 if FileExists( FPath
+ P
+ '+' + FN
) then
671 if FileExists( FPath
+ P
+ '+' + FN
+ '.old' ) then
673 if not DeleteFile( PChar( FPath
+ P
+ '+' + FN
+ '.old' ) ) then
674 Log( '*** Can not delete: ' + FPath
+ P
+ '+' + FN
+ '.old' );
677 MoveFile( PChar( FPath
+ P
+ '+' + FN
), PChar( FPath
+ P
+ '+' + FN
+ '.old' ) );
678 if not Renamed_Delete
then
679 Log( '*** Can not rename ' + FPath
+ P
+ '+' + FN
+ ' to ' +
680 FPath
+ P
+ '+' + FN
+ '.old' );
682 Saved_History
:= SaveFileHistory( SrcFilePath
);
683 if Saved_History
then
685 if Renamed_Delete
then
687 if not DeleteFile( PChar( FPath
+ P
+ '+' + FN
+ '.old' ) ) then
688 Log( '*** Can not delete: ' + FPath
+ P
+ '+' + FN
+ '.old' );
693 if Renamed_Delete
then
695 if not MoveFile( PChar( FPath
+ P
+ '+' + FN
+ '.old' ),
696 PChar( FPath
+ P
+ '+' + FN
) ) then
697 Log( '*** Can not rename ' + FPath
+ P
+ '+' + FN
+ '.old' +
698 ' to ' + FPath
+ P
+ '+' + FN
);
702 if Saved_History
then
704 Log( 'Saved: ' + SrcFilePath
);
705 fmMainGuard
.StorageTreeChanged
:= TRUE;
709 procedure TStorage
.UpdCachedVersionInfo(const SrcFilePath
: String;
710 const ft
: TFileTime
);
713 FIData
: PFileVersionInfo
;
715 S
:= AnsiUpperCase( IncludeTrailingPathDelimiter( SrcFilePath
) );
716 I
:= CacheVersionInfo
.IndexOf( S
);
719 FIData
:= Pointer( CacheVersionInfo
.Objects
[ I
] );