⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 install.pas

📁 源代码
💻 PAS
📖 第 1 页 / 共 5 页
字号:
    for CurDirNumber := 0 to Entries[seDir].Count-1 do
      with PSetupDirEntry(Entries[seDir][CurDirNumber])^ do begin
        if ShouldProcessEntry(WizardComponents, WizardTasks, Components, Tasks, Languages, Check) then begin
          DebugNotifyEntry(seDir, CurDirNumber);
          NotifyBeforeInstallEntry(BeforeInstall);
          Flags := [];
          if doUninsNeverUninstall in Options then Include(Flags, mdNoUninstall);
          if doDeleteAfterInstall in Options then Include(Flags, mdDeleteAfterInstall);
          if doUninsAlwaysUninstall in Options then Include(Flags, mdAlwaysUninstall);
          N := RemoveBackslashUnlessRoot(ExpandConst(DirName));
          MakeDir(N, Flags);
          AddAttributesToFile(N, Attribs);
          ApplyPermissions(N, PermissionsEntry);
          NotifyAfterInstallEntry(AfterInstall);
        end;
      end;
  end;

  procedure WriteUninstallMsgData(const F: TFile);
  var
    UninstLangOpts: TUninstLangOptions;
    LangEntry: PSetupLanguageEntry;
  begin
    FillChar(UninstLangOpts, SizeOf(UninstLangOpts), 0);
    UninstLangOpts.ID := UninstLangOptionsID;
    UninstLangOpts.DialogFontName := LangOptions.DialogFontName;
    UninstLangOpts.DialogFontSize := LangOptions.DialogFontSize;
    LangEntry := Entries[seLanguage][ActiveLanguage];
    F.WriteBuffer(LangEntry.Data[1], Length(LangEntry.Data));
    F.WriteBuffer(UninstLangOpts, SizeOf(UninstLangOpts));
  end;

  procedure MarkExeHeader(const F: TFile; const ModeID: Longint);
  begin
    F.Seek(SetupExeModeOffset);
    F.WriteBuffer(ModeID, SizeOf(ModeID));
  end;

  procedure BindUninstallMsgDataToExe(const F: TFile);
  var
    UninstallerMsgTail: TUninstallerMsgTail;
  begin
    UninstallerMsgTail.ID := UninstallerMsgTailID;
    UninstallerMsgTail.Offset := F.Size.Lo;
    F.SeekToEnd;
    WriteUninstallMsgData(F);
    F.WriteBuffer(UninstallerMsgTail, SizeOf(UninstallerMsgTail));
  end;

  procedure ProcessFileEntry(const CurFile: PSetupFileEntry;
    ASourceFile, ADestName: String; const FileLocationFilenames: TStringList;
    const AExternalSize: Integer64);

    procedure InstallFont(const Filename, FontName: String;
      const AddToFontTableNow: Boolean);
    var
      K: HKEY;
      LastError: DWORD;
    begin
      if IsNT then begin
        if not SetIniString('Fonts', FontName, Filename, '') then
          LogFmt('Failed to create [Fonts] entry in WIN.INI. (%d)', [GetLastError]);
      end
      else begin
        if RegOpenKeyEx(HKEY_LOCAL_MACHINE, NEWREGSTR_PATH_SETUP + '\Fonts', 0,
           KEY_SET_VALUE, K) = ERROR_SUCCESS then begin
          if RegSetValueEx(K, PChar(FontName), 0, REG_SZ, PChar(Filename),
             Length(Filename)+1) <> ERROR_SUCCESS then
            Log('Failed to set value in Fonts registry key.');
          RegCloseKey(K);
        end
        else
          Log('Failed to open Fonts registry key.');
      end;

      if AddToFontTableNow then begin
        LastError := 0;
        repeat
          SetLastError(0);  { does AddFontResource set last error code? }
          if AddFontResource(PChar(Filename)) <> 0 then begin
            SendNotifyMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
            Break;
          end;
          LastError := GetLastError;
        until AbortRetryIgnoreMsgBox(FmtSetupMessage(msgErrorFunctionFailed,
          ['AddFontResource', IntToStr(LastError)]),
          SetupMessages[msgEntryAbortRetryIgnore]);
      end;
    end;

    procedure SetFileLocationFilename(const LocationEntry: Integer;
      Filename: String);
    var
      LowercaseFilename: String;
      Hash: Longint;
      I: Integer;
    begin
      Filename := PathExpand(Filename);
      LowercaseFilename := PathLowercase(Filename);
      Hash := GetCRC32(LowercaseFilename[1], Length(LowercaseFilename));
      { If Filename was already associated with another LocationEntry,
        disassociate it. If we *don't* do this, then this script won't
        produce the expected result:
          [Files]
          Source: "fileA"; DestName: "file2"
          Source: "fileB"; DestName: "file2"
          Source: "fileA"; DestName: "file1"
        1. It extracts fileA under the name "file2"
        2. It extracts fileB under the name "file2"
        3. It copies file2 to file1, thinking a copy of fileA was still
           stored in file2.
      }
      for I := 0 to FileLocationFilenames.Count-1 do
        if (Longint(FileLocationFilenames.Objects[I]) = Hash) and
           (PathLowercase(FileLocationFilenames[I]) = LowercaseFilename) then begin
          FileLocationFilenames[I] := '';
          FileLocationFilenames.Objects[I] := nil;
          Break;
        end;
      FileLocationFilenames[LocationEntry] := Filename;
      FileLocationFilenames.Objects[LocationEntry] := Pointer(Hash);
    end;

    procedure ApplyPermissions(const Filename: String; const PermsEntry: Integer);
    var
      Attr: DWORD;
      P: PSetupPermissionEntry;
    begin
      if PermsEntry <> -1 then begin
        Attr := GetFileAttributes(PChar(Filename));
        if (Attr <> $FFFFFFFF) and (Attr and FILE_ATTRIBUTE_DIRECTORY = 0) then begin
          LogFmt('Setting permissions on file: %s', [Filename]);
          P := Entries[sePermission][PermsEntry];
          if not GrantPermissionOnFile(Filename, TGrantPermissionEntry(Pointer(P.Permissions)^),
             Length(P.Permissions) div SizeOf(TGrantPermissionEntry)) then
            Log('Failed to set permissions on file.');
        end;
      end;
    end;

  var
    ProgressUpdated: Boolean;
    PreviousProgress: Integer64;
    LastOperation: String;
    CurFileLocation: PSetupFileLocationEntry;
    SourceFile, DestFile, TempFile, FontFilename: String;
    DestFileExists, DestFileExistedBefore, CheckedDestFileExistedBefore,
      TempFileLeftOver, AllowFileToBeDuplicated, ReplaceOnRestart: Boolean;
    ExistingFileAttr: Integer;
    Failed: String;
    CurFileVersionInfoValid: Boolean;
    CurFileVersionInfo, ExistingVersionInfo: TFileVersionNumbers;
    CurFileDateValid, ExistingFileDateValid: Boolean;
    CurFileMD5, ExistingFileMD5: TMD5Digest;
    AllowTimeStampComparison: Boolean;
    DeleteFlags: Longint;
    CurFileDate, ExistingFileDate: TFileTime;
    RegisterRec: PRegisterFilesListRec;
    RetriesLeft: Integer;
    LastError: DWORD;
    DestF, SourceF: TFile;
  label Retry, Skip;
  begin
    Log('-- File entry --');

    CheckedDestFileExistedBefore := False;
    DestFileExistedBefore := False;  { prevent warning }

    if CurFile^.LocationEntry <> -1 then
      CurFileLocation := PSetupFileLocationEntry(Entries[seFileLocation][CurFile^.LocationEntry])
    else
      CurFileLocation := nil;

  Retry:
    TempFile := '';
    TempFileLeftOver := False;
    ProgressUpdated := False;
    PreviousProgress := CurProgress;
    LastOperation := '';
    Failed := '';
    try
      try
        ReplaceOnRestart := False;
        DeleteFlags := 0;
        if foRegisterServer in CurFile^.Options then
          DeleteFlags := DeleteFlags or utDeleteFile_RegisteredServer;
        if foRegisterTypeLib in CurFile^.Options then
          DeleteFlags := DeleteFlags or utDeleteFile_RegisteredTypeLib;
        if foUninsRestartDelete in CurFile^.Options then
          DeleteFlags := DeleteFlags or utDeleteFile_RestartDelete;
        if foUninsRemoveReadOnly in CurFile^.Options then
          DeleteFlags := DeleteFlags or utDeleteFile_RemoveReadOnly;
        FontFilename := '';

        { Determine the destination filename }
        case CurFile^.FileType of
          ftUninstExe: DestFile := UninstallExeFilename;
        else
          if ADestName = '' then
            DestFile := ExpandConst(CurFile^.DestName)
          else
            DestFile := ADestName;
        end;

        { Update the filename label }
        SetFilenameLabelText(DestFile, True);
        LogFmt('Dest filename: %s', [DestFile]);

        DestFileExists := NewFileExists(DestFile);
        if not CheckedDestFileExistedBefore then begin
          DestFileExistedBefore := DestFileExists;
          CheckedDestFileExistedBefore := True;
        end;
        if DestFileExistedBefore then
          DeleteFlags := DeleteFlags or utDeleteFile_ExistedBeforeInstall;

        if Assigned(CurFileLocation) then begin
          if foTimeStampInUTC in CurFileLocation^.Flags then
            CurFileDate := CurFileLocation^.TimeStamp
          else
            LocalFileTimeToFileTime(CurFileLocation^.TimeStamp, CurFileDate);
          CurFileDateValid := True;
        end
        else
          CurFileDateValid := GetFileDateTime(ASourceFile, CurFileDate);
        if CurFileDateValid then
          LogFmt('Time stamp of our file: %s', [FileTimeToStr(CurFileDate)])
        else
          Log('Time stamp of our file: (failed to read)');

        if foDontCopy in CurFile^.Options then begin
          Log('Skipping due to "dontcopy" flag.');
          goto Skip;
        end;

        if DestFileExists then begin
          Log('Dest file exists.');
          if foOnlyIfDoesntExist in CurFile^.Options then begin
            Log('Skipping due to "onlyifdoesntexist" flag.');
            goto Skip;
          end;

          LastOperation := SetupMessages[msgErrorReadingExistingDest];

          ExistingFileDateValid := GetFileDateTime(DestFile, ExistingFileDate);
          if ExistingFileDateValid then
            LogFmt('Time stamp of existing file: %s', [FileTimeToStr(ExistingFileDate)])
          else
            Log('Time stamp of existing file: (failed to read)');

          { Skip if it's a protected system file.
            Note: We don't call IsProtectedSystemFile anymore on Windows Me
            even though it supports WFP. Two users reported that installs ran
            very slowly on 4.2.1, and with the help of one of the users, the
            cause was narrowed down to this call. For him, it was taking 6
            seconds per call. I have no idea what would cause it to be so
            slow; it only took a few milliseconds in my tests on Windows Me. }
          if (CurFile^.FileType = ftUserFile) and IsNT then
            if IsProtectedSystemFile(DestFile) then begin
              Log('File is protected by Windows File Protection. Skipping.');
              goto Skip;
            end;

          { Compare version info }
          if not(foIgnoreVersion in CurFile^.Options) then begin
            AllowTimeStampComparison := False;
            { Read version info of file being installed }
            if Assigned(CurFileLocation) then begin
              CurFileVersionInfoValid := foVersionInfoValid in CurFileLocation^.Flags;
              CurFileVersionInfo.MS := CurFileLocation^.FileVersionMS;
              CurFileVersionInfo.LS := CurFileLocation^.FileVersionLS;
            end
            else
              CurFileVersionInfoValid := GetVersionNumbers(PathExpand(ASourceFile),
                CurFileVersionInfo);
            if CurFileVersionInfoValid then
              LogFmt('Version of our file: %u.%u.%u.%u',
                [LongRec(CurFileVersionInfo.MS).Hi, LongRec(CurFileVersionInfo.MS).Lo,
                 LongRec(CurFileVersionInfo.LS).Hi, LongRec(CurFileVersionInfo.LS).Lo])
            else
              Log('Version of our file: (none)');
            { Does the existing file have version info? }
            if GetVersionNumbers(PathExpand(DestFile), ExistingVersionInfo) then begin
              { If the file being installed has no version info, or the existing
                file is a newer version... }
              LogFmt('Version of existing file: %u.%u.%u.%u',
                [LongRec(ExistingVersionInfo.MS).Hi, LongRec(ExistingVersionInfo.MS).Lo,
                 LongRec(ExistingVersionInfo.LS).Hi, LongRec(ExistingVersionInfo.LS).Lo]);
              if not CurFileVersionInfoValid or
                 ((ExistingVersionInfo.MS > CurFileVersionInfo.MS) or
                  ((ExistingVersionInfo.MS = CurFileVersionInfo.MS) and
                   (ExistingVersionInfo.LS > CurFileVersionInfo.LS))) then begin
                if not(foPromptIfOlder in CurFile^.Options) or
                   (MsgBox(DestFile + SNewLine2 + SetupMessages[msgExistingFileNewer],
                    '', mbError, MB_YESNO) <> ID_NO) then begin
                  Log('Existing file is a newer version. Skipping.');
                  goto Skip;
                end;
              end
              else begin
                { If the existing file and the file being installed are the same
                  version... }
                if (ExistingVersionInfo.MS = CurFileVersionInfo.MS) and
                   (ExistingVersionInfo.LS = CurFileVersionInfo.LS) and
                   not(foOverwriteSameVersion in CurFile^.Options) then begin
                  if foReplaceSameVersionIfContentsDiffer in CurFile^.Options then begin
                    { Get the two files' MD5 sums and compare them }
                    if TryToGetMD5OfFile(DestFile, ExistingFileMD5) then begin
                      if Assigned(CurFileLocation) then
                        CurFileMD5 := CurFileLocation^.MD5Sum
                      else begin
                        LastOperation := SetupMessages[msgErrorReadingSource];
                        { This GetMD5OfFile call could raise an exception, but
                          it's very unlikely since we were already able to
                          successfully read the file's version info. }
                        CurFileMD5 := GetMD5OfFile(ASourceFile);
                        LastOperation := SetupMessages[msgErrorReadingExistingDest];
                      end;
                      { If the two files' MD5 sums are equal, skip the file }
                      if MD5DigestsEqual(ExistingFileMD5, CurFileMD5) then begin
                        Log('Existing file''s MD5 sum matches our file. Skipping.');
                        goto Skip;
                      end;
                      Log('Existing file''s MD5 sum is different from our file. Proceeding.');
                    end
                    else
                      Log('Failed to read existing file''s MD5 sum. Proceeding.');
                  end
                  else begin

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -