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

📄 ctdwork.pas

📁 Citadel v.1.6 Full Sources
💻 PAS
📖 第 1 页 / 共 3 页
字号:
      finally
        TCtdMemStream(ResStream).SetPointer(nil, 0);
        ResStream.Free;
      end;
    end;
  end;

  procedure FilterDFMs(ResList: TStringList; hExe: HModule;
    UpdateHandle: THandle);
  begin
    ShowMsg('Filtering DFMs');
    FilterMadExcept(ResList, hExe, UpdateHandle);
  end;

var
  hExe: HModule;
  hCtdTools: THandle;
  Discard: Boolean;
  ResList: TStringList;
  i: Integer;
  PackageFileName: array[0..MAX_PATH] of Char;
  UpdateHandle: THandle;
  DFMOrgSize,
  DFMDstSize: Double;
  WExeFileName: array[0..255] of WideChar;
begin
  ResList := TStringList.Create;
  try
    if not FileExists(ExeFileName) then
      raise Exception.Create(Format('File ''%s'' not found', [ExeFileName]));

    hExe := LoadLibraryEx(PChar(ExeFileName), 0,
              DONT_RESOLVE_DLL_REFERENCES or LOAD_LIBRARY_AS_DATAFILE);
    if hExe = 0 then
      {$ifdef D6UP}RaiseLastOSError;{$else}RaiseLastWin32Error;{$endif D6UP}
    try
      ShowMsg('Checking resources...');
      if not EnumResourceNames(HExe, RT_RCDATA,
               @EnumResourceNamesCallback, Longint(@ResList)) then
        {$ifndef D6Up}
        RaiseLastWin32Error;
        {$else}
        RaiseLastOSError;
        {$endif D6Up}
      ResList.Sorted := True;
    finally
      FreeLibrary(hExe);
    end;

    GetModuleFileName(HInstance, PackageFileName, SizeOf(PackageFileName));
    hCtdTools := LoadLibrary(PChar(ExtractFilePath(PackageFileName) + 'CtdT.ctd'));
    if hCtdTools = 0 then
      raise Exception.Create('Can''t load ' + ExtractFilePath(PackageFileName) + 'CtdT.ctd');
    try
      @CtdBeginUpdRes := GetProcAddress(HCtdTools, 'CtdBeginUpdRes');
      @CtdEndUpdRes   := GetProcAddress(HCtdTools, 'CtdEndUpdRes');
      @CtdUpdRes      := GetProcAddress(HCtdTools, 'CtdUpdRes');
      @CtdGetRes      := GetProcAddress(HCtdTools, 'CtdGetRes');

      UpdateHandle := CtdBeginUpdRes(
                        StringToWideChar(ExeFileName, WExeFileName, SizeOf(WExeFileName) div 2),
                        False);
      if UpdateHandle = 0
      then
        {$ifndef D6Up}
        RaiseLastWin32Error
        {$else}
        RaiseLastOSError
        {$endif D6Up}
      else
      begin
        Discard := True;
        try
          FilterDFMs(ResList, hExe, UpdateHandle);

          Inc(Steps, ResList.Count * 2);
          if DoCompress then
            Inc(Steps, ResList.Count * 2);
          if DoPack      then
            Inc(Steps, ResList.Count * 2);
          if DoCrypt  then
            Inc(Steps, ResList.Count * 2);

          SetProgressSteps(Steps);

          DFMCount := 0;
          for i := 0 to ResList.Count-1 do
          begin
            if ProcessDFM(ResList[i], DoPack, DoCompress, DoCrypt, DoRunTimeLog,
              Password, UpdateHandle, DFMOrgSize, DFMDstSize) then
            begin
              Inc(DFMCount);
              TotDFMOrgSize := TotDFMOrgSize + DFMOrgSize;
              TotDFMDstSize := TotDFMDstSize + DFMDstSize;
            end;
            if DoLog and (not DoRunTimeLog) then
              SecLog.Clear;
          end;

          Discard := False;
        finally
          if not CtdEndUpdRes(UpdateHandle, Discard) then
            {$ifndef D6Up}
            RaiseLastWin32Error;
            {$else}
            RaiseLastOSError;
            {$endif D6Up}
        end;
      end;
    finally
      FreeLibrary(hCtdTools);
    end;
  finally
    ResList.Free;
  end;
end;

procedure TCtdWork.ProcessExe(const DoLogValue, DoRunTimeLog: Boolean; 
  Steps: Integer);

  function GetOSVersion: String;
  const
    cOsUnknown = -1;
    cOsWin95   =  0;
    cOsWin98   =  1;
    cOsWin98SE =  2;
    cOsWinME   =  3;
    cOsWinNT   =  4;
    cOsWin2000 =  5;
    cOsWinXP   =  6;
  var
    osVerInfo: TOSVersionInfo;
    majorVer,
    minorVer,
    OSCode: Integer;
  begin
    osVerInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);

    if GetVersionEx(osVerInfo) then
    begin
      majorVer := osVerInfo.dwMajorVersion;
      minorVer := osVerInfo.dwMinorVersion;

      case osVerInfo.dwPlatformId of
        VER_PLATFORM_WIN32_NT : // Windows NT/2000
        begin
          if majorVer <= 4
          then OSCode := cOsWinNT
          else if((majorVer = 5) and (minorVer = 0))
          then OSCode := cOsWin2000
          else if((majorVer = 5) and (minorVer = 1))
          then OSCode := cOsWinXP
          else OSCode := cOsUnknown;
        end;
        VER_PLATFORM_WIN32_WINDOWS : // Windows 9x/ME
        begin
          if((majorVer = 4) and (minorVer = 0))
          then OSCode := cOsWin95
          else if((majorVer = 4) and (minorVer = 10))
          then
          begin
            if(osVerInfo.szCSDVersion[1] = 'A')
            then OSCode := cOsWin98SE
            else OSCode := cOsWin98;
          end
          else if((majorVer = 4) and (minorVer = 90))
          then OSCode := cOsWinME
          else OSCode := cOsUnknown;
        end;
        else OSCode := cOsUnknown;
      end;
    end
    else OsCode := cOsUnknown;

    case OSCode of
      cOsUnknown: Result := '(unknown OS)';
      cOsWin95  : Result := 'Windows 95';
      cOsWin98  : Result := 'Windows 98';
      cOsWin98SE: Result := 'Windows 98 SE';
      cOsWinME  : Result := 'Windows Millennium';
      cOsWinNT  : Result := 'Windows NT';
      cOsWin2000: Result := 'Windows 2000 / NT 5';
      cOsWinXP  : Result := 'Microsoft Windows XP';
      else Result := 'Microsoft Windows';
    end;
  end;

  procedure SaveLog(var LogFile: TextFile; LogStrings: TStringList);
  var
    i: Integer;
  begin
    if LogStrings.Count > 0 then
    begin
      for i := 0 to LogStrings.Count-1 do
        WriteLn(LogFile, LogStrings[i]);
    end;
  end;

type
  TRemoveRelocResult = (rrOk, rrNotPE, rrLibrary, rrNoRelocations);
  TRemoveRelocations = function(FileName: PAnsiChar;
    var OriginalSize, NewSize: Cardinal): TRemoveRelocResult; stdcall;
var
  Msg: String;
  Handle,
  DFMCount: Integer;
  Savings,
  TotDFMOrgSize,
  TotDFMDstSize,
  InitialFileSize,
  FinalFileSize: Double;
  hCtdTools: THandle;
  RemoveRelocations: TRemoveRelocations;
  PackageFileName: array[0..MAX_PATH] of Char;
  LogFile: TextFile;
  Start: TDateTime;
  OriginalSize,
  NewSize: Cardinal;
  ExeFileName,
  ResName,
  IDEVersion: String;
  Config: TCtdConfig;
