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

📄 setupldr.dpr

📁 源代码
💻 DPR
📖 第 1 页 / 共 2 页
字号:
    xor edx, edx
    lock or [eax], edx
  end;

var
  SysInfo: TSystemInfo;
  CurAddr: Pointer;
  MemInfo: TMemoryBasicInformation;
  ChangedProtection: Boolean;
  OrigProtect: DWORD;
  Offset: Cardinal;
begin
  { Get system's page size }
  GetSystemInfo(SysInfo);

  CurAddr := Pointer(Module);
  if VirtualQuery(CurAddr, MemInfo, SizeOf(MemInfo)) = 0 then
    Exit;

  { Perform this loop until we find a region beyond the end of the file }
  while MemInfo.AllocationBase = Pointer(Module) do begin
    { We can only force committed pages into RAM.
      We do not want to trigger guard pages and confuse the application. }
    if (MemInfo.State = MEM_COMMIT) and (MemInfo.Protect and PAGE_GUARD = 0) then begin
      ChangedProtection := False;

      { Determine if the pages in this region are nonwriteable }
      if (MemInfo.Protect = PAGE_NOACCESS) or
         (MemInfo.Protect = PAGE_READONLY) or
         (MemInfo.Protect = PAGE_EXECUTE) or
         (MemInfo.Protect = PAGE_EXECUTE_READ) then begin
        { Nonwriteable region, make it writeable (with the least protection) }
        if VirtualProtect(MemInfo.BaseAddress, MemInfo.RegionSize,
           PAGE_EXECUTE_READWRITE, @OrigProtect) then
          ChangedProtection := True;
      end;

      { Write to every page in the region.
        This forces the page to be in RAM and swapped to the paging file. }
      Offset := 0;
      while Offset < MemInfo.RegionSize do begin
        Touch(PDWORD(Cardinal(MemInfo.BaseAddress) + Offset)^);
        Inc(Offset, SysInfo.dwPageSize);
      end;

      { If we changed the protection, change it back }
      if ChangedProtection then
        VirtualProtect(MemInfo.BaseAddress, MemInfo.RegionSize, OrigProtect,
          @OrigProtect);
    end;

    { Get next region }
    Cardinal(CurAddr) := Cardinal(MemInfo.BaseAddress) + MemInfo.RegionSize;
    if VirtualQuery(CurAddr, MemInfo, SizeOf(MemInfo)) = 0 then
      Break;
  end;
end;

const
  { Exit codes that are returned by SetupLdr.
    Note: Setup also returns exit codes with the same numbers. }
  ecInitializationError = 1;     { Setup failed to initialize. }
  ecCancelledBeforeInstall = 2;  { User clicked Cancel before the actual
                                   installation started. }

var
  SelfFilename: String;
  SourceF, DestF: TFile;
  SizeOfFile: Longint;
  ExeHeader: TSetupLdrExeHeader;
  OffsetTable: TSetupLdrOffsetTable;
  TempDir: String;
  TempFile: String;
  TestID: TSetupID;
  P: Pointer;
  Reader: TCompressedBlockReader;
  I: Integer;
begin
  try
    { Ensure all of SetupLdr is paged in so that in the case of a disk spanning
      install Windows will never complain when the disk/CD containing SetupLdr
      is ejected. }
    RunImageLocally(HInstance);

    ProcessCommandLine;

    SelfFilename := NewParamStr(0);
    SourceF := TFile.Create(SelfFilename, fdOpenExisting, faRead, fsRead);
    try
      SizeOfFile := SourceF.Size.Lo;
      SourceF.Seek(SetupLdrExeHeaderOffset);
      SourceF.ReadBuffer(ExeHeader, SizeOf(ExeHeader));
      if (ExeHeader.ID <> SetupLdrExeHeaderID) or
         (ExeHeader.OffsetTableOffset <> not ExeHeader.NotOffsetTableOffset) or
         (ExeHeader.OffsetTableOffset + SizeOf(OffsetTable) > SizeOfFile) then
        SetupCorruptError;
      SourceF.Seek(ExeHeader.OffsetTableOffset);
      SourceF.ReadBuffer(OffsetTable, SizeOf(OffsetTable));
      if (OffsetTable.ID <> SetupLdrOffsetTableID) or
         (GetCRC32(OffsetTable, SizeOf(OffsetTable) - SizeOf(OffsetTable.TableCRC)) <> OffsetTable.TableCRC) or
         (SizeOfFile < OffsetTable.TotalSize) then
        SetupCorruptError;

      SourceF.Seek(OffsetTable.Offset0);
      SourceF.ReadBuffer(TestID, SizeOf(TestID));
      if TestID <> SetupID then
        SetupCorruptError;
      try
        Reader := TCompressedBlockReader.Create(SourceF, TLZMADecompressor);
        try
          SECompressedBlockRead(Reader, SetupHeader, SizeOf(SetupHeader),
            SetupHeaderStrings);

          LanguageEntryCount := SetupHeader.NumLanguageEntries;
          LanguageEntries := AllocMem(LanguageEntryCount * SizeOf(TSetupLanguageEntry));
          for I := 0 to LanguageEntryCount-1 do
            SECompressedBlockRead(Reader, LanguageEntries[I], SizeOf(LanguageEntries[I]),
              SetupLanguageEntryStrings);
        finally
          Reader.Free;
        end;
      except
        on ECompressDataError do
          SetupCorruptError;
      end;

      ActivateDefaultLanguage;

      if Win32Platform = VER_PLATFORM_WIN32s then begin
        MessageBox(0, PChar(FmtSetupMessage1(msgNotOnThisPlatform, 'Win32s')),
          PChar(SetupMessages[msgErrorTitle]), MB_OK or MB_ICONSTOP);
        Abort;
      end;

      { Show the startup prompt. If this is enabled, SetupHeader.AppName won't
        have constants. }
      if not(shDisableStartupPrompt in SetupHeader.Options) and
         not InitDisableStartupPrompt and
         (MessageBox(0, PChar(FmtSetupMessage1(msgSetupLdrStartupMessage, SetupHeader.AppName)),
           PChar(SetupMessages[msgSetupAppTitle]), MB_YESNO or MB_ICONQUESTION) <> IDYES) then begin
        SetupLdrExitCode := ecCancelledBeforeInstall;
        Abort;
      end;

      { Create a temporary directory, and extract the embedded setup program
        there }
      Randomize;
      GenerateTempDir(TempDir);
      TempFile := GenerateUniqueName(TempDir, '.tmp');

      SourceF.Seek(OffsetTable.OffsetEXE);

      try
        P := nil;
        DestF := TFile.Create(TempFile, fdCreateAlways, faWrite, fsNone);
        try
          GetMem(P, OffsetTable.UncompressedSizeEXE);
          FillChar(P^, OffsetTable.UncompressedSizeEXE, 0);
          try
            Reader := TCompressedBlockReader.Create(SourceF, TLZMADecompressor);
            try
              Reader.Read(P^, OffsetTable.UncompressedSizeEXE);
            finally
              Reader.Free;
            end;
          except
            on ECompressDataError do
              SetupCorruptError;
          end;
          TransformCallInstructions(P^, OffsetTable.UncompressedSizeEXE, False);
          if GetCRC32(P^, OffsetTable.UncompressedSizeEXE) <> OffsetTable.CRCEXE then
            SetupCorruptError;
          { Preallocate the bytes to avoid file system fragmentation }
          DestF.Seek(OffsetTable.UncompressedSizeEXE);
          DestF.Truncate;
          DestF.Seek(0);
          DestF.WriteBuffer(P^, OffsetTable.UncompressedSizeEXE);
        finally
          FreeMem(P);
          DestF.Free;
        end;
      except
        on E: EFileError do begin
          SetLastError(E.ErrorCode);
          RaiseLastError(msgLdrCannotCreateTemp);
        end;
      end;

      FreeAndNil(SourceF);

      { Create SetupLdrWnd, which is used by Setup to communicate with
        SetupLdr }
      SetupLdrWnd := CreateWindowEx(0, 'STATIC', 'InnoSetupLdrWindow', 0,
        0, 0, 0, 0, HWND_DESKTOP, 0, HInstance, nil);
      Longint(OrigWndProc) := SetWindowLong(SetupLdrWnd, GWL_WNDPROC,
        Longint(@SetupLdrWndProc));

      { Now execute Setup. Use the exit code it returns as our exit code. }
      ExecAndWait(TempFile, Format('/SL4 $%x %s %d %d %s',
        [SetupLdrWnd, AddQuotes(SelfFilename), OffsetTable.Offset0,
         OffsetTable.Offset1, GetCmdTail]),
        SetupLdrExitCode);
    finally
      SourceF.Free;
      if TempFile <> '' then
        { Even though Setup has terminated by now, the system may still have
          the file locked for a short period of time (esp. on multiprocessor
          systems), so use DelayDeleteFile to delete it. }
        DelayDeleteFile(TempFile, 12);
      if TempDir <> '' then
        RemoveDirectory(PChar(TempDir));
      if SetupLdrWnd <> 0 then
        { SetupLdrWnd must be destroyed before RestartComputer is called,
          otherwise SetupLdrWndProc would deny the shutdown request }
        DestroyWindow(SetupLdrWnd);
      if Assigned(LanguageEntries) then begin
        Finalize(LanguageEntries[0], LanguageEntryCount);
        FreeMem(LanguageEntries);
        LanguageEntries := nil;
      end;
    end;
    if RestartSystem then
      RestartComputer;
  except
    ShowExceptionMsg;
    { If SetupLdrExitCode wasn't explicitly set earlier, default to
      ecInitializationError }
    if SetupLdrExitCode = 0 then
      SetupLdrExitCode := ecInitializationError;
  end;
  Halt(SetupLdrExitCode);
end.

⌨️ 快捷键说明

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