unit UFileSummaryInfo;
interface
uses Windows,
ActiveX, ComObj;
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_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.
//I've changed the numbers of the original constants to get the right PID...
//e.g. I decreased all const with 2...
// Summary Information
PID_TITLE = 0; //2;
PID_SUBJECT = 1;
PID_AUTHOR = 2;
PID_KEYWORDS = 3;
PID_COMMENTS = 4;
PID_TEMPLATE = 5;
PID_LASTAUTHOR = 6;
PID_REVNUMBER = 7;
PID_EDITTIME = 8;
PID_LASTPRINTED = 9;
PID_CREATE_DTM = 10;
PID_LASTSAVE_DTM = 11;
PID_PAGECOUNT = 12;
PID_WORDCOUNT = 13;
PID_CHARCOUNT = 14;
PID_THUMBNAIL = 15;
PID_APPNAME = 16;
PID_SECURITY = 17;
// 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;
function GetFileSummaryInfo(const FileName: WideString;
GUID_SummaryType: TGUID; PID_InfoType: cardinal): WideString;
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';
implementation
uses SysUtils;
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;
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 GetFileSummaryInfo(const FileName: WideString;
GUID_SummaryType: TGUID; PID_InfoType: cardinal): WideString;
var
Stg: IStorage;
PropSetStg: IPropertySetStorage;
PropStg: IPropertyStorage;
PropVariant: array of TPropVariant;
PropEnum: IEnumSTATPROPSTG;
PropStat: STATPROPSTG;
PIDCount: Integer;
HRslt: HResult;
PropSpec: array of TPropSpec;
begin
Result:='';
//I use the STGFMT_ANY const instead of the original STGFMT_FILE that didn't work at all...
if(StgOpenStorageEx(pwidechar(FileName),STGM_READ or STGM_SHARE_DENY_WRITE,
STGFMT_ANY,0,nil,nil,@IID_IPropertySetStorage,Stg) = S_OK) then
begin
PropSetStg := Stg as IPropertySetStorage;
If (PropSetStg.Open(GUID_SummaryType,
STGM_READ or STGM_SHARE_EXCLUSIVE,
PropStg)) = S_OK Then
Begin
If PropStg.Enum(PropEnum) = S_OK then
Begin
PIDCount := 0;
HRslt := PropEnum.Next(1, PropStat, nil);
while HRslt = S_OK do
begin
inc(PIDCount);
SetLength(PropSpec,PIDCount);
PropSpec[PIDCount-1].ulKind := PRSPEC_PROPID;
PropSpec[PIDCount-1].propid := PropStat.propid;
HRslt := PropEnum.Next(1, PropStat, nil);
end;
SetLength(PropVariant,PIDCount);
HRslt := PropStg.ReadMultiple(PIDCount, @PropSpec[0], @PropVariant[0]);
// Use this to get the Incomming PID_InfoType
if HRslt <> S_FALSE then
Begin
if PropVariant[PID_InfoType].vt = VT_LPSTR then
if Assigned(PropVariant[PID_InfoType].pszVal) then
Result := PropVariant[PID_InfoType].pszVal;
End;
//Use This to loop through all PID's
//(and ignore the incomming PID_InfoType)
{
for k := 0 to PIDCount -1 do
begin
S := '';
if PropVariant[k].vt = VT_LPSTR then
if Assigned(PropVariant[k].pszVal) then
S := PropVariant[k].pszVal;
S := Format(IntToStr(k)+' '+PropertyPIDToCaption(PropSpec[k].Propid)+ ' %s',[s]);
if S <> '' then Result := Result + S + #13;
end;
}
End;
End;
end;
end;
end.