save IStorage into stream

In last days I worked with IStorage interface. For my task I needed the function to save the IStorage into file and/or stream and later to load from file/stream into IStorage.

I wrote the next useful functions:

  procedure CreateOLEDoc(const AFileName: WideString; AStorage: IStorage);
  var
    hr: Integer;
    NewStorage: IStorage;
  begin
    hr := StgCreateDocfile(PWideChar(AFileName), STGM_DIRECT or STGM_READWRITE or STGM_CREATE or
                           STGM_SHARE_EXCLUSIVE, 0, NewStorage);
    if (hr = S_OK) then
    begin
      AStorage.CopyTo(0, nil, nil, NewStorage);
      NewStorage.Commit(STGC_DEFAULT);
      NewStorage := nil
    end
  end;

  procedure WriteStorageToStream(AStorage: IStorage; AStream: TStream);
  var
    NewStorage: IStorage;

    LockBytes: ILockBytes;
    HGlob: HGLOBAL;
    intfStream, myStream: IStream;
    oldStatstg: TStatStg;
    cbRead, cbWritten: Comp;
  begin
    HGlob := GlobalAlloc(GMEM_MOVEABLE, 0);
    try
      OleCheck(CreateILockBytesOnHGlobal(HGlob, False, LockBytes));
      OleCheck(StgCreateDocfileOnILockBytes(LockBytes, STGM_DIRECT or STGM_READWRITE or STGM_CREATE or
                           STGM_SHARE_EXCLUSIVE, 0, NewStorage));
      OleCheck(AStorage.CopyTo(0, nil, nil, NewStorage));
      NewStorage.Commit(STGC_DEFAULT);
      OleCheck(CreateStreamOnHGlobal(HGlob, True, intfStream));

      myStream  := TStreamAdapter.Create(AStream);
      try
        OleCheck(intfStream.Stat(oldStatstg, 1));
        OleCheck(intfStream.Seek(0, 0, cbWritten));

        OleCheck(intfStream.CopyTo(myStream, oldStatstg.cbSize, cbRead, cbWritten));
      finally
        myStream  := nil;
        intfStream := nil;
      end;
    finally
      NewStorage := nil;
      GlobalFree(HGlob);
    end;

    AStream.Position := 0;
  end;

Comments are closed.