begin
  DoLog := DoLogValue;

  MainLog.Clear;
  SecLog .Clear;

  Start := Now;
  try
    try
      PreProcess(ExeFileName, ResName);
      ReadResConfig(ExeFileName, ResName, Config);

      if Config.Encrypt and (Config.Password = '') then
        raise Exception.Create(
          'Please select a password of at least 8 characters in length.');
      Handle := FileOpen(ExeFileName, 0);
      try
        InitialFileSize := GetFileSize(Handle, nil);
      finally
        FileClose(Handle);
      end;

      if not(Config.Compress or Config.Pack or Config.Encrypt or Config.RmvReloc) then
        raise Exception.Create('Nothing to do');

      {$ifdef CtdNoPack}
      if Config.Pack then
        raise Exception.Create('Pack not supported');
      {$endif CtdNoPack}
      {$ifdef CtdNoCrypt}
      if Config.Encrypt then
        raise Exception.Create('Encryption not supported');
      {$endif CtdNoCrypt}

      if Config.Compress or Config.Pack or Config.Encrypt then
      begin
        TotDFMOrgSize := 0;
        TotDFMDstSize := 0;
        DFMCount      := 0;
        ProcessDFMs(ExeFileName, Config.Pack, Config.Compress, Config.Encrypt,
          DoRunTimeLog,
          {$ifdef CtdDoTrial}'trial'{$else}Config.Password{$endif CtdDoTrial},
          Steps, TotDFMOrgSize, TotDFMDstSize, DFMCount);
      end;

      if Config.RmvReloc then
      begin
        ShowMsg('Removing relocations...');
        GetModuleFileName(HInstance, PackageFileName, SizeOf(PackageFileName));
        hCtdTools := LoadLibrary(PChar(ExtractFilePath(PackageFileName) + 'CtdT.ctd'));
        if hCtdTools = 0 then
          raise Exception.Create('Can''t load ' + ExtractFilePath(PackageFileName) + 'CtdT.ctd');
        try
          @RemoveRelocations := GetProcAddress(hCtdTools, 'RemoveRelocations');
          case RemoveRelocations(PAnsiChar(AnsiString(ExeFileName)), OriginalSize, NewSize) of
            rrOk           :
            begin
              Savings := OriginalSize - NewSize;
              ShowMsg(Format('  %.0n bytes saved', [Savings]));
            end;
            rrNotPE        : ShowMsg('The PE format is unknown');
            rrLibrary      : ShowMsg('Must be an exe');
            rrNoRelocations: ShowMsg('Relocation section non-existent');
          end;
          ProgressStep;
        finally
          FreeLibrary(hCtdTools);
        end;
      end;
    except
      on E: Exception do
      begin
        ShowMsg(E.ClassName + ': ' + E.Message);
        raise;
      end;
    end;

    Handle := FileOpen(ExeFileName, 0);
    try
      Msg := Format('%d DFMs processed - %.0n bytes', [DFMCount, TotDFMOrgSize]);
      if TotDFMOrgSize > TotDFMDstSize then
        Msg := Format('%s -> %.0n (%%%d ratio)',
          [Msg, TotDFMDstSize, Round((TotDFMDstSize * 100) / TotDFMOrgSize)]);
      ShowMsg(Msg);
      FinalFileSize := GetFileSize(Handle, nil);
      ShowMsg(Format('Initial file size: %.0n bytes',  [InitialFileSize]));
      LastMsg := Format('Final file size: %.0n bytes', [FinalFileSize]);
      if Config.Compress or Config.RmvReloc then
        LastMsg := Format('%s (%%%d ratio)',
          [LastMsg, Round((FinalFileSize * 100) / InitialFileSize)]);
      ShowMsg(LastMsg);
    finally
      FileClose(Handle);
    end;
  finally
    if DoLog then
    begin
      AssignFile(LogFile, ExtractFilePath(ExeFileName) + 'ctdlog.txt');
      Rewrite(LogFile);
      try
        WriteLn(LogFile,
          'Design time log started at ' +
          FormatDateTime('dd/mm/yy hh:nn:ss', Start));
        WriteLn(LogFile, Format('Citadel %s (%s)', [Name, CtdVersion]));
        IDEVersion := GetIDEVersion;
        if IDEVersion <> '' then
          WriteLn(LogFile, IDEVersion);
        WriteLn(LogFile, GetOSVersion);

        SaveLog(LogFile, MainLog);
        SaveLog(LogFile, SecLog);
        WriteLn(LogFile, 'Log finished at ' + FormatDateTime('hh:nn:ss', Time));
      finally
        CloseFile(LogFile);
        MainLog.Clear;
        SecLog .Clear;
      end;
    end;
  end;
end;

procedure TCtdWork.ProgressStep(const StepSize: Integer);
begin
end;

procedure TCtdWork.SetProgressSteps(const Steps: Integer);
begin
end;

procedure TCtdWork.ShowMsg(const Msg: String; LogMode: TCtdLogModes);
begin
  if DoLog then
  begin
    if lmMain in LogMode then
      MainLog.Add(Msg);
    if lmSecondary in LogMode then
      SecLog .Add(Msg);
  end;
end;

end.

⌨️ 快捷键说明

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