StgOpenStorageEx only reads .doc files. Delphi 2007

259 Views Asked by At

I am trying to acquire file properties such as Title, Subject, Author, Copyright, Comments and the various file dates. Other properties would be nice, but not required. My searches all seem to lead to variations of the code I found here as well as here. Copying and pasting the code, I had to do a bit of tweaking to make it work at all. I was finally able to get it to partially work, but only on .doc files. Other files produced "EOleSysError with message '%1 could not be found'". I thought this related to compound files, but the same error occurred with .docx and .xls files.

I have tried STGFMT_STORAGE, STGFMT_FILE, STGFMT_ANY, and STGFMT_DOCFILE, but the only one that works is STGFMT_ANY. Again, that only works on .doc files. Even on .doc files, it doesn't return dates, although I have only treated them as string values. Here's my code, and the results.

Output in a TListView

unit u_fSummary;

interface

uses Windows, ComObj, ActiveX, Variants, Sysutils, dialogs;

function GetFileSummaryInfo(const FileName: WideString): String;
function IsNTFS(AFileName : string) : boolean;

implementation

const

FmtID_SummaryInformation: TGUID =     '{F29F85E0-4FF9-1068-AB91-08002B27B3D9}';
FMTID_DocSummaryInformation : TGUID = '{D5CDD502-2E9C-101B-9397-08002B2CF9AE}';
FMTID_UserDefinedProperties : TGUID = '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}';
IID_IPropertySetStorage : TGUID =     '{0000013A-0000-0000-C000-000000000046}';

STGFMT_STORAGE = 0; {Indicates that the file must be a compound file}

STGFMT_FILE =    3; {Indicates that the file must not be a compound file.
                    This element is only valid when using the StgCreateStorageEx
                    or StgOpenStorageEx functions to access the NTFS file system
                    implementation of the IPropertySetStorage interface.
                    Therefore, these functions return an error if the riid
                    parameter does not specify the IPropertySetStorage interface,
                    or if the specified file is not located on an NTFS file system volume.}

STGFMT_ANY =     4; {Indicates that the system will determine the file type and
                    use the appropriate structured storage or property set
                    implementation.
                    This value cannot be used with the StgCreateStorageEx function.}

STGFMT_DOCFILE = 5; {Indicates that the file must be a compound file, and is
                    similar to the STGFMT_STORAGE flag, but indicates that the
                    compound-file form of the compound-file implementation must
                    be used. For more information}


// Summary Information
 PID_TITLE        = 2;
 PID_SUBJECT      = 3;
 PID_AUTHOR       = 4;
 PID_KEYWORDS     = 5;
 PID_COMMENTS     = 6;
 PID_TEMPLATE     = 7;
 PID_LASTAUTHOR   = 8;
 PID_REVNUMBER    = 9;
 PID_EDITTIME     = 10;
 PID_LASTPRINTED  = 11;
 PID_CREATE_DTM   = 12;
 PID_LASTSAVE_DTM = 13;
 PID_PAGECOUNT    = 14;
 PID_WORDCOUNT    = 15;
 PID_CHARCOUNT    = 16;
 PID_THUMBNAIL    = 17;
 PID_APPNAME      = 18;
 PID_SECURITY     = 19;

 // Document Summary Information
 PID_CATEGORY     = 2;
 PID_PRESFORMAT   = 3;
 PID_BYTECOUNT    = 4;
 PID_LINECOUNT    = 5;
 PID_PARCOUNT     = 6;
 PID_SLIDECOUNT   = 7;
 PID_NOTECOUNT    = 8;
 PID_HIDDENCOUNT  = 9;
 PID_MMCLIPCOUNT  = 10;
 PID_SCALE        = 11;
 PID_HEADINGPAIR  = 12;
 PID_DOCPARTS     = 13;
 PID_MANAGER      = 14;
 PID_COMPANY      = 15;
 PID_LINKSDIRTY   = 16;
 PID_CHARCOUNT2   = 17;

function IsNTFS(AFileName : string) : boolean;
var
fso, drv : OleVariant;
begin
  IsNTFS := False;
  fso := CreateOleObject('Scripting.FileSystemObject');
  drv := fso.GetDrive(fso.GetDriveName(AFileName));
  if drv.FileSystem = 'NTFS' then
    IsNTFS := True;
