Search code examples
winapiinno-setuppascalscriptcryptoapi

Accessing memory pointed to by PAnsiChar in Inno Setup Pascal Script


Need to Use the Win32 encryption API to convert password to encrypted blob before passing to child process.

Trying to use [email protected] API to perform the encryption. The function is returning success. But I'm facing issue while accessing the returned encrypted blob.

Tried to use the StrPas() to convert the PAnsiChar to AnsiString, but I get "Invalid identifier" error.

const
  CRYPTPROTECT_LOCAL_MACHINE = $4;

type
  DataBlob = record
    cbData: Longword;
    pbData: PAnsiChar;
  end;

function CryptProtectData(var pDataIn: DataBlob;
  szDataDescr, pOptionalEntropy, pvReserved, pPromptStruct : DWORD;
  dwFlags: DWORD; var pDataOut: DataBlob): Boolean;
  external '[email protected] stdcall delayload';

var
  Password: AnsiString;

function Encrypt(): Boolean;
var
  DataBlobIn, DataBlobOut: DataBlob
  EncryptStr: AnsiString;
begin
  DataBlobIn.cbData := Length(Password);
  DataBlobIn.pbData := Password;
  if CryptProtectData(DataBlobIn, 0, 0, 0, 0, CRYPTPROTECT_LOCAL_MACHINE, DataBlobOut) then
  begin
    Log('Success');

    { Using StrPas gives an 'unknown identifier error' }
    EncryptStr := StrPas(DataBlobOut.pbData);
  end;
end;

The size of the return memory blob is DataBlobOut.cbData, but how to access the memory blob returned in DataBlobOut.pbData?

Can you please point to some sample code where we can access the memory of length X?


Solution

  • To copy data from a memory pointer to an Inno Setup buffer-like variable (such as AnsiString), you can use RtlMoveMemory WinAPI function:

    procedure RtlMoveMemory(Dest: AnsiString; Source: PAnsiChar; Len: Integer);
      external '[email protected] stdcall';
    

    You can use it like:

    // Allocate memory
    SetLength(EncryptStr, DataBlobOut.cbData);
    // Copy data
    RtlMoveMemory(EncryptStr, DataBlobOut.pbData, DataBlobOut.cbData);