瀏覽代碼

Add [Setup] section directive ArchiveExtraction. Removes the need for the script to handle inclusion/extraction/loading.

Martijn Laan 3 月之前
父節點
當前提交
0d1c4dcdc6

+ 23 - 1
Projects/Src/Compiler.SetupCompiler.pas

@@ -2588,6 +2588,17 @@ begin
         ProcessExpressionParameter(KeyName, LowerCase(Value),
           EvalArchitectureIdentifier, False, SetupHeader.ArchitecturesInstallIn64BitMode);
       end;
+    ssArchiveExtraction: begin
+        Value := LowerCase(Trim(Value));
+        if Value = 'enhanced/nopassword' then begin
+          SetupHeader.SevenZipLibraryName := 'is7zxr.dll'
+        end else if Value = 'enhanced' then begin
+          SetupHeader.SevenZipLibraryName := 'is7zxa.dll'
+        end else if Value = 'full' then
+          SetupHeader.SevenZipLibraryName := 'is7z.dll'
+        else if Value <> 'basic' then
+          Invalid;
+      end;
     ssASLRCompatible: begin
         ASLRCompatible := StrToBool(Value);
       end;
@@ -6711,7 +6722,7 @@ var
   ExeFile: TFile;
   LicenseText, InfoBeforeText, InfoAfterText: AnsiString;
   WizardImages, WizardSmallImages: TObjectList<TCustomMemoryStream>;
-  DecompressorDLL: TMemoryStream;
+  DecompressorDLL, SevenZipDLL: TMemoryStream;
 
   SetupLdrOffsetTable: TSetupLdrOffsetTable;
   SizeOfExe, SizeOfHeaders: Longint;
@@ -6821,6 +6832,8 @@ var
         WriteStream(WizardSmallImages[J], W);
       if SetupHeader.CompressMethod in [cmZip, cmBzip] then
         WriteStream(DecompressorDLL, W);
+      if SetupHeader.SevenZipLibraryName <> '' then
+        WriteStream(SevenZipDLL, W);
 
       W.Finish;
     finally
@@ -7518,6 +7531,7 @@ begin
   WizardSmallImages := nil;
   SetupE32 := nil;
   DecompressorDLL := nil;
+  SevenZipDLL := nil;
 
   try
     Finalize(SetupHeader);
@@ -8038,6 +8052,13 @@ begin
         end;
     end;
 
