On Windows 2000 you can right-click in Explorer to get the file properties on any
file and can associate summary information to any type of files, including even
text files.
For Word or Excel documents (compound files) the summary information is a part of
document itself.
For other files the way of storing additional information are different. This
feature are only available on volumes formatted with NTFS. The NTFS implementation
stores property sets in alternate streams of an NTFS file. The alternate streams
must be copied when the main file is copied. However, not all file systems support
such streams. For example, if an NTFS file with property sets is copied to a FAT
volume, only the data in the file is copied; the property set is lost.
First thing you probably want do is to detect whether the current volume is NTFS:
1 // IsNTFS() - Verifies whether the file's volume is NTFS
2 function IsNTFS(AFileName : string) : boolean;
3 var
4 fso, drv : OleVariant;
5 begin
6 IsNTFS := False;
7 fso := CreateOleObject('Scripting.FileSystemObject');
8 drv := fso.GetDrive(fso.GetDriveName(AFileName));
9 if drv.FileSystem = 'NTFS' then
10 IsNTFS := True;
11 end;
12
13 {But how to read these properties? Is it really nessesary to work with a streams?
14 No, NTFS file system 5.0 provides an implementation of IPropertySetStorage
15 interface for files on an NTFS volume when the files themselves are not compound
16 files. To get a pointer to the NTFS implementation of IPropertySetStorage, we have
17 to call the StgCreateStorageEx function: }
18
19 function StgOpenStorageEx (
20 const pwcsName : POleStr; //Pointer to the path of the
21 //file containing storage object
22 grfMode : LongInt; //Specifies the access mode for the object
23 stgfmt : DWORD; //Specifies the storage file format
24 grfAttrs : DWORD; //Reserved; must be zero
25 pStgOptions : Pointer; //Address of STGOPTIONS pointer
26 reserved2 : Pointer; //Reserved; must be zero
27 riid : PGUID; //Specifies the GUID of the interface pointer
28 out stgOpen : //Address of an interface pointer
29 IStorage ) : HResult; stdcall; external 'ole32.dll';
30
31
32 {All Microsoft Windows 2000 applications should use this new function,
33 StgOpenStorageEx, instead of StgOpenStorage, to take advantage of the enhanced
34 Windows 2000 Structured Storage features.
35
36 The implementation of IPropertySetStorage on NTFS file system is similar with
37 compound file implementation and available only on Windows 2000. Windows 95 and
38 Windows NT 4.0 and earlier versions cannot access this interface.
39 However, you cannot obtain the NTFS implementation of IPropertySetStorage for a
40 compound file. When opening a compound file with StgOpenStorage, specifying the
41 STGFMT_FILE enumeration value results in an error.
42
43 The next function dumps all properties of the specific file. By changing the
44 STGFMT_FILE flag in the StgOpenStorageEx call to STGMT_ANY you can open a
45 Structured Storage property set or an NTFS file system property set. }
46
47 function GetFileSummaryInfo(const FileName: WideString): string;
48
49 const
50 FmtID_SummaryInformation: TGUID = '{F29F85E0-4FF9-1068-AB91-08002B27B3D9}';
51 FMTID_DocSummaryInformation : TGUID = '{D5CDD502-2E9C-101B-9397-08002B2CF9AE}';
52 FMTID_UserDefinedProperties : TGUID = '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}';
53 IID_IPropertySetStorage : TGUID = '{0000013A-0000-0000-C000-000000000046}';
54
55 const
56 STGFMT_FILE = 3; //Indicates that the file must not be a compound file.
57 //This element is only valid when using the StgCreateStorageEx
58 //or StgOpenStorageEx functions to access the NTFS file system
59 //implementation of the IPropertySetStorage interface.
60 //Therefore, these functions return an error if the riid
61 //parameter does not specify the IPropertySetStorage interface,
62 //or if the specified file is not located on an NTFS file system
63 volume.
64
65 STGFMT_ANY = 4; //Indicates that the system will determine the file type and
66 //use the appropriate structured storage or property set
67 //implementation.
68 //This value cannot be used with the StgCreateStorageEx function.
69
70
71 // Summary Information
72 PID_TITLE = 2;
73 PID_SUBJECT = 3;
74 PID_AUTHOR = 4;
75 PID_KEYWORDS = 5;
76 PID_COMMENTS = 6;
77 PID_TEMPLATE = 7;
78 PID_LASTAUTHOR = 8;
79 PID_REVNUMBER = 9;
80 PID_EDITTIME = 10;
81 PID_LASTPRINTED = 11;
82 PID_CREATE_DTM = 12;
83 PID_LASTSAVE_DTM = 13;
84 PID_PAGECOUNT = 14;
85 PID_WORDCOUNT = 15;
86 PID_CHARCOUNT = 16;
87 PID_THUMBNAIL = 17;
88 PID_APPNAME = 18;
89 PID_SECURITY = 19;
90
91 // Document Summary Information
92 PID_CATEGORY = 2;
93 PID_PRESFORMAT = 3;
94 PID_BYTECOUNT = 4;
95 PID_LINECOUNT = 5;
96 PID_PARCOUNT = 6;
97 PID_SLIDECOUNT = 7;
98 PID_NOTECOUNT = 8;
99 PID_HIDDENCOUNT = 9;
100 PID_MMCLIPCOUNT = 10;
101 PID_SCALE = 11;
102 PID_HEADINGPAIR = 12;
103 PID_DOCPARTS = 13;
104 PID_MANAGER = 14;
105 PID_COMPANY = 15;
106 PID_LINKSDIRTY = 16;
107 PID_CHARCOUNT2 = 17;
108
109 var
110 I: Integer;
111 PropSetStg: IPropertySetStorage;
112 PropSpec: array of TPropSpec;
113 PropStg: IPropertyStorage;
114 PropVariant: array of TPropVariant;
115 Rslt: HResult;
116 S: string;
117 Stg: IStorage;
118 PropEnum: IEnumSTATPROPSTG;
119 HR : HResult;
120 PropStat: STATPROPSTG;
121 k : integer;
122
123 function PropertyPIDToCaption(const ePID: Cardinal): string;
124 begin
125 case ePID of
126 PID_TITLE:
127 Result := 'Title';
128 PID_SUBJECT:
129 Result := 'Subject';
130 PID_AUTHOR:
131 Result := 'Author';
132 PID_KEYWORDS:
133 Result := 'Keywords';
134 PID_COMMENTS:
135 Result := 'Comments';
136 PID_TEMPLATE:
137 Result := 'Template';
138 PID_LASTAUTHOR:
139 Result := 'Last Saved By';
140 PID_REVNUMBER:
141 Result := 'Revision Number';
142 PID_EDITTIME:
143 Result := 'Total Editing Time';
144 PID_LASTPRINTED:
145 Result := 'Last Printed';
146 PID_CREATE_DTM:
147 Result := 'Create Time/Date';
148 PID_LASTSAVE_DTM:
149 Result := 'Last Saved Time/Date';
150 PID_PAGECOUNT:
151 Result := 'Number of Pages';
152 PID_WORDCOUNT:
153 Result := 'Number of Words';
154 PID_CHARCOUNT:
155 Result := 'Number of Characters';
156 PID_THUMBNAIL:
157 Result := 'Thumbnail';
158 PID_APPNAME:
159 Result := 'Creating Application';
160 PID_SECURITY:
161 Result := 'Security';
162 else
163 Result := '$' + IntToHex(ePID, 8);
164 end
165 end;
166
167 begin
168 Result := '';
169 try
170 OleCheck(StgOpenStorageEx(PWideChar(FileName),
171 STGM_READ or STGM_SHARE_DENY_WRITE,
172 STGFMT_FILE,
173 0, nil, nil, @IID_IPropertySetStorage, stg));
174
175 PropSetStg := Stg as IPropertySetStorage;
176
177 OleCheck(PropSetStg.Open(FmtID_SummaryInformation,
178 STGM_READ or STGM_SHARE_EXCLUSIVE, PropStg));
179
180 OleCheck(PropStg.Enum(PropEnum));
181 I := 0;
182
183 hr := PropEnum.Next(1, PropStat, nil);
184 while hr = S_OK do
185 begin
186 inc(I);
187 SetLength(PropSpec,I);
188 PropSpec[i-1].ulKind := PRSPEC_PROPID;
189 PropSpec[i-1].propid := PropStat.propid;
190 hr := PropEnum.Next(1, PropStat, nil);
191 end;
192
193 SetLength(PropVariant,i);
194 Rslt := PropStg.ReadMultiple(i, @PropSpec[0], @PropVariant[0]);
195
196 if Rslt = S_FALSE then Exit;
197
198 for k := 0 to i -1 do
199 begin
200 S := '';
201 if PropVariant[k].vt = VT_LPSTR then
202 if Assigned(PropVariant[k].pszVal) then
203 S := PropVariant[k].pszVal;
204
205 S := Format(PropertyPIDToCaption(PropSpec[k].Propid)+ ' %s',[s]);
206 if S <> '' then Result := Result + S + #13;
207 end;
208 finally
209 end;
210 end;
|