Modifying a string in resource of an exe

后端 未结 4 1806
醉梦人生
醉梦人生 2021-01-03 16:03

How do I modify buffer in following code then save the changes in resource of the executable? I\'m looking for something like SetString(handle,index,buffe

4条回答
  •  一生所求
    2021-01-03 16:42

    I've found the answer using Google. (English translation from Chinese) Thanks anyways everyone!

    procedure UpdateResString(AFileName, ANewString: string; AStringIdent: Integer);
      procedure WriteToArray(AArray: TByteDynArray; AData: Word; var APos: Integer);
      begin
        AArray[APos] := Lo(AData);
        AArray[APos + 1] := Hi(AData);
        Inc(APos, 2);
      end;
    
      function ReadFromArray(AArray: TByteDynArray; APos: Integer): Word;
      begin
        Result := AArray[APos] + AArray[APos + 1] * 16;
      end;
    
    var
      hModule, hResInfo, hUpdate: THandle;
      ResData, TempData: TByteDynArray;
      wsNewString: WideString;
      iSection, iIndexInSection: Integer;
      i, iLen, iSkip, iPos: Integer;
    begin
      hModule := LoadLibrary(PChar(AFileName));
      if hModule = 0 then
        raise Exception.CreateFmt('file %s failed to load.', [AFileName]);
    
      // Calculate the resource string area and the string index in that area
      iSection := AStringIdent div 16 + 1;
      iIndexInSection := AStringIdent mod 16;
    
      // If the resource already exists, then read it out of the original data
      hResInfo := FindResource(hModule, MakeIntResource(iSection), RT_STRING);
      if hResInfo <> 0 then
      begin
        iLen := SizeOfResource(hModule, hResInfo);
        SetLength(ResData, iLen);
        CopyMemory(ResData, LockResource(LoadResource(hModule, hResInfo)), iLen);
      end;
      // Should first close the file, and then update
      FreeLibrary(hModule);
      // Calculate the new data is written to location
      wsNewString := WideString(ANewString);
      iLen := Length(wsNewString);
      iPos := 0;
      for i := 0 to iIndexInSection do
      begin
        if iPos > High(ResData) then
          SetLength(ResData, iPos + 2);
        if i <> iIndexInSection then
        begin
          iSkip := (ReadFromArray(ResData, iPos) + 1) * 2;
          Inc(iPos, iSkip);
        end;
      end;
    
      // Delete the original data and the data behind the temporary
      // storage of data to be added
      iSkip := (ReadFromArray(ResData, iPos) + 1) * 2;
      TempData := Copy(ResData, iPos + iSkip, Length(ResData) - iSkip);
      SetLength(ResData, iPos);
      SetLength(ResData, iPos + (iLen + 1) * 2 + Length(TempData));
    
      // Write new data
      WriteToArray(ResData, iLen, iPos);
      for i := 1 to iLen do
        WriteToArray(ResData, Ord(wsNewString[i]), iPos);
      // Write back to the original data
      for i := 0 to High(TempData) do
        ResData[iPos + i] := TempData[i];
    
      // Write the data back to file
      hUpdate := BeginUpdateResource(PChar(AFileName), False);
      if hUpdate = 0 then
        raise Exception.CreateFmt(
          'cannot write file %s. Please check whether it is open or set read-only.',
          [AFileName]);
    
      UpdateResource(hUpdate, RT_STRING, MakeIntResource(iSection), LANG_NEUTRAL,
        ResData, Length(ResData));
      EndUpdateResource(hUpdate, False);
    end;
    

提交回复
热议问题