| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644 |
- unit CnSMRBplUtils;
- interface
- {$I CnWizards.inc}
- uses
- SysUtils, Windows, Classes, CnBaseUtils;
- const
- csDefaultPackageExt = '.bpl';
- cssExecutableFiles = ' Executable Files ';
- cssUnits = 'Units:';
- cssRequiredPackages = 'Required Packages:';
- { DO NOT LOCALIZE }
- csFileNotExists = 'File %s not exists.';
- csCanNotAnalyseFile = 'Analyze "%s" failed: ';
- type
- PPackageInfos = ^TPackageInfos;
- TPackageInfos = record
- Units: TStrings;
- RequiredPackages: TStrings;
- end;
- TPackageInfosList = class(TStringList)
- private
- FStringProcessProc: TStringProcessProc;
- function GetPackageInfos(Index: Integer): PPackageInfos;
- procedure SetPackageInfos(Index: Integer; const Value: PPackageInfos);
- function ProcessString(const s: string): string;
- procedure ClearPackageInfos;
- procedure InternalSaveToText(var Stream: Text);
- public
- constructor Create;
- destructor Destroy; override;
- function GetRequiredPackagesSectionName(const s: string): string; virtual;
- function GetUnitsSectionName(const s: string): string; virtual;
- procedure AddFile(const FileName: string);
- procedure Clear; override;
- procedure Delete(Index: Integer); override;
- procedure BuildPackageUsedBy(UsedByPackagesList: TStringObjectList); overload;
- procedure BuildPackageUsedBy(UsedByPackagesList: TStringObjectList; TempStrings: TStrings); overload;
- procedure BuildUnits(Units: TStringObjectList);
- procedure GetAllAffectedPackages(UsedByPackagesList: TStringObjectList; ssUsedByPackages, ssAllAffectedPackages: TStrings);
- procedure GetAllRequiredPackages(ssRequiredPackages, ssAllRequiredPackages: TStrings);
- procedure GetAllUsedByPackages(UsedByPackagesList: TStringObjectList; ssUsedByPackages, ssAllUsedByPackages: TStrings);
- procedure GetRequiredPackages(const s: string; ssAllRequiredPackages: TStrings);
- procedure GetUsedByPackages(UsedByPackagesList: TStringObjectList; const s: string; ssAllUsedByPackages: TStrings);
- procedure AppendToFile(const FileName: string);
- procedure LoadFromFile(const FileName: string); override;
- procedure SaveToFile(const FileName: string); override;
- property PackageInfos[Index: Integer]: PPackageInfos read GetPackageInfos write SetPackageInfos;
- property StringProcessProc: TStringProcessProc read FStringProcessProc write FStringProcessProc;
- end;
- function NewPackageInfos: PPackageInfos;
- function NewPackageInfosAndCreateList: PPackageInfos;
- procedure DisposePackageInfos(P: PPackageInfos);
- function EnumUnits(const FileName: string; ss: TStrings): Boolean; overload;
- function EnumUnits(const Module: HMODULE; ss: TStrings): Boolean; overload;
- function EnumRequiredPackages(const FileName: string; ss: TStrings): Boolean; overload;
- function EnumRequiredPackages(const Module: HMODULE; ss: TStrings): Boolean; overload;
- function EnumPackageInfos(const FileName: string; ssUnits, ssRequiredPackages: TStrings): Boolean; overload;
- function EnumPackageInfos(const Module: HMODULE; ssUnits, ssRequiredPackages: TStrings): Boolean; overload;
- implementation
- {$IFDEF DELPHI7_UP}
- {$WARN SYMBOL_PLATFORM OFF}
- {$WARN UNIT_PLATFORM OFF}
- {$ENDIF}
- uses
- FileCtrl, CnBuffStr, CnSMRPEUtils;
- function NewPackageInfos: PPackageInfos;
- begin
- New(Result);
- Result.Units := nil;
- Result.RequiredPackages := nil;
- end;
- function NewPackageInfosAndCreateList: PPackageInfos;
- begin
- New(Result);
- Result.Units := TStringList.Create;
- TStringList(Result.Units).Sorted := True;
- Result.RequiredPackages := TStringList.Create;
- TStringList(Result.RequiredPackages).Sorted := True;
- end;
- procedure DisposePackageInfos(P: PPackageInfos);
- begin
- if P <> nil then
- begin
- if Assigned(P.Units) then
- begin
- FreeAndNil(P.Units);
- end;
- if Assigned(P.RequiredPackages) then
- begin
- FreeAndNil(P.RequiredPackages);
- end;
- Dispose(P);
- end;
- end;
- procedure GetPackageInfosProc(const Name: string; NameType: TNameType; Flags: Byte;
- Param: Pointer);
- var
- P: PPackageInfos;
- begin
- P := PPackageInfos(Param);
- if not Assigned(P) then
- begin
- Exit;
- end;
- if (NameType = ntContainsUnit) and (Assigned(P.Units)) then
- begin
- P.Units.Add(Name);
- end
- else if (NameType = ntRequiresPackage) and (Assigned(P.RequiredPackages)) then
- begin
- P.RequiredPackages.Add(Name);
- end;
- end;
- function EnumUnits(const FileName: string; ss: TStrings): Boolean;
- begin
- Result := EnumPackageInfos(FileName, ss, nil);
- end;
- function EnumUnits(const Module: HMODULE; ss: TStrings): Boolean;
- begin
- Result := EnumPackageInfos(Module, ss, nil);
- end;
- function EnumRequiredPackages(const FileName: string; ss: TStrings): Boolean;
- begin
- Result := EnumPackageInfos(FileName, nil, ss);
- end;
- function EnumRequiredPackages(const Module: HMODULE; ss: TStrings): Boolean;
- begin
- Result := EnumPackageInfos(Module, nil, ss);
- end;
- function EnumPackageInfos(const FileName: string; ssUnits, ssRequiredPackages: TStrings): Boolean;
- var
- Module: HMODULE;
- begin
- Result := False;
- if not FileExists(FileName) then
- begin
- Exit;
- end;
- Module := LoadLibraryEx(PChar(FileName), 0, LOAD_LIBRARY_AS_DATAFILE);
- if Module = 0 then
- begin
- RaiseLastWin32Error;
- end;
-
- try
- Result := EnumPackageInfos(Module, ssUnits, ssRequiredPackages);
- finally
- FreeLibrary(Module);
- end;
- end;
- function EnumPackageInfos(const Module: HMODULE; ssUnits, ssRequiredPackages: TStrings): Boolean;
- var
- Flags: Integer;
- PI: TPackageInfos;
- begin
- Result := False;
- if FindResource(Module, 'PACKAGEINFO', RT_RCDATA) <> 0 then
- begin
- PI.Units := ssUnits;
- PI.RequiredPackages := ssRequiredPackages;
- GetPackageInfo(Module, @PI, Flags, GetPackageInfosProc);
- Result := True;
- end;
- end;
- { TPackageInfosList }
- procedure TPackageInfosList.AddFile(const FileName: string);
- var
- P: PPackageInfos;
- begin
- if not FileExists(FileName) then
- begin
- raise Exception.CreateFmt(csFileNotExists, [AnsiQuotedStr(FileName, '"')]);
- end;
- P := NewPackageInfosAndCreateList;
- try
- EnumPackageInfos(FileName, P.Units, P.RequiredPackages);
- if P.RequiredPackages.Count = 0 then
- GetImportTable(P.RequiredPackages, FileName);
- except
- on E: Exception do
- begin
- DisposePackageInfos(P);
- E.Message := Format(csCanNotAnalyseFile, [FileName]) + E.Message;
- raise;
- end;
- end;
- AddObject(FileName, Pointer(P));
- end;
- procedure TPackageInfosList.AppendToFile(const FileName: string);
- var
- Stream: TextFile;
- begin
- AssignFile(Stream, FileName);
- try
- if FileExists(FileName) then
- begin
- System.Append(Stream);
- end
- else
- begin
- Rewrite(Stream);
- end;
- InternalSaveToText(Stream);
- finally
- CloseFile(Stream);
- end;
- end;
- procedure TPackageInfosList.BuildPackageUsedBy(
- UsedByPackagesList: TStringObjectList; TempStrings: TStrings);
- var
- i, j: Integer;
- idx: Integer;
- P: PPackageInfos;
- sRequiredPackage, sPackages, s: string;
- begin
- if not (Assigned(UsedByPackagesList) and Assigned(TempStrings)) then
- begin
- Exit;
- end;
- UsedByPackagesList.BeginUpdate;
- try
- UsedByPackagesList.Clear;
- for i := 0 to Self.Count - 1 do
- begin
- P := Self.PackageInfos[i];
- if (P <> nil) and (P.RequiredPackages <> nil) then
- begin
- for j := 0 to P.RequiredPackages.Count - 1 do
- begin
- sRequiredPackage := P.RequiredPackages[j];
- if ExtractFileExt(sRequiredPackage) = '' then
- begin
- sRequiredPackage := sRequiredPackage + csDefaultPackageExt;
- end;
- with UsedByPackagesList do
- begin
- idx := IndexOf(sRequiredPackage);
- if idx >= 0 then
- begin
- s := Strings[idx];
- SetCommaText(StringObjects[idx], TempStrings);
- TempStrings.Add(Self[i]);
- sPackages := TempStrings.CommaText;
- Delete(idx);
- end
- else
- begin
- sPackages := AnsiQuotedStr(Self[i], '"');
- end;
- AddStringObject(sRequiredPackage, sPackages);
- end;
- end;
- end;
- end;
- finally
- UsedByPackagesList.EndUpdate;
- end;
- end;
- procedure TPackageInfosList.BuildUnits(Units: TStringObjectList);
- var
- i, j: Integer;
- idx: Integer;
- P: PPackageInfos;
- sUnit, sPackages, s: string;
- begin
- Units.BeginUpdate;
- try
- Units.Clear;
- for i := 0 to Self.Count - 1 do
- begin
- P := Self.PackageInfos[i];
- if (P <> nil) and (P.Units <> nil) then
- begin
- for j := 0 to P.Units.Count - 1 do
- begin
- sUnit := P.Units[j];
- with Units do
- begin
- idx := IndexOf(sUnit);
- if idx >= 0 then
- begin
- s := Strings[idx];
- sPackages := StringObjects[idx] + ',' + AnsiQuotedStr(Self[i], '"');
- Delete(idx);
- end
- else
- begin
- sPackages := AnsiQuotedStr(Self[i], '"');
- end;
- AddStringObject(sUnit, sPackages);
- end;
- end;
- end;
- end;
- finally
- Units.EndUpdate;
- end;
- end;
- procedure TPackageInfosList.BuildPackageUsedBy(UsedByPackagesList: TStringObjectList);
- var
- sstmp: TStringList;
- begin
- sstmp := TStringList.Create;
- try
- sstmp.Sorted := True;
- BuildPackageUsedBy(UsedByPackagesList, sstmp);
- finally
- sstmp.Free;
- end;
- end;
- procedure TPackageInfosList.Clear;
- begin
- ClearPackageInfos;
- inherited;
- end;
- procedure TPackageInfosList.ClearPackageInfos;
- var
- i: Integer;
- begin
- for i := 0 to Count - 1 do
- begin
- DisposePackageInfos(PPackageInfos(Objects[i]));
- end;
- end;
- constructor TPackageInfosList.Create;
- begin
- inherited;
- end;
- procedure TPackageInfosList.Delete(Index: Integer);
- begin
- if (Index < 0) or (Index >= Count) then
- begin
- Exit;
- end;
- DisposePackageInfos(PackageInfos[Index]);
- inherited;
- end;
- destructor TPackageInfosList.Destroy;
- begin
- Clear;
- inherited;
- end;
- procedure TPackageInfosList.GetAllAffectedPackages(
- UsedByPackagesList: TStringObjectList;
- ssUsedByPackages, ssAllAffectedPackages: TStrings);
- var
- i, j, idx: Integer;
- ss: TStringList;
- begin
- if not (Assigned(ssUsedByPackages) and Assigned(ssAllAffectedPackages) and
- Assigned(UsedByPackagesList)) then
- begin
- Exit;
- end;
- ssAllAffectedPackages.Clear;
- for i := 0 to ssUsedByPackages.Count - 1 do
- begin
- ssAllAffectedPackages.Add(ssUsedByPackages[i]);
- end;
- ss := TStringList.Create;
- try
- for i := 0 to ssUsedByPackages.Count - 1 do
- begin
- idx := UsedByPackagesList.IndexOf(ssUsedByPackages[i]);
- if idx >= 0 then
- begin
- SetCommaText(UsedByPackagesList.StringObjects[idx], ss);
- for j := 0 to ss.Count - 1 do
- begin
- if ssAllAffectedPackages.IndexOf(ss[j]) < 0 then
- ssAllAffectedPackages.Add(ss[j]);
- end;
- end;
- end;
- finally
- ss.Free;
- end;
- end;
- procedure TPackageInfosList.GetAllRequiredPackages(ssRequiredPackages,
- ssAllRequiredPackages: TStrings);
- var
- i: Integer;
- s: string;
- begin
- if not (Assigned(ssRequiredPackages) and Assigned(ssAllRequiredPackages)) then
- begin
- Exit;
- end;
- for i := 0 to ssRequiredPackages.Count - 1 do
- begin
- s := ssRequiredPackages[i];
- if ssAllRequiredPackages.IndexOf(s) >= 0 then
- begin
- Continue;
- end;
- ssAllRequiredPackages.Add(s);
- GetRequiredPackages(s, ssAllRequiredPackages);
- end;
- end;
- procedure TPackageInfosList.GetAllUsedByPackages(UsedByPackagesList: TStringObjectList;
- ssUsedByPackages, ssAllUsedByPackages: TStrings);
- var
- i: Integer;
- s: string;
- begin
- if not (Assigned(ssUsedByPackages) and Assigned(ssAllUsedByPackages) and Assigned(UsedByPackagesList)) then
- begin
- Exit;
- end;
- for i := 0 to ssUsedByPackages.Count - 1 do
- begin
- s := ssUsedByPackages[i];
- if ssAllUsedByPackages.IndexOf(s) >= 0 then
- begin
- Continue;
- end;
- ssAllUsedByPackages.Add(s);
- GetUsedByPackages(UsedByPackagesList, s, ssAllUsedByPackages);
- end;
- end;
- function TPackageInfosList.GetPackageInfos(Index: Integer): PPackageInfos;
- begin
- if (Index < 0) or (Index >= Count) then
- begin
- Result := nil;
- Exit;
- end;
- Result := Pointer(Objects[Index]);
- end;
- function TPackageInfosList.GetRequiredPackagesSectionName(
- const s: string): string;
- begin
- Result := cssRequiredPackages + s;
- end;
- procedure TPackageInfosList.GetRequiredPackages(const s: string;
- ssAllRequiredPackages: TStrings);
- var
- P: PPackageInfos;
- begin
- P := Self.PackageInfos[Self.IndexOf(s)];
- if not (Assigned(ssAllRequiredPackages) and Assigned(P)) then
- begin
- Exit;
- end;
- GetAllRequiredPackages(P.RequiredPackages, ssAllRequiredPackages);
- end;
- function TPackageInfosList.GetUnitsSectionName(const s: string): string;
- begin
- Result := cssUnits + s;
- end;
- procedure TPackageInfosList.GetUsedByPackages(UsedByPackagesList: TStringObjectList;
- const s: string; ssAllUsedByPackages: TStrings);
- var
- idx: Integer;
- ss: TStringList;
- begin
- if not (Assigned(ssAllUsedByPackages) and Assigned(UsedByPackagesList)) then
- begin
- Exit;
- end;
- idx := UsedByPackagesList.IndexOf(s);
- if idx < 0 then
- begin
- Exit;
- end;
- ss := TStringList.Create;
- try
- SetCommaText(UsedByPackagesList.StringObjects[idx], ss);
- GetAllUsedByPackages(UsedByPackagesList, ss, ssAllUsedByPackages);
- finally
- ss.Free;
- end;
- end;
- procedure TPackageInfosList.InternalSaveToText(var Stream: Text);
- var
- i: Integer;
- begin
- //Save Head
- StringsSaveToTextWithSection(Self, Stream, cssExecutableFiles, False, StringProcessProc);
- //Save Results
- for i := 0 to Count - 1 do
- begin
- if PackageInfos[i] <> nil then
- begin
- with PackageInfos[i]^ do
- begin
- StringsSaveToTextWithSection(
- Units,
- Stream,
- GetUnitsSectionName(ProcessString(Strings[i])));
- StringsSaveToTextWithSection(
- RequiredPackages,
- Stream,
- GetRequiredPackagesSectionName(ProcessString(Strings[i])));
- end;
- end;
- end;
- end;
- procedure TPackageInfosList.LoadFromFile(const FileName: string);
- var
- P: PPackageInfos;
- Stream: TStringReader;
- i: Integer;
- sl: TSectionList;
- begin
- Stream := TStringReader.Create;
- try
- Stream.LoadFromFile(FileName);
- BulidSectionList(Stream, sl);
- // sl := nil;
- BeginUpdate;
- try
- Clear;
- //Load Head
- StringsLoadFromTextWithSection(Self, Stream, cssExecutableFiles, sl);
- //Load Results
- for i := 0 to Count - 1 do
- begin
- P := NewPackageInfosAndCreateList;
- try
- PackageInfos[i] := P;
- StringsLoadFromTextWithSection(P.Units,
- Stream,
- GetUnitsSectionName(Strings[i]),
- sl);
- StringsLoadFromTextWithSection(
- P.RequiredPackages,
- Stream,
- GetRequiredPackagesSectionName(Strings[i]),
- sl);
- except
- DisposePackageInfos(P);
- raise;
- end;
- end;
- finally
- EndUpdate;
- end;
- finally
- Stream.Free;
- FreeSectionList(sl);
- end;
- end;
- function TPackageInfosList.ProcessString(const s: string): string;
- begin
- if Assigned(StringProcessProc) then
- begin
- Result := StringProcessProc(s);
- end
- else
- begin
- Result := s;
- end;
- end;
- procedure TPackageInfosList.SaveToFile(const FileName: string);
- var
- Stream: TextFile;
- begin
- AssignFile(Stream, FileName);
- try
- Rewrite(Stream);
- InternalSaveToText(Stream);
- finally
- CloseFile(Stream);
- end;
- end;
- procedure TPackageInfosList.SetPackageInfos(Index: Integer;
- const Value: PPackageInfos);
- begin
- if (Index < 0) or (Index >= Count) then
- begin
- Exit;
- end;
- PutObject(Index, Pointer(Value));
- end;
- end.
|