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;