user1332636
user1332636

Reputation: 31

Convert one delphi code line to c++

How can I write that line in c++?

with delphi code (not this code posted here) i will write that record filled with some info to exe file and with c++ code i will read thhis record and pass the info to the struct

This is the code in delphi

type
 TSettings = record
    sFileName: String[50]; 
    siInstallFolder: Byte; 
    bRunFile: Boolean;
   ...
  end;

..
var
i: dword;
sZdData: PChar;
Settings :Tsettings;
begin
....
     ZeroMemory(@Settings, sizeof(Tsettings));
      settings := Tsettings(Pointer(@sZdData[i])^); // this code to c++

c++ code (hope the rest is OK)

struct TSettings{
    char sFileName[50]; 
    byte siInstallFolder; 
    bool bRunFile;
   ...
}  Settings;

...
DWORD i;
LPBYTE sZdData;

         ZeroMemory(&Settings, sizeof(TSettings));
      Settings = ????? // im failing here i dunno what to do // i need same as in delphi code above

and sory for my bad english .. :(

this is the delphi code

function GetInfoSettings(FileName: String; // filename from where to get data
                        var lpData: PChar; // where to write data
                        var dwSettingsLen: DWORD // returns the length of all bound files
                        ): Boolean;
var
  hFile: THandle;
  DosHeader: TImageDosHeader;
  NtHeaders: TImageNtHeaders;
  SectionHeader: TImageSectionHeader;
  dwReadBytes, dwOrginalFileSize, dwFileSize, dwSettingsLength: DWORD;
begin
  Result := False;
  hFile :=  Createfile(PChar(FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
  SetFilePointer(hFile, 0, nil, FILE_BEGIN);
  ReadFile(hFile, DosHeader, sizeof(DosHeader), dwReadBytes, nil);
  if dwReadBytes = sizeof(DosHeader) then
  begin
    SetFilePointer(hFile, DosHeader._lfanew, nil, FILE_BEGIN);
    ReadFile(hFile, NtHeaders, sizeof(NtHeaders), dwReadBytes, nil);
    if dwReadBytes = sizeof(NtHeaders) then
    begin
      SetFilePointer(hFile, sizeof(SectionHeader) * (NtHeaders.FileHeader.NumberOfSections -1), nil, FILE_CURRENT);
      ReadFile(hFile, SectionHeader, sizeof(SectionHeader), dwReadBytes, nil);
      dwOrginalFileSize := SectionHeader.PointerToRawData + SectionHeader.SizeOfRawData;
      dwFileSize := GetFileSize(hFile, nil);
      dwSettingsLength := dwFileSize - dwOrginalFileSize;
      if dwSettingsLength > 0 then
      begin
        SetFilePointer(hFile, dwOrginalFileSize, nil, FILE_BEGIN);
        GetMem(lpData, dwSettingsLength);
        ReadFile(hFile, lpData^, dwSettingsLength, dwReadBytes, nil);
        if dwReadBytes = dwSettingsLength then
        begin
          Result := True;
          dwSettingsLen := dwSettingsLength;
        end;
      end;
    end;
  end;
  CloseHandle(hFile);
end;

and here i get the info or the binded file ...

var i, // here will be saved how much bytes are already done .. dwDaSize: DWORD; // length of data after all sections .. dwFilenaam,sFileName :string; sZdData: PChar; // here will be all data after "EOF" (End of all sections data) // the filename where the file will be extracted ..

  Settings: Tsettings;


// writting
  hFile: THandle;
  lpNumberOfBytesWritten: DWORD;
begin
  GetMem(dwFilenaam, MAX_PATH);
  GetModuleFileName(GetModuleHandle(nil), dwFilenaam, MAX_PATH);
  if GetInfos(dwFilenaam, sZdData, dwDaSize) then
  begin
    i := 0;
    repeat

      ZeroMemory(@Settings, sizeof(Tsettings));
      settings := Tsettings(Pointer(@sZdData[i])^);

my try (i know this code looks garbage LOL) maybe not?

bool getSettingsInfo(LPSTR FileName, LPBYTE lpdata, DWORD dwSettingsLen)
{
    HANDLE HandleFile ;
    DWORD  dwReadBytes;
    DWORD dwOrginalFileSize;
    DWORD dwFileSize;
    DWORD dwSettingsLength; 
    PIMAGE_DOS_HEADER pidh ;
    PIMAGE_NT_HEADERS pinh ;
    PIMAGE_SECTION_HEADER pish;

    return  false;
    HandleFile =  CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, 0,OPEN_EXISTING,0, NULL); 
    SetFilePointer(HandleFile, 0,0, FILE_BEGIN);
        ReadFile(HandleFile, pidh, sizeof(pidh), &dwReadBytes,NULL); 
    if (dwReadBytes == sizeof(pidh))
     {
     SetFilePointer(HandleFile, pidh->e_lfanew , NULL, FILE_BEGIN);
     ReadFile(HandleFile, pidh,sizeof(pinh), &dwReadBytes, NULL); 
    if (dwReadBytes == sizeof(pinh)) 
    {
      SetFilePointer(HandleFile, sizeof(pish) * (pinh->FileHeader.NumberOfSections -1), NULL, FILE_CURRENT);
      ReadFile(HandleFile, pish, sizeof(pinh), &dwReadBytes, NULL);
      dwOrginalFileSize = pish->PointerToRawData + pish->SizeOfRawData;
      dwFileSize = GetFileSize(HandleFile, NULL);
      dwSettingsLength = dwFileSize - dwOrginalFileSize;
      if (dwSettingsLength > 0) 
      {

        SetFilePointer(HandleFile, dwOrginalFileSize, NULL, FILE_BEGIN);
        realloc(lpdata, dwSettingsLength);
        ReadFile(HandleFile, lpdata, dwSettingsLength, &dwReadBytes, NULL);
        if (dwReadBytes == dwSettingsLength) 
        {
         return true;
          dwSettingsLen = dwSettingsLength;
        }
      }
    }
  }
  CloseHandle(HandleFile);
} 

code to extract info ...

  DWORD i; // here will be saved how much bytes are already done ..
  DWORD dwDaSize; // length of data after all sections ..

  LPSTR dwFilenaam; 
  LPBYTE sZdData; // here will be all data after "EOF" (End of all sections data)
  LPSTR sFileName;// the filename where the file will be extracted ..

  char * Installpath;
  char * buffer;

  HFILE hFile;
  DWORD lpNumberOfBytesWritten;

  memset(dwFilenaam,0, MAX_PATH);
  GetModuleFileName(GetModuleHandle(NULL), dwFilenaam, MAX_PATH);
  if (getSettingsInfo(dwFilenaam, sZdData, dwDaSize) == true)
  {
      i = 0;
    //  REPEAT


      ZeroMemory(&Settings, sizeof(TSettings));

Settings = ???

Upvotes: 1

Views: 1015

Answers (3)

Adrian Maire
Adrian Maire

Reputation: 14865

Probably a bit late, but in case it helps.

Looking for a close equivalence, we get probably something like:

#include <array>
#include <cstdint>
#include <cstring>

struct TSettings
{
    std::array<wchar_t,50> sFileName;
    std::byte siInstallFolder;
    bool bRunFile;
};

uint32_t i;
wchar_t* sZdData;
TSettings Settings;
    
memset(&Settings, 0, sizeof(TSettings));
Settings = *reinterpret_cast<TSettings*>(&(sZdData[i]));


Here is a slightly more elaborated version:

#include <array>
#include <cassert>
#include <cstdint>
#include <iostream>
#include <string>

using Buff = std::array<char, 300>;

struct Settings
{
    std::array<wchar_t,50> sFileName;
    uint8_t siInstallFolder = 0;
    bool bRunFile = false;
};


auto write_settings_in_buffer( Buff& buff, const Settings& s, size_t pos=0) -> void
{
    assert(buff.size() > sizeof(Settings)+pos);
    *reinterpret_cast<Settings*>(buff.data()+pos) = s;
}

auto read_settings_from_buffer( Settings& s, const Buff& buff, size_t pos=0) -> void
{
    assert(buff.size() > sizeof(Settings)+pos);
    s = *reinterpret_cast<const Settings*>(&(buff.data()[pos]));
}

auto print_settings( const Settings& s) -> void
{
    std::wcout << 
        s.sFileName.data() << " : " << 
        s.siInstallFolder << " - " << 
        s.bRunFile << std::endl;
}

auto main() -> int
{
    const size_t idx = 5;
    
    Settings origSettings{L"Hi world!", 42, true};
    
    Buff buff;
    write_settings_in_buffer(buff, origSettings, idx); 
    
    Settings destSetting;
    read_settings_from_buffer(destSetting, buff, idx);
    
    print_settings(destSetting);
}

https://onlinegdb.com/RlTd8GT_Y

Upvotes: 0

Mehmet Fide
Mehmet Fide

Reputation: 1794

It should be easier in C than Delphi:

typedef struct 
{
     uchar length ; // shortstrings have an implicit length byte
     char sFileName[50]; 
     byte siInstallFolder; 
     bool bRunFile;  // one byte, 1=true, 0=false  any other value undefined
     ...
} TSettings;

TSettings settings;
DWORD i;
LPBYTE sZdData;

settings = *(TSettings*)(&sZdData[i]);

This will call memcpy, not because of casting, because of assigning TSettings structure. You can access without copying if you use pointer to TSettings:

TSettings* pSettings;
DWORD i; 
LPBYTE sZdData;

pSettings = (TSettings*)(&sZdData[i]);
printf("%d\n", pSettings->siInstallFolder); // example

By the way, be careful for alignment. Total structure size can exceed your expectation because of gaps between items.

Upvotes: 0

Marco van de Voort
Marco van de Voort

Reputation: 26361

  struct TSettings{
     uchar length ; // shortstrings have an implicit length byte
     char sFileName[50]; 
     byte siInstallFolder; 
     bool bRunFile;  // one byte, 1=true, 0=false  any other value undefined
     ...
   }  Settings;


  DWORD i;
  LPBYTE sZdData;

  ZeroMemory(&Settings, sizeof(TSettings));   

  literally it is something like
    Settings = (struct Settings)  (*((void *)&sZDData[i])

  essentially it does

  memcpy (&sZDData[i],&settings,sizeof(TSettings));

What it does is take the address of the i-th element of sZSdata ( @sZDDATA[i]) and cast it to an untyped pointer. (equivalent in C++ (void*)(&sZDData[i])) )

Then comes the funky part, derefence it (^ as postfix operator in pascal, * as prefix operator in C) (essentially the result of that being the address the (void) ptr points to, a block of memory without length data attached to it).

When that is assigned to settings, that apparantly means move as many bytes as the size of the lvalue (= sizeof(settings)) bytes from that address into the lvalue (settings).

It's a very funky construct and I'm not sure if I have seen it before. I check to both asm level in Delphi and FPC, and they behaved the same.

Upvotes: 0

Related Questions