2

In my setup scenario at the end of the installation process each client downloads application key from the server. The file consists of ~64 random bytes, binary, non-encoded. It should be stored in configuration file in installation directory.

The setup is handled with Inno Setup, which calls key generation procedure during CurStepChanged event. OLE WinHttp.WinHttpRequest.5.1 is created, POST request containing client data is sent, and binary response should be received. The response is extracted using WinHttpReq.ResponseText and stored to file using SaveStringToFile.

However the resulting file differs from this sent from the server. For example data logged on the server side:

5a7868256a890e25735f431351f023c143f0cc397e6ec01e8a81806564eaa9f4fc8a005d9035c18fa32f95daaeff34955f3f6e4bfc5051bd33a522cc2aaddac8f29a1031dcb23728250c4f0a73db6a5bcc64e1ddef71a6

is received as

5a7868256a3f0e25735f4313513f23c1433f49397e6e411e3f813f656465a9f4fc3f005d9035c13f4c2f3fdaae79343f5f3f6e4bfc505131335922492aadda456f3f1031dc323728250c4f0a73556a5b4964e1dd6971a6

(for example 6th byte is different). There are no such problems is data does not contain non-ascii data.

My first idea was that at some point encoding/decoding of the binary data to text modifies some bytes. I wanted to use IWinHttpRequest::ResponseBody to access the data in binary version instead of the text version. Passing this property results in target file being filled with ? characters instead of the data. Only ascii characters were preserved.

I also tried converting ResponseBody to pascal array of bytes, but received Type Mismatch error. The VarType for ResponseBody returns dec 8209, which maps to array and byte, but assigning ResponseBody to array of byte leads to the error above.

What is the correct way to store binary HTTP result to file in Inno Setup?

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
peku33
  • 3,628
  • 3
  • 26
  • 44

1 Answers1

1

You didn't show us your code, so it's difficult to say what problem you may have.

Though I guess that you have passed WinHttpReq.ResponseText (wide string) directly to SaveStringToFile (which takes AnsiString). This involves an implicit UTF-16 to ANSI encoding conversion, what causes loss or conversion of some characters.

This works just fine, in Unicode version of Inno Setup (the only version as of Inno Setup 6):

var
  WinHttpReq: Variant;
  S: string;
  I: Integer;
  Data: AnsiString;
begin
  WinHttpReq := CreateOleObject('WinHttp.WinHttpRequest.5.1');
  WinHttpReq.Open('GET', 'https://www.example.com/key.dat', False);
  WinHttpReq.Send('');
  if WinHttpReq.Status <> 200 then
  begin
    Log('HTTP Error: ' + IntToStr(WinHttpReq.Status) + ' ' + WinHttpReq.StatusText);
  end
    else
  begin
    S := WinHttpReq.ResponseText;
    SetLength(Data, Length(S));
    for I := 1 to Length(S) do
    begin
      Data[I] := S[I];
    end;

    SaveStringToFile(ExpandConstant('{app}\key.dat'), Data, False);
  end;
end;

The code might be inefficient for downloading large binary files. But for 64 bytes it's just ok. For larger files, one probably can use ADODB.Stream class.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992