{ fpolestorage.pas Writes an OLE document using the OLE virtual layer. Note: Compatibility with previous version (fpolestorage.pas). } unit fpolebasic; {$ifdef fpc} {$mode delphi} {$endif} interface uses Classes, SysUtils, uvirtuallayer_ole; type { Describes an OLE Document } TOLEDocument = record // Information about the document Stream: TStream; // Stream: TMemoryStream; end; { TOLEStorage } TOLEStorage = class private public procedure WriteOLEFile(AFileName: string; AOLEDocument: TOLEDocument; const AOverwriteExisting: Boolean = False; const AStreamName: String='Book'); procedure WriteOLEStream(AStream: TStream; AOLEDocument: TOLEDocument; const AStreamName: String='Book'); procedure ReadOLEFile(AFileName: string; AOLEDocument: TOLEDocument; const AStreamName: String='Book'); procedure ReadOLEStream(AStream: TStream; AOLEDocument: TOLEDocument; const AStreamName: String='Book'); procedure FreeOLEDocumentData(AOLEDocument: TOLEDocument); end; implementation uses fpsStrings; {@@ ---------------------------------------------------------------------------- Writes the OLE document specified in AOLEDocument to the file with name AFileName. The routine will fail if the file already exists, or if the directory where it should be placed doesn't exist. -------------------------------------------------------------------------------} procedure TOLEStorage.WriteOLEFile(AFileName: string; AOLEDocument: TOLEDocument; const AOverwriteExisting: Boolean; const AStreamName: String = 'Book'); var RealFile: TFileStream; begin if FileExists(AFileName) then begin if AOverwriteExisting then DeleteFile(AFileName) // In Ubuntu it seems that fmCreate does not erase an existing file. // Therefore, we delete it manually else raise EStreamError.CreateFmt(rsFileAlreadyExists, [AFileName]); end; RealFile := TFileStream.Create(AFileName, fmCreate); try WriteOLEStream(RealFile, AOLEDocument, AStreamName); finally RealFile.Free; end; end; procedure TOLEStorage.WriteOLEStream(AStream: TStream; AOLEDocument: TOLEDocument; const AStreamName: String = 'Book'); var fsOLE: TVirtualLayer_OLE; VLAbsolutePath: String; OLEStream: TStream; tmpStream: TStream; // workaround to compiler bug, see bug 22370 begin VLAbsolutePath := '/' + AStreamName; // Virtual layer always uses absolute paths fsOLE := TVirtualLayer_OLE.Create(AStream); try fsOLE.Format; // Initialize and format the OLE container; OLEStream := fsOLE.CreateStream(VLAbsolutePath, fmCreate); try // woraround for bug 22370 tmpStream := AOLEDocument.Stream; tmpStream.Position := 0; // Ensures that stream is at the beginning // previous code: AOLEDocument.Stream.Position := 0; OLEStream.CopyFrom(tmpStream, tmpStream.Size); finally OLEStream.Free; end; finally fsOLE.Free; end; end; {@@ ---------------------------------------------------------------------------- Reads an OLE file. -------------------------------------------------------------------------------} procedure TOLEStorage.ReadOLEFile(AFileName: string; AOLEDocument: TOLEDocument; const AStreamName: String = 'Book'); var RealFile: TFileStream; begin RealFile := TFileStream.Create(AFileName, fmOpenRead or fmShareDenyNone); try ReadOLEStream(RealFile, AOLEDocument, AStreamName); finally RealFile.Free; end; end; procedure TOLEStorage.ReadOLEStream(AStream: TStream; AOLEDocument: TOLEDocument; const AStreamName: String = 'Book'); var fsOLE: TVirtualLayer_OLE; OLEStream: TStream; VLAbsolutePath: UTF8String; begin VLAbsolutePath := '/' + AStreamName; //Virtual layer always use absolute paths. fsOLE := TVirtualLayer_OLE.Create(AStream); try fsOLE.Initialize(); //Initialize the OLE container. OLEStream := fsOLE.CreateStream(VLAbsolutePath, fmOpenRead); try if Assigned(OLEStream) then begin if not Assigned(AOLEDocument.Stream) then AOLEDocument.Stream := TMemoryStream.Create else (AOLEDocument.Stream as TMemoryStream).Clear; AOLEDocument.Stream.CopyFrom(OLEStream, OLEStream.Size); end; finally OLEStream.Free; end; finally fsOLE.Free; end; end; {@@ ---------------------------------------------------------------------------- Frees all internal objects storable in a TOLEDocument structure -------------------------------------------------------------------------------} procedure TOLEStorage.FreeOLEDocumentData(AOLEDocument: TOLEDocument); begin if Assigned(AOLEDocument.Stream) then FreeAndNil(AOLEDocument.Stream); end; end.