end;

function StgOpenStorageEx (
 const pwcsName : POleStr;  //Pointer to the path of the
                            //file containing storage object
 grfMode : LongInt;         //Specifies the access mode for the object
 stgfmt : DWORD;            //Specifies the storage file format
 grfAttrs : DWORD;          //Reserved; must be zero
 pStgOptions : Pointer;     //Address of STGOPTIONS pointer
 reserved2 : Pointer;       //Reserved; must be zero
 riid : PGUID;              //Specifies the GUID of the interface pointer
 out stgOpen :              //Address of an interface pointer
 IStorage ) : HResult; stdcall; external 'ole32.dll';


function GetFileSummaryInfo(const FileName: WideString): String;
var
  I: Integer;
  PropSetStg: IPropertySetStorage;
  PropSpec: array of TPropSpec;
  PropStg: IPropertyStorage;
  PropVariant: array of TPropVariant;
  Rslt: HResult;
  S: String;
  Stg: IStorage;
  PropEnum: IEnumSTATPROPSTG;
  HR : HResult;
  PropStat: STATPROPSTG;
  k : integer;

      function _PropertyPIDToCaption(const ePID: Cardinal): string;
      begin
        case ePID of
          PID_TITLE:
            Result := 'Title';
          PID_SUBJECT:
            Result := 'Subject';
          PID_AUTHOR:
            Result := 'Author';
          PID_KEYWORDS:
            Result := 'Keywords';
          PID_COMMENTS:
            Result := 'Comments';
          PID_TEMPLATE:
            Result := 'Template';
          PID_LASTAUTHOR:
            Result := 'Last Saved By';
          PID_REVNUMBER:
            Result := 'Revision Number';
          PID_EDITTIME:
            Result := 'Total Editing Time';
          PID_LASTPRINTED:
            Result := 'Last Printed';
          PID_CREATE_DTM:
            Result := 'Create Time/Date';
          PID_LASTSAVE_DTM:
            Result := 'Last Saved Time/Date';
          PID_PAGECOUNT:
            Result := 'Number of Pages';
          PID_WORDCOUNT:
            Result := 'Number of Words';
          PID_CHARCOUNT:
            Result := 'Number of Characters';
          PID_THUMBNAIL:
            Result := 'Thumbnail';
          PID_APPNAME:
            Result := 'Creating Application';
          PID_SECURITY:
            Result := 'Security';
        else
         Result := '$' + IntToHex(ePID, 8);
        end
      end;

begin
 Result := '';
  try

    OleCheck(StgOpenStorageEx(StringToOleStr(FileName), STGM_READ or STGM_SHARE_DENY_WRITE,
      STGFMT_ANY, 0, nil,  nil, @IID_IPropertySetStorage, stg));

    PropSetStg := Stg as IPropertySetStorage;

    OleCheck(PropSetStg.Open(FmtID_SummaryInformation,
      STGM_READ or STGM_SHARE_EXCLUSIVE, PropStg));

    OleCheck(PropStg.Enum(PropEnum));
    i := 0;

    hr := PropEnum.Next(1, PropStat, nil);
    while hr = S_OK do
    begin
      inc(I);
      SetLength(PropSpec,I);
      PropSpec[i-1].ulKind := PRSPEC_PROPID;
      PropSpec[i-1].propid := PropStat.propid;
      hr := PropEnum.Next(1, PropStat, nil);
    end;

    SetLength(PropVariant,i);
    Rslt := PropStg.ReadMultiple(i, @PropSpec[0], @PropVariant[0]);

    if Rslt <>  S_FALSE then;
    begin
    for k := 0 to i -1 do
      begin
        S := '';
        if PropVariant[k].vt = VT_LPSTR then
          if Assigned(PropVariant[k].pszVal) then
           S := PropVariant[k].pszVal;
        S := Trim(Format(_PropertyPIDToCaption(PropSpec[k].Propid)+ ': %s',[s]));
        if S <> '' then Result := Result + S + #176;
      end;
    end;
  finally
  end;
end;

end.
0

There are 0 best solutions below