+    { Read 7-Zip DLL. Must be done after [Files] is parsed, since
+      SetupHeader.SevenZipLibraryName isn't set until then }
+    if SetupHeader.SevenZipLibraryName <> '' then begin
+      AddStatus(Format(SCompilerStatusReadingFile, [SetupHeader.SevenZipLibraryName]));
+      SevenZipDLL := CreateMemoryStreamFromFile(CompilerDir + SetupHeader.SevenZipLibraryName);
+    end;
+
     { Add default types if necessary }
     if (ComponentEntries.Count > 0) and (TypeEntries.Count = 0) then begin
       AddDefaultSetupType(DefaultTypeEntryNames[0], [], ttDefaultFull);
@@ -8217,6 +8238,7 @@ begin
     CallPreprocessorCleanupProc;
     UsedUserAreas.Clear;
     WarningsList.Clear;
+    SevenZipDLL.Free;
     DecompressorDLL.Free;
     SetupE32.Free;
     WizardSmallImages.Free;

+ 5 - 37
Projects/Src/Compression.SevenZipDllDecoder.pas

@@ -17,11 +17,8 @@ interface
 uses
   Compression.SevenZipDecoder;
 
-procedure InitSevenZipLibrary(const DllFilename: String);
-procedure FreeSevenZipLibrary;
-
+function SevenZipDLLInit(const SevenZipLibrary: HMODULE): Boolean;
 function IsExtractArchiveRedirAvailable: Boolean;
-function GetSevenZipLibraryName: String;
 
 procedure ExtractArchiveRedir(const DisableFsRedir: Boolean;
   const ArchiveFilename, DestDir, Password: String; const FullPaths: Boolean;
@@ -397,34 +394,12 @@ end;
 {---}
 
 var
-  SevenZipLibrary: HMODULE;
-  SevenZipLibraryName: String;
   CreateSevenZipObject: function(const clsid, iid: TGUID; var outObject): HRESULT; stdcall;
 
-procedure FreeSevenZipLibrary;
-begin
-  if SevenZipLibrary <> 0 then begin
-    FreeLibrary(SevenZipLibrary);
-    SevenZipLibrary := 0;
-    SevenZipLibraryName := '';
-    CreateSevenZipObject := nil;
-  end;
-end;
-
-procedure InitSevenZipLibrary(const DllFilename: String);
+function SevenZipDLLInit(const SevenZipLibrary: HMODULE): Boolean;
 begin
-  if SevenZipLibrary = 0 then begin
-    SevenZipLibrary := LoadLibrary(PChar(DllFilename));
-    if SevenZipLibrary = 0 then
-      Win32ErrorMsg('LoadLibrary');
-    CreateSevenZipObject := GetProcAddress(SevenZipLibrary, 'CreateObject');
-    if not Assigned(CreateSevenZipObject) then begin
-      var LastError := GetLastError;
-      FreeSevenZipLibrary;
-      Win32ErrorMsgEx('GetProcAddress', LastError);
-    end;
-    SevenZipLibraryName := PathExtractName(DllFilename);
-  end;
+  CreateSevenZipObject := GetProcAddress(SevenZipLibrary, 'CreateObject');
+  Result := Assigned(CreateSevenZipObject);
 end;
 
 function IsExtractArchiveRedirAvailable: Boolean;
@@ -432,11 +407,6 @@ begin
   Result := Assigned(CreateSevenZipObject);
 end;
 
-function GetSevenZipLibraryName: String;
-begin
-  Result := SevenZipLibraryName;
-end;
-
 procedure ExtractArchiveRedir(const DisableFsRedir: Boolean;
   const ArchiveFilename, DestDir, Password: String;
   const FullPaths: Boolean; const OnExtractionProgress: TOnExtractionProgress);
@@ -492,8 +462,6 @@ procedure ExtractArchiveRedir(const DisableFsRedir: Boolean;
   end;
 
 begin
-  if not IsExtractArchiveRedirAvailable then
-    InternalError('ExtractArchive: 7z(xa).dll not loaded');
   if ArchiveFileName = '' then
     InternalError('ExtractArchive: Invalid ArchiveFileName value');
   const clsid = GetHandler(PathExtractExt(ArchiveFilename),
@@ -503,7 +471,7 @@ begin
 
   LogFmt('Extracting archive %s to %s. Full paths? %s', [ArchiveFileName, DestDir, SYesNo[FullPaths]]);
 
-  LogFmt('%s Decoder : Igor Pavlov', [SevenZipLibraryName]); { Just like 7zMain.c }
+  LogFmt('%s Decoder : Igor Pavlov', [SetupHeader.SevenZipLibraryName]); { Just like 7zMain.c }
 
   { CreateObject }
   var InArchive: IInArchive;

+ 30 - 5
Projects/Src/Setup.MainFunc.pas

@@ -256,7 +256,7 @@ var
   SHGetKnownFolderPathFunc: function(const rfid: TGUID; dwFlags: DWORD; hToken: THandle;
     var ppszPath: PWideChar): HRESULT; stdcall;
 
-  DecompressorDLLHandle: HMODULE;
+  DecompressorDLLHandle, SevenZipDLLHandle: HMODULE;
 
 type
   TDummyClass = class
@@ -2518,7 +2518,7 @@ procedure InitializeSetup;
 { Initializes various vars used by the setup. This is called in the project
   source. }
 var
-  DecompressorDLL: TMemoryStream;
+  DecompressorDLL, SevenZipDLL: TMemoryStream;
 
   function ExtractLongWord(var S: String): LongWord;
   var
@@ -2610,6 +2610,20 @@ var
     end;
   end;
 
+  procedure LoadSevenZipDLL;
+  var
+    Filename: String;
+  begin
+    Filename := AddBackslash(TempInstallDir) + '_isetup\_is7z.dll';
+    SaveStreamToTempFile(SevenZipDLL, Filename);
+    FreeAndNil(SevenZipDLL);
+    SevenZipDLLHandle := SafeLoadLibrary(Filename, SEM_NOOPENFILEERRORBOX);
+    if SevenZipDLLHandle = 0 then
+      InternalError(Format('Failed to load DLL "%s"', [Filename]))
+    else if not SevenZipDLLInit(SevenZipDLLHandle) then
+      InternalError('SevenZipDLLInit failed');
+  end;
+
 var
   Reader: TCompressedBlockReader;
 
@@ -3128,6 +3142,12 @@ begin
           DecompressorDLL := TMemoryStream.Create;
           ReadFileIntoStream(DecompressorDLL, Reader);
         end;
+        { SevenZip DLL }
+        SevenZipDLL := nil;
+        if SetupHeader.SevenZipLibraryName <> '' then begin
+          SevenZipDLL := TMemoryStream.Create;
+          ReadFileIntoStream(SevenZipDLL, Reader);
+        end;
       finally
         Reader.Free;
       end;
@@ -3211,6 +3231,10 @@ begin
   if SetupHeader.CompressMethod in [cmZip, cmBzip] then
     LoadDecompressorDLL;
 
+  { Extract "_is7z.dll" to TempInstallDir, and load it }
+  if SetupHeader.SevenZipLibraryName <> '' then
+    LoadSevenZipDLL;
+
   { Start RestartManager session }
   if InitCloseApplications or
      ((shCloseApplications in SetupHeader.Options) and not InitNoCloseApplications) then begin
@@ -3492,13 +3516,14 @@ begin
   if RmSessionStarted then
     RmEndSession(RmSessionHandle);
 
-  { Free the _isdecmp.dll handle }
+  { Free the _isdecmp.dll and _is7z.dll handles }
   if DecompressorDLLHandle <> 0 then
     FreeLibrary(DecompressorDLLHandle);
+  if SevenZipDLLHandle <> 0 then
+    FreeLibrary(SevenZipDLLHandle);
 
-  { Free the shfolder.dll and 7z.dll handles }
+  { Free the shfolder.dll handle }
   UnloadSHFolderDLL;
-  FreeSevenZipLibrary;
 
   { Remove TempInstallDir, stopping the 64-bit helper first if necessary }
   RemoveTempInstallDir;

+ 1 - 1
Projects/Src/Setup.ScriptDlg.pas

@@ -1193,7 +1193,7 @@ begin
   const ExtractArchiveRedirAvailable = IsExtractArchiveRedirAvailable;
 
   LogFmt('Archive extraction mode: %s',
-    [IfThen(ExtractArchiveRedirAvailable, Format('Using %s', [GetSevenZipLibraryName]), 'Built-in')]);
+    [IfThen(ExtractArchiveRedirAvailable, Format('Using %s', [SetupHeader.SevenZipLibraryName]), 'Built-in')]);
 
   for var A in FArchives do begin
     { Don't need to set DownloadTemporaryFileOrExtractArchiveProcessMessages before extraction since we already process messages ourselves }

+ 0 - 4
Projects/Src/Setup.ScriptFunc.pas

@@ -1788,10 +1788,6 @@ var
     begin
       Extract7ZipArchiveRedir(ScriptFuncDisableFsRedir, Stack.GetString(PStart), Stack.GetString(PStart-1), '', Stack.GetBool(PStart-2), TOnExtractionProgress(Stack.GetProc(PStart-3, Caller)));
     end);
-    RegisterScriptFunc('INIT7ZIPLIBRARY', procedure(const Caller: TPSExec; const OrgName: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
-    begin
-      InitSevenZipLibrary(Stack.GetString(PStart));
-    end);
     RegisterScriptFunc('EXTRACTARCHIVE', procedure(const Caller: TPSExec; const OrgName: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     begin
       ExtractArchiveRedir(ScriptFuncDisableFsRedir, Stack.GetString(PStart), Stack.GetString(PStart-1), Stack.GetString(PStart-2), Stack.GetBool(PStart-3), TOnExtractionProgress(Stack.GetProc(PStart-4, Caller)));

+ 0 - 1
Projects/Src/Shared.ScriptFunc.pas

@@ -540,7 +540,6 @@ initialization
     'function IsMsiProductInstalled(const UpgradeCode: String; const PackedMinVersion: Int64): Boolean;',
     'function InitializeBitmapImageFromIcon(const BitmapImage: TBitmapImage; const IconFilename: String; const BkColor: TColor; const AscendingTrySizes: TArrayOfInteger): Boolean;',
     'procedure Extract7ZipArchive(const ArchiveFileName, DestDir: String; const FullPaths: Boolean; const OnExtractionProgress: TOnExtractionProgress);',
-    'procedure Init7ZipLibrary(const DllFilename: String);',
     'procedure ExtractArchive(const ArchiveFilename, DestDir, Password: String; const FullPaths: Boolean; const OnExtractionProgress: TOnExtractionProgress);',
     'function Debugging: Boolean;',
     'function StringJoin(const Separator: String; const Values: TArrayOfString): String;',

+ 1 - 0
Projects/Src/Shared.SetupSectionDirectives.pas

@@ -44,6 +44,7 @@ type
     ssAppVersion,
     ssArchitecturesAllowed,
     ssArchitecturesInstallIn64BitMode,
+    ssArchiveExtraction,
     ssASLRCompatible,
     ssBackColor,
     ssBackColor2,

+ 3 - 2
Projects/Src/Shared.Struct.pas

@@ -86,7 +86,7 @@ const
     ('Unknown', 'x86', 'x64', 'Arm32', 'Arm64');
 
 const
-  SetupHeaderStrings = 33;
+  SetupHeaderStrings = 34;
   SetupHeaderAnsiStrings = 4;
 type
   TSetupHeader = packed record
@@ -97,7 +97,8 @@ type
       DefaultUserInfoSerial, AppReadmeFile, AppContact, AppComments,
       AppModifyPath, CreateUninstallRegKey, Uninstallable, CloseApplicationsFilter,
       SetupMutex, ChangesEnvironment, ChangesAssociations,
-      ArchitecturesAllowed, ArchitecturesInstallIn64BitMode, CloseApplicationsFilterExcludes: String;
+      ArchitecturesAllowed, ArchitecturesInstallIn64BitMode, CloseApplicationsFilterExcludes,
+      SevenZipLibraryName: String;
     LicenseText, InfoBeforeText, InfoAfterText, CompiledCodeText: AnsiString;
     NumLanguageEntries, NumCustomMessageEntries, NumPermissionEntries,
       NumTypeEntries, NumComponentEntries, NumTaskEntries, NumDirEntries,