Recent

Author Topic: TMemIniFile does not support ADS (alternate data streams)  (Read 4197 times)

CCRDude

  • Hero Member
  • *****
  • Posts: 600
TMemIniFile does not support ADS (alternate data streams)
« on: August 29, 2016, 04:16:51 pm »
On Windows, additional information can be stored alongside files in ADS - alternate data streams.

One example for this is the information whether a file has been downloaded from the Internet, which gets stored in a stream called :Zone.Identifier, which basically is an Ini file.

In Delphi, passing "file::Zone.Identifier" to TMemIniFile.Create opens this stream.

On Lazarus (1.6, FPC 3.0.0), this fails.

Has anyone else come across this and has a simple workaround?

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11459
  • FPC developer.
Re: TMemIniFile does not support ADS (alternate data streams)
« Reply #1 on: August 29, 2016, 06:05:55 pm »
Try opening a tfilestream and reading the INI then with ini.loadstream() or so.

CCRDude

  • Hero Member
  • *****
  • Posts: 600
Re: TMemIniFile does not support ADS (alternate data streams)
« Reply #2 on: August 30, 2016, 11:27:45 am »
Thank you, I did not think of that! For such a small operation, TIniFile is fine. And while I don't like too many IFDEFs for differences, I can live with that and simply proceed to the next unit tests :)

Code: Pascal  [Select][+][-]
  1. function SetFileZone(const AFilename: string; const AZone: integer): boolean;
  2. var
  3.    sFilenameWithStream: string;
  4.    {$IFDEF FPC}
  5.    fs: TFileStream;
  6.    oif: TIniFile;
  7.    {$ELSE FPC}
  8.    mif: TMemIniFile;
  9.    {$ENDIF FPC}
  10. begin
  11.    Result := False;
  12.    sFilenameWithStream := AFilename + SFileSuffix;
  13.    try
  14.       {$IFDEF FPC}
  15.       fs := TFileStream.Create(sFilenameWithStream, fmOpenReadWrite or fmShareDenyNone);
  16.       try
  17.          fs.Seek(0, soFromBeginning);
  18.          oif := TIniFile.Create(fs);
  19.          try
  20.             oif.WriteInteger('ZoneTransfer', 'ZoneId', AZone);
  21.             Result := True;
  22.          finally
  23.             oif.Free;
  24.          end;
  25.       finally
  26.          fs.Free;
  27.       end;
  28.       {$ELSE FPC}
  29.       mif := TMemIniFile.Create(sFilenameWithStream);
  30.       try
  31.          mif.WriteInteger('ZoneTransfer', 'ZoneId', AZone);
  32.          mif.UpdateFile;
  33.          Result := True;
  34.       finally
  35.          mif.Free;
  36.       end;
  37.       {$ENDIF FPC}
  38.    except
  39.       on E: Exception do begin
  40.          DebugLogger.LogException(E, 'SetFileZone');
  41.       end;
  42.    end;
  43. end;

Thaddy

  • Hero Member
  • *****
  • Posts: 14393
  • Sensorship about opinions does not belong here.
Re: TMemIniFile does not support ADS (alternate data streams)
« Reply #3 on: August 30, 2016, 11:41:37 am »
I suspect that a simple Tinifile DOES support alternate data streams... As long as the can be identified as .ini
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

CCRDude

  • Hero Member
  • *****
  • Posts: 600
Re: TMemIniFile does not support ADS (alternate data streams)
« Reply #4 on: August 31, 2016, 05:22:47 pm »
Just tried, because it would have simplified code, but it isn't so.

Which is interesting, since TMemIniFile uses TIniFile for loading, which uses FileExists and a TStringList.LoadFromFile, which again uses TFileStream. So it's either the TFileStream modes that branch into something different, or something even more deep inside.

There we would be at the different file handling underneath I've written about on bugs.freepascal.org as well, in case you're the same Thaddy :)

 

TinyPortal © 2005-2018