typelib.pas 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517
  1. unit typelib;
  2. {$mode objfpc}{$H+}
  3. { Typelib import routines.
  4. Creates freepascal bindings for COM objects stored in .tlb, .dll, .exe or .olb files.
  5. Copyright (C) 2011 Ludo Brands
  6. This library is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU Library General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or (at your
  9. option) any later version with the following modification:
  10. As a special exception, the copyright holders of this library give you
  11. permission to link this library with independent modules to produce an
  12. executable, regardless of the license terms of these independent modules,and
  13. to copy and distribute the resulting executable under terms of your choice,
  14. provided that you also meet, for each linked independent module, the terms
  15. and conditions of the license of that module. An independent module is a
  16. module which is not derived from or based on this library. If you modify
  17. this library, you may extend this exception to your version of the library,
  18. but you are not obligated to do so. If you do not wish to do so, delete this
  19. exception statement from your version.
  20. This program is distributed in the hope that it will be useful, but WITHOUT
  21. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  22. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
  23. for more details.
  24. You should have received a copy of the GNU Library General Public License
  25. along with this library; if not, write to the Free Software Foundation,
  26. Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  27. }
  28. interface
  29. uses
  30. Classes, SysUtils,comobj,activex,windows;
  31. {
  32. Reads type information from 'FileName' and converts it in a freepascal binding unit. The
  33. contents of the unit is returned as the function result.
  34. Returns in 'sUnitName' the unit name with '.pas' extension.
  35. Appends to 'slDependencies' the filenames of the additional typelibs needed.
  36. If bActiveX is true an ActiveXContainer descendant is created with the evenual OnEvent hooks
  37. If bActiveX is false and an event source is found an TEventSink descendant is created with the OnEvent hooks
  38. By default, the type library is extracted from the first resource of type ITypeLib.
  39. To load a different type of library resource, append an integer index to 'FileName'.
  40. Example: C:\WINDOWS\system32\msvbvm60.dll\3
  41. }
  42. function ImportTypelib(FileName: WideString;var sUnitName:string;var slDependencies:TStringList;
  43. bActiveX:boolean):string;
  44. Type
  45. { TTypeLibImporter }
  46. TTypeLibImporter = Class(TComponent)
  47. private
  48. FActiveX: Boolean;
  49. FAppendVersionNumber: Boolean;
  50. FDependencies: TStringList;
  51. FUnitSource: TStringList;
  52. FInputFileName: WideString;
  53. FOutputFileName: String;
  54. FUnitname: string;
  55. FUses : TStrings;
  56. FHeader : TStrings;
  57. FInterface : TStrings;
  58. FImplementation : TStrings;
  59. FTypes : TStrings;
  60. FEventDisp : TStrings;
  61. FEventIID : TStrings;
  62. FEventSignatures: TStrings;
  63. FEventFunctions: TStrings;
  64. FEventProperties: TStrings;
  65. FEventImplementations: TStrings;
  66. function GetDependencies: TStrings;
  67. function GetUnitSource: TStrings;
  68. procedure SetOutputFileName(AValue: String);
  69. procedure SetUnitName(AValue: string);
  70. Protected
  71. bIsCustomAutomatable,bIsInterface,bIsAutomatable,bIsExternalDecl,bIsUserDefined:boolean;
  72. // Construct unit from header, uses, interface,
  73. procedure BuildUnit; virtual;
  74. // Add to various parts of sources
  75. Procedure AddToUses(Const AUnit : String); virtual;
  76. Procedure AddToHeader(Const ALine : String; AllowDuplicate : Boolean = False);virtual;
  77. Procedure AddToHeader(Const Fmt : String; Args : Array of const; AllowDuplicate : Boolean = False);
  78. Procedure AddToInterface(Const ALine : String);virtual;
  79. Procedure AddToInterface(Const Fmt : String; Args : Array of const);
  80. Procedure AddToImplementation(Const ALine : String);virtual;
  81. Procedure AddToImplementation(Const Fmt : String; Args : Array of const);
  82. // utility functions
  83. function interfacedeclaration(iName, iDoc: string; TI: ITypeInfo; TA: LPTYPEATTR;
  84. bIsDispatch,bCreateEvents:boolean): string;
  85. function VarTypeIsAutomatable(ParamType: integer): boolean; virtual;
  86. function VarTypeToStr(ParamType: integer): string; virtual;
  87. function TypeToString(TI: ITypeInfo; TD: TYPEDESC): string; virtual;
  88. function ValidateID(id: string): boolean; virtual;
  89. // The actual routines that do the work.
  90. procedure CreateCoClasses(const TL: ITypeLib; TICount: Integer); virtual;
  91. procedure CreateForwards(const TL: ITypeLib; TICount: Integer); virtual;
  92. procedure CreateInterfaces(const TL: ITypeLib; TICount: Integer); virtual;
  93. procedure CreateRecordsUnionsAliases(const TL: ITypeLib; TICount: Integer); virtual;
  94. procedure CreateUnitHeader(const TL: ITypeLib; const LA: lpTLIBATTR); virtual;
  95. procedure ImportEnums(const TL: ITypeLib; TICount: Integer); virtual;
  96. procedure ImportGUIDs(const TL: ITypeLib; TICount: Integer); virtual;
  97. Procedure DoImportTypelib;virtual;
  98. // For the benefit of descendents;
  99. Property UsesClause : TStrings read FUses;
  100. Property Header : TStrings read FHeader;
  101. Property InterfaceSection : TStrings Read FInterface;
  102. Property ImplementationSection : TStrings Read FImplementation;
  103. Public
  104. Constructor Create(AOwner : TComponent); override;
  105. Destructor Destroy; override;
  106. Procedure Execute;
  107. Property Dependencies : TStrings Read GetDependencies;
  108. Property UnitSource : TStrings Read GetUnitSource;
  109. Published
  110. // Create ActiveXContainer descendant: default false
  111. Property ActiveX : Boolean Read FActiveX write FActiveX Default False;
  112. // Append version number to unit name.
  113. Property AppendVersionNumber : Boolean Read FAppendVersionNumber Write FAppendVersionNumber Default True;
  114. // File to read typelib from.
  115. Property InputFileName : WideString Read FInputFileName Write FInputFileName;
  116. // If set, unit source will be written to this file.
  117. Property OutputFileName : String Read FOutputFileName Write SetOutputFileName;
  118. // Set automatically by OutputFileName or by Execute
  119. Property UnitName : string Read FUnitname Write SetUnitName;
  120. end;
  121. implementation
  122. Resourcestring
  123. SErrInvalidUnitName = 'Invalid unit name : %s';
  124. function ImportTypelib(FileName: WideString;var sUnitName:string;var slDependencies:TStringList;
  125. bActiveX:boolean):string;
  126. var i:integer;
  127. begin
  128. With TTypeLibImporter.Create(Nil) do
  129. try
  130. InputFileName:=FileName;
  131. ActiveX:=bActiveX;
  132. Execute;
  133. Result:=UnitSource.Text;
  134. sUnitname:=UnitName+'.pas';
  135. if Assigned(slDependencies) then
  136. begin //add new dependencies
  137. for i:=0 to Dependencies.Count-1 do
  138. if slDependencies.IndexOf(Dependencies[i])=-1 then
  139. slDependencies.Add(Dependencies[i]);
  140. end;
  141. finally
  142. Free;
  143. end;
  144. end;
  145. function TTypeLibImporter.VarTypeIsAutomatable(ParamType:integer): boolean;
  146. begin
  147. result:=ParamType in [vt_i1,vt_ui1,vt_i2,vt_ui2,vt_i4,vt_ui4,vt_uint,
  148. vt_i8,VT_UI8,vt_bool,vt_r4,vt_r8,vt_cy,vt_date,
  149. VT_BSTR,VT_VARIANT,VT_DISPATCH,VT_UNKNOWN,vt_hresult,VT_INT,
  150. VT_LPWSTR,VT_LPSTR];
  151. end;
  152. function TTypeLibImporter.VarTypeToStr(ParamType:integer): string;
  153. begin
  154. case ParamType of
  155. vt_empty : Result := 'Empty';
  156. vt_null : Result := 'Null';
  157. vt_i2 : Result := 'Smallint';
  158. vt_i4 : Result := 'Integer';
  159. vt_r4 : Result := 'Single';
  160. vt_r8 : Result := 'Double';
  161. vt_cy : Result := 'Currency';
  162. vt_date : Result := 'TDateTime';
  163. vt_bstr : Result := 'WideString';
  164. vt_dispatch : Result := 'IDispatch';
  165. vt_error : Result := 'SCODE';
  166. vt_bool : Result := 'WordBool';
  167. vt_variant : Result := 'Variant';
  168. vt_unknown : Result := 'IUnknown';
  169. vt_i1 : Result := 'ShortInt';
  170. vt_ui1 : Result := 'Byte';
  171. vt_ui2 : Result := 'Word';
  172. vt_ui4 : Result := 'LongWord';
  173. vt_i8 : Result := 'Int64';
  174. VT_UI8: Result := 'QWord';
  175. vt_clsid : Result := 'TGUID';
  176. vt_void : Result := 'pointer';
  177. vt_ptr : Result := 'Pointer';
  178. vt_uint : Result := 'UInt';
  179. vt_userdefined : Result := 'User defined';
  180. vt_hresult : Result := 'HResult';
  181. VT_INT:Result:='SYSINT';
  182. VT_SAFEARRAY:Result:='PSafeArray';
  183. VT_LPWSTR:Result:='PWideChar';
  184. VT_LPSTR:Result:='PChar';
  185. else
  186. Result := 'Unknown (' + IntToStr(ParamType) + ')';
  187. end;
  188. end;
  189. function TTypeLibImporter.ValidateID(id:string):boolean;
  190. const
  191. RESERVEDCNT=111;
  192. RESERVED:array[1..RESERVEDCNT] of string=
  193. ('absolute','and','array','asm','begin','break','case','const',
  194. 'constructor','continue','destructor','div','do','downto','else','end',
  195. 'file','for','function','goto','if','implementation','in','inherited',
  196. 'inline','interface','label','mod','nil','not','object','of',
  197. 'on','operator','or','packed','procedure','program','record','reintroduce',
  198. 'repeat','self','set','shl','shr','string','then','to',
  199. 'type','unit','until','uses','var','while','with','xor',
  200. 'as','class','except','exports','finalization','finally','initialization',
  201. 'is','library','on','property','raise','threadvar','try',
  202. 'dispose','exit','false','new','true',
  203. 'abs','arctan','boolean','char','cos','dispose','eof','eoln',
  204. 'exp','false','input','integer','ln','maxint','new','odd',
  205. 'ord','output','pack','page','pred','read','readln','real',
  206. 'reset','rewrite','round','sin','sqr','sqrt','succ','text',
  207. 'true','trunc','write','writeln');
  208. var
  209. sl:string;
  210. i:integer;
  211. begin
  212. sl:=lowercase(id);
  213. result:=true;
  214. for i:=1 to RESERVEDCNT do
  215. if sl= RESERVED[i] then
  216. begin
  217. result:=false;
  218. break;
  219. end;
  220. end;
  221. function TTypeLibImporter.TypeToString(TI:ITypeInfo; TD:TYPEDESC):string;
  222. var
  223. TIref: ITypeInfo;
  224. TARef:LPTYPEATTR;
  225. TLRef: ITypeLib;
  226. LARef: lpTLIBATTR;
  227. BstrName : WideString;
  228. il:LongWord;
  229. i,idims:integer;
  230. sl,sRefSrc,sKey:string;
  231. Handle:HKEY;
  232. bWasPointer:boolean;
  233. begin
  234. result:='';
  235. bIsCustomAutomatable:=false;
  236. bIsInterface:=false;
  237. bIsExternalDecl:=false;
  238. bIsUserDefined:=false;
  239. if (TD.vt=vt_userdefined) or ((TD.vt=VT_PTR) and (TD.lptdesc^.vt=vt_userdefined)) then
  240. begin
  241. // interface references are dealt with now because they are pointers in fpc.
  242. // Recursive algorithm makes it difficult to remove a single preceding 'P' from the result.
  243. bIsUserDefined:=true;
  244. bWasPointer:=(TD.vt=VT_PTR);
  245. if bWasPointer then
  246. TD:=TD.lptdesc^;
  247. OleCheck(TI.GetRefTypeInfo(TD.hreftype,TIref));
  248. OleCheck(TIRef.GetDocumentation(DISPID_UNKNOWN, @BstrName, nil, nil, nil));
  249. result:=BstrName;
  250. OleCheck(TIRef.GetTypeAttr(TARef));
  251. bIsCustomAutomatable:=TARef^.typekind in [TKIND_DISPATCH,TKIND_INTERFACE,TKIND_ENUM];
  252. if TARef^.typekind=TKIND_ALIAS then
  253. begin
  254. TypeToString(TIRef,TARef^.tdescAlias); //not interested in result, only bIsCustomAutomatable and bIsInterface
  255. bIsCustomAutomatable:=bIsAutomatable;
  256. end
  257. else
  258. bIsInterface:=TARef^.typekind in [TKIND_DISPATCH,TKIND_INTERFACE] ;
  259. if bWasPointer and not bIsInterface then // interfaces are pointers to interface in fpc
  260. result:='P'+result;
  261. OleCheck(TIRef.GetContainingTypeLib(TLRef,il));
  262. OleCheck(TLRef.GetDocumentation(-1, @BstrName, nil, nil, nil));
  263. OleCheck(TLRef.GetLibAttr(LARef));
  264. if FAppendVersionNumber then
  265. sl:=format('%s_%d_%d_TLB',[BstrName,LARef^.wMajorVerNum,LARef^.wMinorVerNum])
  266. else
  267. sl:=format('%s_TLB',[BstrName]);
  268. if (LowerCase(BstrName)='stdole') then // don't include, uses pre-defined stdole2.pas if V2
  269. begin
  270. bIsExternalDecl:=true;
  271. if lowercase(result)='guid' then
  272. result:='TGUID';
  273. if (LARef^.wMajorVerNum=2) and (FUses.IndexOf('stdole2')=-1) then
  274. begin
  275. AddToHeader('// Dependency: stdole v2 (stdole2.pas)');
  276. FUses.Add('stdole2');
  277. end;
  278. end
  279. else if (LowerCase(sl)<>LowerCase(UnitName)) and (FUses.IndexOf(sl)=-1) then
  280. begin // add dependency
  281. // find source in registry key HKEY_CLASSES_ROOT\TypeLib\GUID\version\0\win32
  282. bIsExternalDecl:=true;
  283. il:=MAX_PATH;
  284. SetLength(sRefSrc,il);
  285. sKey:=format('\TypeLib\%s\%d.%d\0\win32',[GUIDToString(LARef^.GUID),LARef^.wMajorVerNum,LARef^.wMinorVerNum]);
  286. if (RegOpenKeyEx(HKEY_CLASSES_ROOT,pchar(sKey),0,KEY_READ,Handle) = ERROR_SUCCESS) then
  287. begin
  288. if RegQueryValue(Handle,nil,@sRefSrc[1],@il) = ERROR_SUCCESS then
  289. begin
  290. SetLength(sRefSrc,il-1); // includes null terminator
  291. if not FDependencies.Find(sRefSrc,i) then
  292. FDependencies.Add(sRefSrc);
  293. end
  294. else
  295. sRefSrc:=GUIDToString(LARef^.GUID);
  296. RegCloseKey(Handle);
  297. end;
  298. AddToHeader('// Dependency: %s v%d.%d (%s)',[BstrName,LARef^.wMajorVerNum,LARef^.wMinorVerNum,sRefSrc]);
  299. FUses.Add(sl);
  300. TLRef.ReleaseTLibAttr(LARef);
  301. end;
  302. TIRef.ReleaseTypeAttr(TARef);
  303. end
  304. else if TD.vt=VT_PTR then //pointer type
  305. begin
  306. TD:=TD.lptdesc^;
  307. result:='P'+TypeToString(TI,TD);
  308. bIsAutomatable:=(VarTypeIsAutomatable(TD.vt) {and (TD.vt<>VT_VARIANT)}) or bIsCustomAutomatable;
  309. exit;
  310. end
  311. else if TD.vt=VT_CARRAY then //C type array
  312. begin
  313. // get array element type
  314. sl:=TypeToString(TI,TD.lpadesc^.tdescElem);
  315. // get dimensions
  316. idims:=TD.lpadesc^.cDims;
  317. result:='array[';
  318. // get boundaries for every dimension
  319. for i:=0 to idims-1 do
  320. result:=result+IntToStr(TD.lpadesc^.rgbounds[i].lLbound)+'..'+IntToStr(TD.lpadesc^.rgbounds[i].cElements - TD.lpadesc^.rgbounds[i].lLbound -1)+',';
  321. result[length(result)]:=']';
  322. result:=result + ' of '+sl;
  323. end
  324. else
  325. result:=VarTypeToStr(TD.vt);
  326. bIsAutomatable:=VarTypeIsAutomatable(TD.vt) or bIsCustomAutomatable;
  327. end;
  328. function TTypeLibImporter.interfacedeclaration(iName,iDoc:string;TI:ITypeInfo;TA:LPTYPEATTR;
  329. bIsDispatch,bCreateEvents:boolean):string;
  330. type
  331. TPropertyDef=record
  332. idispid:integer;
  333. bput,bget:boolean;
  334. iptype,igtype:integer;
  335. name,
  336. sptype, // only used if iptype=igtype
  337. sorgname,
  338. sdoc,
  339. sParam,
  340. sDefault:string;
  341. end;
  342. var
  343. RTIT: HREFTYPE;
  344. TIref: ITypeInfo;
  345. BstrName,BstrNameRef,BstrDocString : WideString;
  346. s,sl,sPropIntfc,sPropDispIntfc,sType,sConv,sFunc,sPar,sVarName,sMethodName,sPropParam,sPropParam2:string;
  347. sEventSignatures,sEventFunctions,sEventProperties,sEventImplementations:string;
  348. i,j,k:integer;
  349. FD: lpFUNCDESC;
  350. BL : array[0..99] of TBstr;
  351. cnt:LongWord;
  352. TD: TYPEDESC;
  353. bPropHasParam,bIsFunction,bParamByRef:boolean;
  354. VD: lpVARDESC;
  355. aPropertyDefs:array of TPropertyDef;
  356. Propertycnt,iType:integer;
  357. function findProperty(ireqdispid:integer):integer;
  358. var i:integer;
  359. begin
  360. for i:=0 to Propertycnt-1 do
  361. if aPropertyDefs[i].idispid=ireqdispid then
  362. begin
  363. result:=i;
  364. exit;
  365. end;
  366. result:=Propertycnt;
  367. Propertycnt:=Propertycnt+1;
  368. with aPropertyDefs[result] do
  369. begin
  370. idispid:=ireqdispid;
  371. bput:=false;
  372. bget:=false;
  373. name:='';
  374. iptype:=vt_empty;
  375. igtype:=vt_empty;
  376. sptype:='';
  377. sorgname:='';
  378. sdoc:='';
  379. sParam:='';
  380. sDefault:='';
  381. end;
  382. end;
  383. begin
  384. Propertycnt:=0;
  385. SetLength(aPropertyDefs,TA^.cFuncs+TA^.cVars); // worst case, all functions getters or all setters
  386. sEventSignatures:='';
  387. sEventFunctions:='';
  388. sEventProperties:='';
  389. sEventImplementations:='';
  390. if not bIsDispatch then
  391. begin
  392. // find base class
  393. if TA^.cImplTypes>0 then
  394. begin
  395. OleCheck(TI.GetRefTypeOfImplType(0,RTIT));
  396. OleCheck(TI.GetRefTypeInfo(RTIT,TIref));
  397. OleCheck(TIRef.GetDocumentation(DISPID_UNKNOWN, @BstrNameRef, nil, nil, nil));
  398. s:=format(#13#10'// %s : %s'#13#10#13#10' %s = interface(%s)'#13#10,[iname,iDoc,iname,BstrNameRef]);
  399. end
  400. else // no base class
  401. begin
  402. s:=format(#13#10'// %s : %s'#13#10#13#10' %s = interface'#13#10,[iname,iDoc,iname]);
  403. end;
  404. end
  405. else
  406. if (TA^.wTypeFlags and TYPEFLAG_FDUAL)=TYPEFLAG_FDUAL then
  407. s:=format(#13#10'// %s : %s'#13#10#13#10' %sDisp = dispinterface'#13#10,[iname,iDoc,iname])
  408. else
  409. s:=format(#13#10'// %s : %s'#13#10#13#10' %s = dispinterface'#13#10,[iname,iDoc,iname]);
  410. sPropIntfc:='';
  411. sPropDispIntfc:='';
  412. s:=s+format(' [''%s'']'#13#10,[GUIDToString(TA^.GUID)]);
  413. for j:=0 to TA^.cFuncs-1 do
  414. begin
  415. OleCheck(TI.GetFuncDesc(j,FD));
  416. OleCheck(TI.GetNames(FD^.memid,@BL,length(BL),cnt));
  417. // skip IUnknown and IDispatch methods
  418. sl:=lowercase(BL[0]);
  419. if (sl='queryinterface') or (sl='addref') or (sl='release') then //IUnknown
  420. continue;
  421. if bIsDispatch and
  422. ((sl='gettypeinfocount') or (sl='gettypeinfo') or (sl='getidsofnames') or (sl='invoke')) then //IDispatch
  423. continue;
  424. // get return type
  425. if bIsDispatch and ((FD^.invkind=INVOKE_PROPERTYGET) or (FD^.invkind=INVOKE_FUNC)) then
  426. begin
  427. sType:=TypeToString(TI,FD^.elemdescFunc.tdesc);
  428. iType:=FD^.elemdescFunc.tdesc.vt;
  429. end
  430. else
  431. if FD^.cParams>0 then
  432. begin
  433. sType:=TypeToString(TI,FD^.lprgelemdescParam[FD^.cParams-1].tdesc);
  434. iType:=FD^.lprgelemdescParam[FD^.cParams-1].tdesc.vt;
  435. if ((FD^.lprgelemdescParam[FD^.cParams-1].paramdesc.wParamFlags and (PARAMFLAG_FRETVAL or PARAMFLAG_FOUT)) <>0) then
  436. begin
  437. delete(sType,1,1); //out parameters are always defined as pointer
  438. if assigned(FD^.lprgelemdescParam[FD^.cParams-1].tdesc.lptdesc) then
  439. iType:=FD^.lprgelemdescParam[FD^.cParams-1].tdesc.lptdesc^.vt;
  440. end;
  441. end;
  442. //get calling convention
  443. if FD^.callconv=CC_STDCALL then
  444. begin
  445. if lowercase(BstrNameRef)='iunknown' then
  446. sConv:='stdcall'
  447. else
  448. sConv:='safecall';
  449. end
  450. else
  451. sConv:='cdecl';
  452. // get info
  453. OleCheck(TI.GetDocumentation(FD^.memid, @BstrName, @BstrDocString, nil, nil));
  454. case FD^.invkind of
  455. // build function/procedure
  456. INVOKE_FUNC :
  457. begin
  458. if ValidateID(BstrName) then
  459. sMethodName:=BstrName
  460. else
  461. begin
  462. sMethodName:=BstrName+'_';
  463. AddToHeader('// Warning: renamed method ''%s'' in %s to ''%s''',[BstrName,iname,sMethodName],True);
  464. end;
  465. bIsFunction:=(bIsDispatch and (FD^.elemdescFunc.tdesc.vt<>VT_VOID)) or
  466. (not bIsDispatch and (FD^.cParams>0) and ((FD^.lprgelemdescParam[FD^.cParams-1].paramdesc.wParamFlags and PARAMFLAG_FRETVAL ) <>0));
  467. if bIsFunction then
  468. sFunc:=format(' // %s : %s '#13#10' function %s(',[sMethodName,BstrDocString,sMethodName])
  469. else
  470. sFunc:=format(' // %s : %s '#13#10' procedure %s(',[sMethodName,BstrDocString,sMethodName]);
  471. if bIsFunction and bIsDispatch and not bIsAutomatable then
  472. begin
  473. AddToHeader('// Warning: ''%s'' not automatable in %sdisp.%s',[stype,iname,BstrName],True);
  474. sType:='{!! '+sType+' !!} OleVariant';
  475. end;
  476. if bCreateEvents then
  477. begin
  478. sEventSignatures:=sEventSignatures+format(' T%s%s = procedure(Sender: TObject;',[iname,sMethodName]);
  479. sEventFunctions:=sEventFunctions+format(' FOn%s:T%s%s;'#13#10,[sMethodName,iname,sMethodName]);
  480. sEventProperties:=sEventProperties+format(' property On%s : T%s%s read FOn%s write FOn%s;'#13#10,
  481. [sMethodName,iname,sMethodName,sMethodName,sMethodName]);
  482. sEventImplementations:=sEventImplementations+
  483. format(' %d: if assigned(On%s) then'#13#10+
  484. ' On%s(Self,',[FD^.memid,sMethodName,sMethodName]);
  485. end;
  486. // parameters
  487. for k:=0 to FD^.cParams-1 do
  488. begin
  489. bParamByRef:=(FD^.lprgelemdescParam[k].tdesc.vt=VT_PTR) and // by ref
  490. not((FD^.lprgelemdescParam[k].tdesc.lptdesc^.vt=VT_USERDEFINED) and bIsInterface);// but not pointer to interface
  491. if (FD^.lprgelemdescParam[k].paramdesc.wParamFlags and PARAMFLAG_FRETVAL ) <>0 then //return type
  492. continue;
  493. sl:=TypeToString(TI,FD^.lprgelemdescParam[k].tdesc);
  494. if bParamByRef then
  495. delete(sl,1,1);
  496. if bIsDispatch and not bIsAutomatable then
  497. begin
  498. AddToHeader('// Warning: ''%s'' not automatable in %sdisp.%s',[sl,iname,sMethodName],True);
  499. sl:='{!! '+sl+' !!} OleVariant';
  500. end;
  501. sPar:='';
  502. if bParamByRef then
  503. case FD^.lprgelemdescParam[k].paramdesc.wParamFlags and (PARAMFLAG_FIN or PARAMFLAG_FOUT) of
  504. PARAMFLAG_FIN or PARAMFLAG_FOUT:sPar:='var ';
  505. PARAMFLAG_FOUT:sPar:='out ';
  506. PARAMFLAG_FIN:sPar:='var '; //constref in safecall? TBD
  507. end;
  508. if ValidateID(BL[k+1]) then
  509. sVarName:=BL[k+1]
  510. else
  511. begin
  512. sVarName:=BL[k+1]+'_';
  513. AddToHeader('// Warning: renamed parameter ''%s'' in %s.%s to ''%s'''#13#10,[BL[k+1],iname,sMethodName,sVarName],True);
  514. end;
  515. sPar:=sPar+format('%s:%s;',[sVarName,sl]);
  516. sFunc:=sFunc+sPar;
  517. if bCreateEvents then
  518. begin
  519. sEventSignatures:=sEventSignatures+sPar;
  520. //params are numbered last to first
  521. if bParamByRef and not(bIsDispatch and not bIsAutomatable) then
  522. begin
  523. case FD^.lprgelemdescParam[k].tdesc.lptdesc^.vt of
  524. VT_UI1: sl:='pbVal';
  525. VT_UI2: sl:='puiVal';
  526. VT_UI4: sl:='pulVal';
  527. VT_UI8: sl:='pullVal';
  528. VT_I1: sl:='pcVal';
  529. VT_I2: sl:='piVal';
  530. VT_I4: sl:='plVal';
  531. VT_I8: sl:='pllVal';
  532. VT_R4: sl:='pfltVal';
  533. VT_R8: sl:='pdblVal';
  534. VT_BOOL: sl:='pbool';
  535. VT_ERROR: sl:='pscode';
  536. VT_CY: sl:='pcyVal';
  537. VT_DATE: sl:='pdate';
  538. VT_BSTR: sl:='pbstrVal';
  539. VT_UNKNOWN: sl:='punkVal';
  540. VT_DISPATCH: sl:='pdispVal';
  541. VT_ARRAY: sl:='pparray';
  542. VT_VARIANT: sl:='pvarVal';
  543. end;
  544. sEventImplementations:=sEventImplementations+format(' Params.rgvarg[%d].%s^,',[FD^.cParams-1-k,sl]);
  545. end
  546. else
  547. sEventImplementations:=sEventImplementations+format(' OleVariant(Params.rgvarg[%d]),',[FD^.cParams-1-k]);
  548. end;
  549. end;
  550. // finish interface and dispinterface
  551. if sFunc[length(sFunc)]=';' then
  552. sFunc[length(sFunc)]:=')'
  553. else // no params
  554. delete(sFunc,length(sFunc),1);
  555. if bCreateEvents then
  556. begin
  557. sEventSignatures[length(sEventSignatures)]:=')';
  558. sEventSignatures:=sEventSignatures+' of object;'#13#10;
  559. sEventImplementations[length(sEventImplementations)]:=')';
  560. sEventImplementations:=sEventImplementations+';'#13#10;
  561. end;
  562. if bIsFunction then
  563. sFunc:=sFunc+format(':%s',[sType]);
  564. if bIsDispatch then
  565. s:=s+sFunc+format(';dispid %d;'#13#10,[FD^.memid])
  566. else
  567. s:=s+sFunc+format(';%s;'#13#10,[sConv]);
  568. end;
  569. INVOKE_PROPERTYGET,INVOKE_PROPERTYPUT,INVOKE_PROPERTYPUTREF :
  570. // build properties. Use separate string to group properties at end of interface declaration.
  571. begin
  572. if ValidateID(BstrName) then
  573. sMethodName:=BstrName
  574. else
  575. begin
  576. sMethodName:=BstrName+'_';
  577. AddToHeader('// Warning: renamed property ''%s'' in %s to ''%s''',[BstrName,iname,sMethodName]);
  578. end;
  579. bPropHasParam:=(((FD^.invkind=INVOKE_PROPERTYGET) and (FD^.cParams>0)) or (FD^.cParams>1))
  580. and ((FD^.lprgelemdescParam[0].paramdesc.wParamFlags and PARAMFLAG_FIN) = PARAMFLAG_FIN) ;
  581. if (FD^.memid=0) and bPropHasParam then sl:=' default;' else sl:='';
  582. sPropParam:='';
  583. sPropParam2:='';
  584. if bPropHasParam then
  585. begin
  586. sPropParam:=BL[1]+':'+TypeToString(TI,FD^.lprgelemdescParam[0].tdesc);
  587. end;
  588. if bIsDispatch then
  589. begin
  590. if (TD.vt<>VT_VOID) and not bIsAutomatable then
  591. begin
  592. AddToHeader('// Warning: ''%s'' not automatable in %s.%s',[stype,iname,BstrName]);
  593. sType:='{!! '+sType+' !!} OleVariant';
  594. end;
  595. if bPropHasParam then
  596. sPropParam:='['+sPropParam+']';
  597. i:=pos(format('dispid %d;',[FD^.memid]),sPropDispIntfc);
  598. if i<=0 then
  599. begin
  600. if FD^.invkind=INVOKE_PROPERTYGET then
  601. sType:=sType+' readonly '
  602. else
  603. sType:=sType+' writeonly';
  604. sPropDispIntfc:=sPropDispIntfc+format(' // %s : %s '#13#10' property %s%s:%s dispid %d;%s'#13#10,
  605. [BstrName,BstrDocString,sMethodName,sPropParam,sType,FD^.memid,sl]);
  606. end
  607. else //remove readonly or writeonly
  608. delete(sPropDispIntfc,i-11,10); //10= length(' readonly ')
  609. end
  610. else
  611. begin
  612. //getters/setters for interface, insert in interface as they come,
  613. //store in aPropertyDefs to create properties at the end
  614. if bPropHasParam then
  615. begin
  616. sPropParam2:='('+sPropParam+')';
  617. sPropParam:='['+sPropParam+']';
  618. end;
  619. if FD^.invkind=INVOKE_PROPERTYGET then
  620. begin
  621. s:=s+format(' function Get_%s%s : %s; %s;'#13#10,[sMethodName,sPropParam2,sType,sConv]);
  622. with aPropertyDefs[findProperty(FD^.memid)] do
  623. begin
  624. bget:=true;
  625. name:=sMethodName;
  626. igtype:=itype;
  627. sptype:=sType;
  628. sorgname:=BstrName;
  629. sdoc:=BstrDocString;
  630. sParam:=sPropParam;
  631. sDefault:=sl;
  632. end;
  633. end
  634. else
  635. begin
  636. if ValidateID(BL[1]) then
  637. sVarName:=BL[1]
  638. else
  639. begin
  640. sVarName:=BL[1]+'_';
  641. AddToHeader('// Warning: renamed parameter ''%s'' in %s.Set_%s to ''%s''',[BL[1],iname,sMethodName,sVarName]);
  642. end;
  643. s:=s+format(' procedure Set_%s(const %s:%s); %s;'#13#10,[sMethodName,sVarName,sType,sConv]);
  644. with aPropertyDefs[findProperty(FD^.memid)] do
  645. begin
  646. bput:=true;
  647. name:=sMethodName;
  648. iptype:=itype;
  649. sptype:=sType;
  650. sorgname:=BstrName;
  651. sdoc:=BstrDocString;
  652. sParam:=sPropParam;
  653. sDefault:=sl;
  654. end;
  655. end;
  656. end;
  657. end;
  658. end;
  659. TI.ReleaseFuncDesc(FD);
  660. end;
  661. for j:=0 to TA^.cVars-1 do
  662. begin //read-write properties only
  663. if bIsDispatch then
  664. begin
  665. TI.GetVarDesc(j,VD);
  666. if assigned(VD) then
  667. begin
  668. TI.GetDocumentation(VD^.memId,@BstrName, @BstrDocString, nil, nil);
  669. if ValidateID(BstrName) then
  670. sMethodName:=BstrName
  671. else
  672. begin
  673. sMethodName:=BstrName+'_';
  674. AddToHeader('// Warning: renamed property ''%s'' in %s to ''%s'''#13#10,[BstrName,iname,sMethodName]);
  675. end;
  676. sType:=TypeToString(TI,VD^.ElemdescVar.tdesc);
  677. sPropDispIntfc:=sPropDispIntfc+format(' // %s : %s '#13#10' property %s:%s dispid %d;'#13#10,
  678. [BstrName,BstrDocString,sMethodName,sType,VD^.memId]);
  679. end;
  680. end;
  681. end;
  682. if bCreateEvents then
  683. begin
  684. FEventDisp.Add(iname);
  685. FEventIID.Add(GUIDToString(TA^.GUID));
  686. FEventSignatures.Add(sEventSignatures);
  687. FEventFunctions.Add(sEventFunctions);
  688. FEventProperties.Add(sEventProperties);
  689. FEventImplementations.Add(sEventImplementations);
  690. end;
  691. if bIsDispatch then
  692. result:=s + sPropDispIntfc +' end;'#13#10
  693. else
  694. begin
  695. // add interface properties
  696. for i:=0 to Propertycnt-1 do
  697. with aPropertyDefs[i] do
  698. if (iptype=igtype) or not bget or not bput then
  699. begin
  700. s:=s+format(' // %s : %s '#13#10' property %s%s:%s',[sorgname,sdoc,name,sParam,sptype]);
  701. if bget then
  702. s:=s+format(' read Get_%s',[name]);
  703. if bput then
  704. s:=s+format(' write Set_%s',[name]);
  705. s:=s+format(';%s'#13#10,[sDefault]);
  706. end;
  707. result:=s+' end;'#13#10;
  708. end;
  709. end;
  710. function TTypeLibImporter.GetDependencies: TStrings;
  711. begin
  712. Result:=FDependencies;
  713. end;
  714. function TTypeLibImporter.GetUnitSource: TStrings;
  715. begin
  716. Result:=FUnitSource;
  717. end;
  718. Procedure TTypeLibImporter.ImportGUIDs(Const TL : ITypeLib; TICount : Integer);
  719. Var
  720. i : integer;
  721. BstrName, BstrDocString, BstrHelpFile : WideString;
  722. dwHelpContext: DWORD;
  723. TI:ITypeInfo;
  724. TA:LPTYPEATTR;
  725. TIT: TYPEKIND;
  726. begin
  727. //GUIDs
  728. for i:=0 to TIcount-1 do
  729. begin
  730. OleCheck(TL.GetTypeInfoType(i, TIT));
  731. OleCheck(TL.GetTypeInfo(i, TI));
  732. OleCheck(TL.GetDocumentation(i, @BstrName, @BstrDocString, @dwHelpContext, @BstrHelpFile));
  733. OleCheck(TI.GetTypeAttr(TA));
  734. case TIT of
  735. TKIND_DISPATCH,TKIND_INTERFACE:
  736. begin
  737. AddToInterface(' IID_%s : TGUID = ''%s'';',[BstrName,GUIDToString(TA^.GUID)]);
  738. end;
  739. TKIND_COCLASS:
  740. begin
  741. AddToInterface(' CLASS_%s : TGUID = ''%s'';',[BstrName,GUIDToString(TA^.GUID)]);
  742. end;
  743. end;
  744. TI.ReleaseTypeAttr(TA);
  745. end;
  746. end;
  747. Procedure TTypeLibImporter.ImportEnums(Const TL : ITypeLib; TICount : Integer);
  748. Var
  749. i,j : integer;
  750. sl : string;
  751. BstrName, BstrDocString, BstrHelpFile : WideString;
  752. dwHelpContext: DWORD;
  753. TI:ITypeInfo;
  754. TA:LPTYPEATTR;
  755. TIT: TYPEKIND;
  756. bDuplicate:boolean;
  757. VD: lpVARDESC;
  758. begin
  759. //enums
  760. AddToInterface('');
  761. AddToInterface('//Enums');
  762. AddToInterface('');
  763. for i:=0 to TIcount-1 do
  764. begin
  765. OleCheck(TL.GetTypeInfoType(i, TIT));
  766. OleCheck(TL.GetTypeInfo(i, TI));
  767. OleCheck(TL.GetDocumentation(i, @BstrName, @BstrDocString, @dwHelpContext, @BstrHelpFile));
  768. OleCheck(TI.GetTypeAttr(TA));
  769. if TIT=TKIND_ENUM then
  770. begin
  771. bDuplicate:=false;
  772. if ValidateID(BstrName) then
  773. sl:=BstrName
  774. else
  775. begin
  776. sl:=BstrName+'_';
  777. AddToHeader('// Warning: renamed enum type ''%s'' to ''%s''',[BstrName,sl],True);
  778. end;
  779. if (InterfaceSection.IndexOf(Format(' %s =TOleEnum;',[sl]))<>-1) then // duplicate enums fe. AXVCL.dll 1.0
  780. begin
  781. sl:=sl+IntToStr(i); // index is unique in this typelib
  782. AddToHeader('// Warning: duplicate enum ''%s''. Renamed to ''%s''. consts appended with %d',[BstrName,sl,i]);
  783. bDuplicate:=true;
  784. end;
  785. AddToInterface('Type');
  786. AddToInterface(' %s =TOleEnum;',[sl]);
  787. FTypes.Add(sl);
  788. AddToInterface('Const');
  789. for j:=0 to TA^.cVars-1 do
  790. begin
  791. TI.GetVarDesc(j,VD);
  792. if assigned(VD) then
  793. begin
  794. TI.GetDocumentation(VD^.memId,@BstrName, nil, nil, nil);
  795. if ValidateID(BstrName) then
  796. sl:=BstrName
  797. else
  798. begin
  799. sl:=BstrName+'_';
  800. AddToHeader('// Warning: renamed enum value ''%s'' to ''%s''',[BstrName,sl],True);
  801. end;
  802. if bDuplicate then
  803. sl:=sl+IntToStr(i);
  804. if assigned(VD^.lpvarValue) then
  805. AddToInterface(' %s = $%s;',[sl,IntToHex(PtrInt(VD^.lpvarValue^),16)]);
  806. end;
  807. end;
  808. end;
  809. TI.ReleaseTypeAttr(TA);
  810. end;
  811. end;
  812. Procedure TTypeLibImporter.CreateForwards(Const TL : ITypeLib; TICount : Integer);
  813. Var
  814. i : integer;
  815. BstrName, BstrDocString, BstrHelpFile : WideString;
  816. dwHelpContext: DWORD;
  817. TI:ITypeInfo;
  818. TA:LPTYPEATTR;
  819. TIT: TYPEKIND;
  820. begin
  821. // Forward declarations
  822. AddToInterface('//Forward declarations');
  823. AddToInterface('');
  824. AddToInterface('Type');
  825. for i:=0 to TIcount-1 do
  826. begin
  827. OleCheck(TL.GetTypeInfoType(i, TIT));
  828. OleCheck(TL.GetTypeInfo(i, TI));
  829. OleCheck(TL.GetDocumentation(i, @BstrName, @BstrDocString, @dwHelpContext, @BstrHelpFile));
  830. OleCheck(TI.GetTypeAttr(TA));
  831. if (TIT=TKIND_DISPATCH) then
  832. begin
  833. if (TA^.wTypeFlags and TYPEFLAG_FDUAL)=TYPEFLAG_FDUAL then
  834. begin
  835. AddToInterface(' %s = interface;',[BstrName]);
  836. AddToInterFace(' %sDisp = dispinterface;',[BstrName]);
  837. end
  838. else
  839. AddToInterface(' %s = dispinterface;',[BstrName]);
  840. end
  841. else if (TIT=TKIND_INTERFACE) then
  842. AddToInterface(' %s = interface;',[BstrName]);
  843. TI.ReleaseTypeAttr(TA);
  844. end;
  845. end;
  846. Procedure TTypeLibImporter.CreateRecordsUnionsAliases(Const TL : ITypeLib; TICount : Integer);
  847. Var
  848. i,j : integer;
  849. BstrName, BstrDocString, BstrHelpFile : WideString;
  850. dwHelpContext: DWORD;
  851. TI:ITypeInfo;
  852. TA:LPTYPEATTR;
  853. TIT: TYPEKIND;
  854. VD: lpVARDESC;
  855. slDeferredType,slDeferredPendingType,slDeferredDeclaration:TStrings;
  856. sl,sldeclaration,stype,smembername,srecordname:string;
  857. bIsDeferred:boolean;
  858. procedure ReleasePendingType(sPen:string);
  859. var k:integer;
  860. sDec,sTyp:string;
  861. begin
  862. k:=slDeferredPendingType.IndexOf(sPen);
  863. while (k>=0) do
  864. begin
  865. sDec:=slDeferredDeclaration[k];
  866. sTyp:=slDeferredType[k];
  867. slDeferredPendingType.Delete(k);
  868. slDeferredDeclaration.Delete(k);
  869. slDeferredType.Delete(k);
  870. // any other types pending for this declaration ? If yes, wait until all types declared.
  871. if slDeferredDeclaration.IndexOf(sDec)=-1 then
  872. begin
  873. AddToInterface(sDec);
  874. FTypes.Add(sTyp);
  875. ReleasePendingType(sTyp);
  876. end;
  877. k:=slDeferredPendingType.IndexOf(sPen);
  878. end;
  879. end;
  880. begin
  881. //records, unions aliases
  882. AddToInterface('');
  883. AddToInterface('//records, unions, aliases');
  884. AddToInterface('');
  885. slDeferredType:=TStringList.Create;
  886. slDeferredPendingType:=TStringList.Create;
  887. slDeferredDeclaration:=TStringList.Create;
  888. try
  889. for i:=0 to TIcount-1 do
  890. begin
  891. bIsDeferred:=false;
  892. sldeclaration:='';
  893. OleCheck(TL.GetTypeInfoType(i, TIT));
  894. //s:=s+format('type %d'#13#10,[ord(TIT)]);
  895. OleCheck(TL.GetTypeInfo(i, TI));
  896. OleCheck(TL.GetDocumentation(i, @BstrName, @BstrDocString, @dwHelpContext, @BstrHelpFile));
  897. OleCheck(TI.GetTypeAttr(TA));
  898. case TIT of
  899. TKIND_RECORD,TKIND_UNION:
  900. begin
  901. if ValidateID(BstrName) then
  902. sRecordName:=BstrName
  903. else
  904. begin
  905. sRecordName:=BstrName+'_';
  906. AddToHeader('// Warning: renamed record ''%s'' to ''%s''',[BstrName,sRecordName],True);
  907. end;
  908. AddToInterface(' P%s = ^%s;'#13#10,[sRecordName,sRecordName]);
  909. FTypes.Add('P'+sRecordName);
  910. ReleasePendingType('P'+sRecordName);
  911. if TIT=TKIND_RECORD then
  912. sldeclaration:=sldeclaration+format(' %s = packed record'#13#10,[sRecordName])
  913. else
  914. begin
  915. sldeclaration:=sldeclaration+format(' %s = record'#13#10,[sRecordName]);
  916. sldeclaration:=sldeclaration+' case Integer of'#13#10;
  917. end;
  918. for j:=0 to TA^.cVars-1 do
  919. begin
  920. TI.GetVarDesc(j,VD);
  921. TI.GetDocumentation(VD^.memId,@BstrName, @BstrDocString, @dwHelpContext, @BstrHelpFile);
  922. if ValidateID(BstrName) then
  923. smemberName:=BstrName
  924. else
  925. begin
  926. smemberName:=BstrName+'_';
  927. AddToHeader('// Warning: renamed record member ''%s'' in %s to ''%s''',[BstrName,sRecordName,smemberName],True);
  928. end;
  929. stype:=TypeToString(TI, VD^.ElemdescVar.tdesc);
  930. if bIsUserDefined and not ValidateID(stype) then
  931. stype:=stype+'_';
  932. if bIsUserDefined and not bIsExternalDecl and (FTypes.IndexOf(stype)=-1) then //not defined yet, defer
  933. begin
  934. bIsDeferred:=true;
  935. slDeferredPendingType.Add(stype);
  936. slDeferredType.Add(sRecordName);
  937. end;
  938. if TIT=TKIND_RECORD then
  939. sldeclaration:=sldeclaration+format(' %s : %s;'#13#10,[smemberName,stype])
  940. else
  941. sldeclaration:=sldeclaration+format(' %d: (%s : %s);'#13#10,[j,smemberName,stype]);
  942. end;
  943. sldeclaration:=sldeclaration+' end;';
  944. if not bIsDeferred then
  945. begin
  946. AddToInterface(sldeclaration);
  947. FTypes.Add(sRecordName);
  948. ReleasePendingType(sRecordName);
  949. end
  950. else
  951. for j:=slDeferredDeclaration.Count to slDeferredType.Count-1 do // catch up on slDeferredType
  952. slDeferredDeclaration.Add(sldeclaration);
  953. end;
  954. TKIND_ALIAS:
  955. begin
  956. stype:=TypeToString(TI, TA^.tdescAlias);
  957. if bIsUserDefined and not ValidateID(stype) then
  958. stype:=stype+'_';
  959. if ValidateID(BstrName) then
  960. sRecordName:=BstrName
  961. else
  962. begin
  963. sRecordName:=BstrName+'_';
  964. AddToHeader('// Warning: renamed alias ''%s'' to ''%s''',[BstrName,sRecordName],True);
  965. end;
  966. sl:=format(' %s = %s;',[sRecordName,stype]);
  967. if bIsUserDefined and not bIsExternalDecl and (FTypes.IndexOf(stype)=-1) then //not defined yet, defer
  968. begin
  969. slDeferredDeclaration.Add(sl);
  970. slDeferredPendingType.Add(stype);
  971. slDeferredType.Add(sRecordName);
  972. end
  973. else
  974. begin
  975. AddToInterface(sl);
  976. FTypes.Add(sRecordName);
  977. ReleasePendingType(sRecordName);
  978. end;
  979. end;
  980. end;
  981. TI.ReleaseTypeAttr(TA);
  982. end;
  983. if slDeferredDeclaration.Count>1 then // circular references
  984. begin
  985. AddToHeader('// Error : the following type declarations have circular references',True);
  986. AddToInterface('// circular references start here');
  987. for j:=0 to slDeferredDeclaration.Count-1 do
  988. AddToHeader('// %s',[slDeferredType[j]]);
  989. for j:=0 to slDeferredDeclaration.Count-1 do
  990. AddToInterface(slDeferredDeclaration[j]);
  991. end;
  992. finally
  993. slDeferredDeclaration.Free;
  994. slDeferredPendingType.Free;
  995. slDeferredType.Free;
  996. end;
  997. end;
  998. Procedure TTypeLibImporter.CreateInterfaces(Const TL : ITypeLib; TICount : Integer);
  999. Var
  1000. i : integer;
  1001. BstrName, BstrDocString, BstrHelpFile : WideString;
  1002. dwHelpContext : DWORD;
  1003. TI,TIref : ITypeInfo;
  1004. TA,TAref : LPTYPEATTR;
  1005. TIT : TYPEKIND;
  1006. RTIT : HREFTYPE;
  1007. begin
  1008. // interface declarations
  1009. AddToInterface('//interface declarations');
  1010. for i:=0 to TIcount-1 do
  1011. begin
  1012. OleCheck(TL.GetTypeInfoType(i, TIT));
  1013. OleCheck(TL.GetTypeInfo(i, TI));
  1014. OleCheck(TL.GetDocumentation(i, @BstrName, @BstrDocString, @dwHelpContext, @BstrHelpFile));
  1015. if (TIT=TKIND_DISPATCH) or (TIT=TKIND_INTERFACE) then
  1016. begin
  1017. OleCheck(TI.GetTypeAttr(TA));
  1018. if (TIT=TKIND_DISPATCH) then
  1019. begin
  1020. // get also TKIND_INTERFACE if dual interface
  1021. if (TA^.wTypeFlags and TYPEFLAG_FDUAL)=TYPEFLAG_FDUAL then
  1022. begin
  1023. OleCheck(TI.GetRefTypeOfImplType(-1,RTIT));
  1024. OleCheck(TI.GetRefTypeInfo(RTIT,TIref));
  1025. OleCheck(TIref.GetTypeAttr(TAref));
  1026. AddToInterface(interfacedeclaration(BstrName,BstrDocString,TIref,TAref,false,false));
  1027. TIref.ReleaseTypeAttr(TAref);
  1028. AddToInterface(interfacedeclaration(BstrName,BstrDocString,TI,TA,true,false));
  1029. end
  1030. else
  1031. AddToInterface(interfacedeclaration(BstrName,BstrDocString,TI,TA,true,true));
  1032. end
  1033. else
  1034. AddToInterface(interfacedeclaration(BstrName,BstrDocString,TI,TA,false,false));
  1035. TI.ReleaseTypeAttr(TA);
  1036. end;
  1037. end;
  1038. end;
  1039. Procedure TTypeLibImporter.CreateCoClasses(Const TL : ITypeLib; TICount : Integer);
  1040. Var
  1041. i, j ,idx: integer;
  1042. BstrName, BstrDocString, BstrHelpFile, BstrNameRef : WideString;
  1043. dwHelpContext : DWORD;
  1044. TI,TIref : ITypeInfo;
  1045. TA : LPTYPEATTR;
  1046. TIT : TYPEKIND;
  1047. RTIT : HREFTYPE;
  1048. sDefIntf, sDefEvents : string;
  1049. ITF:WINT;
  1050. begin
  1051. //CoClasses
  1052. AddToInterface('//CoClasses');
  1053. AddToImplementation('implementation');
  1054. AddToImplementation('');
  1055. AddToImplementation('uses comobj;');
  1056. AddToImplementation('');
  1057. for i:=0 to TIcount-1 do
  1058. begin
  1059. OleCheck(TL.GetTypeInfoType(i, TIT));
  1060. if TIT =TKIND_COCLASS then
  1061. begin
  1062. OleCheck(TL.GetTypeInfo(i, TI));
  1063. OleCheck(TL.GetDocumentation(i, @BstrName, @BstrDocString, @dwHelpContext, @BstrHelpFile));
  1064. OleCheck(TI.GetTypeAttr(TA));
  1065. // get default interface and events.
  1066. sDefEvents:='';
  1067. for j:=0 to TA^.cImplTypes-1 do
  1068. begin
  1069. OleCheck(TI.GetImplTypeFlags(J,ITF));
  1070. if (ITF and IMPLTYPEFLAG_FDEFAULT)<>0 then
  1071. begin
  1072. OleCheck(TI.GetRefTypeOfImplType(J,RTIT));
  1073. OleCheck(TI.GetRefTypeInfo(RTIT,TIref));
  1074. OleCheck(TIRef.GetDocumentation(DISPID_UNKNOWN, @BstrNameRef, nil, nil, nil));
  1075. if (ITF and IMPLTYPEFLAG_FSOURCE)<>0 then
  1076. begin
  1077. sDefEvents:=BstrNameRef;
  1078. idx:=FEventDisp.IndexOf(sDefEvents);
  1079. if idx<0 then // should not happen
  1080. sDefEvents:='';
  1081. end
  1082. else
  1083. sDefIntf:=BstrNameRef;
  1084. end;
  1085. end;
  1086. if sDefEvents<>'' then //add event signatures
  1087. begin
  1088. AddToInterface(FEventSignatures[idx]);
  1089. FEventSignatures[idx]:=''; // only add event signatures only once. Multiple coclasses can use same events
  1090. AddToInterface('');
  1091. end;
  1092. AddToInterFace(' Co%s = Class',[BstrName]);
  1093. AddToInterface(' Public');
  1094. AddToInterface(' Class Function Create: %s;',[sDefIntf]);
  1095. AddToInterFace(' Class Function CreateRemote(const MachineName: string): %s;',[sDefIntf]);
  1096. AddToInterFace(' end;');
  1097. AddToInterFace('');
  1098. if FActiveX then
  1099. begin
  1100. if FUses.IndexOf('ActiveXContainer')<0 then
  1101. FUses.Add('ActiveXContainer');
  1102. AddToInterFace(' T%s = Class(TActiveXContainer)',[BstrName]);
  1103. AddToInterface(' Private');
  1104. AddToInterface(' FServer:%s;',[sDefIntf]);
  1105. if (sDefEvents<>'') then //add function variables
  1106. begin
  1107. if FUses.IndexOf('Eventsink')<0 then
  1108. FUses.Add('EventSink');
  1109. AddToInterface(FEventFunctions[idx]);
  1110. AddToInterface(' FEventSink:TEventSink;',[sDefIntf]);
  1111. AddToInterface(' procedure EventSinkInvoke(Sender: TObject; DispID: Integer;');
  1112. AddToInterface(' const IID: TGUID; LocaleID: Integer; Flags: Word;');
  1113. AddToInterface(' Params: tagDISPPARAMS; VarResult, ExcepInfo, ArgErr: Pointer);');
  1114. end;
  1115. AddToInterface(' Public');
  1116. AddToInterface(' constructor Create(TheOwner: TComponent); override;');
  1117. AddToInterface(' destructor Destroy; override;');
  1118. AddToInterface(' property OleServer:%s read FServer;',[sDefIntf]);
  1119. AddToInterFace(' Published');
  1120. AddToInterFace(' property Align;');
  1121. AddToInterFace(' property Anchors;');
  1122. AddToInterFace(' property AutoSize;');
  1123. AddToInterFace(' property BorderSpacing;');
  1124. AddToInterFace(' property ChildSizing;');
  1125. AddToInterFace(' property ClientHeight;');
  1126. AddToInterFace(' property ClientWidth;');
  1127. AddToInterFace(' property Constraints;');
  1128. AddToInterFace(' property DockSite;');
  1129. AddToInterFace(' property DragCursor;');
  1130. AddToInterFace(' property DragKind;');
  1131. AddToInterFace(' property DragMode;');
  1132. AddToInterFace(' property Enabled;');
  1133. AddToInterFace(' property ParentShowHint;');
  1134. AddToInterFace(' property PopupMenu;');
  1135. AddToInterFace(' property ShowHint;');
  1136. AddToInterFace(' property TabOrder;');
  1137. AddToInterFace(' property TabStop;');
  1138. AddToInterFace(' property UseDockManager default True;');
  1139. AddToInterFace(' property Visible;');
  1140. AddToInterFace(' property OnContextPopup;');
  1141. AddToInterFace(' property OnDockDrop;');
  1142. AddToInterFace(' property OnDockOver;');
  1143. AddToInterFace(' property OnDragDrop;');
  1144. AddToInterFace(' property OnDragOver;');
  1145. AddToInterFace(' property OnEndDock;');
  1146. AddToInterFace(' property OnEndDrag;');
  1147. AddToInterFace(' property OnEnter;');
  1148. AddToInterFace(' property OnExit;');
  1149. AddToInterFace(' property OnGetSiteInfo;');
  1150. AddToInterFace(' property OnGetDockCaption;');
  1151. AddToInterFace(' property OnResize;');
  1152. AddToInterFace(' property OnStartDock;');
  1153. AddToInterFace(' property OnStartDrag;');
  1154. AddToInterFace(' property OnStatusText;');
  1155. AddToInterFace(' property OnUnDock;');
  1156. if (sDefEvents<>'') then
  1157. AddToInterface(FEventProperties[idx]);
  1158. AddToInterFace(' property Active;');
  1159. AddToInterFace(' end;');
  1160. AddToInterFace('');
  1161. end
  1162. else if (sDefEvents<>'') then //add function variables
  1163. begin
  1164. if FUses.IndexOf('Eventsink')<0 then
  1165. FUses.Add('EventSink');
  1166. AddToInterFace(' T%s = Class(TEventSink)',[BstrName]);
  1167. AddToInterface(' Private');
  1168. AddToInterface(FEventFunctions[idx]);
  1169. AddToInterface(' fServer:%s;',[sDefIntf]);
  1170. AddToInterface(' procedure EventSinkInvoke(Sender: TObject; DispID: Integer;');
  1171. AddToInterface(' const IID: TGUID; LocaleID: Integer; Flags: Word;');
  1172. AddToInterface(' Params: tagDISPPARAMS; VarResult, ExcepInfo, ArgErr: Pointer);');
  1173. AddToInterface(' Public');
  1174. AddToInterface(' constructor Create(TheOwner: TComponent); override;');
  1175. AddToInterface(' property ComServer:%s read fServer;',[sDefIntf]);
  1176. AddToInterface(FEventProperties[idx]);
  1177. AddToInterFace(' end;');
  1178. AddToInterFace('');
  1179. end;
  1180. AddToImplementation('Class Function Co%s.Create: %s;',[BstrName,sDefIntf]);
  1181. AddToImplementation('begin');
  1182. AddToImplementation(' Result := CreateComObject(CLASS_%s) as %s;',[BstrName,sDefIntf]);
  1183. AddToImplementation('end;');
  1184. AddToImplementation('');
  1185. AddToImplementation('Class Function Co%s.CreateRemote(const MachineName: string): %s;',[BstrName,sDefIntf]);
  1186. AddToImplementation('begin');
  1187. AddToImplementation(' Result := CreateRemoteComObject(MachineName,CLASS_%s) as %s;',[BstrName,sDefIntf]);
  1188. AddToImplementation('end;');
  1189. AddToImplementation('');
  1190. if FActiveX then
  1191. begin
  1192. AddToImplementation('constructor T%s.Create(TheOwner: TComponent);',[BstrName]);
  1193. AddToImplementation('begin');
  1194. AddToImplementation(' inherited Create(TheOwner);');
  1195. AddToImplementation(' FServer:=Co%s.Create;',[BstrName]);
  1196. AddToImplementation(' ComServer:=FServer;',[BstrName]);
  1197. if (sDefEvents<>'') then
  1198. begin
  1199. AddToImplementation(' FEventSink:=TEventSink.Create(Self);');
  1200. AddToImplementation(' FEventSink.OnInvoke:=EventSinkInvoke;');
  1201. AddToImplementation(' FEventSink.Connect(FServer,%s);',[FEventDisp[idx]]);
  1202. end;
  1203. AddToImplementation('end;');
  1204. AddToImplementation('');
  1205. AddToImplementation('destructor T%s.Destroy;',[BstrName]);
  1206. AddToImplementation('begin');
  1207. if (sDefEvents<>'') then
  1208. AddToImplementation(' FEventSink.Destroy;');
  1209. AddToImplementation(' inherited destroy;');
  1210. AddToImplementation('end;');
  1211. AddToImplementation('');
  1212. if (sDefEvents<>'') then
  1213. begin
  1214. AddToImplementation('procedure T%s.EventSinkInvoke(Sender: TObject; DispID: Integer;',[BstrName]);
  1215. AddToImplementation(' const IID: TGUID; LocaleID: Integer; Flags: Word; Params: tagDISPPARAMS;');
  1216. AddToImplementation(' VarResult, ExcepInfo, ArgErr: Pointer);');
  1217. AddToImplementation('begin');
  1218. AddToImplementation(' case DispID of');
  1219. AddToImplementation(FEventImplementations[idx]);
  1220. AddToImplementation(' end;');
  1221. AddToImplementation('end;');
  1222. AddToImplementation('');
  1223. end;
  1224. end
  1225. else if sDefEvents<>'' then //add event implementations
  1226. begin
  1227. AddToImplementation('constructor T%s.Create(TheOwner: TComponent);',[BstrName]);
  1228. AddToImplementation('begin');
  1229. AddToImplementation(' inherited Create(TheOwner);');
  1230. AddToImplementation(' OnInvoke:=EventSinkInvoke;');
  1231. AddToImplementation(' fServer:=Co%s.Create;',[BstrName]);
  1232. AddToImplementation(' Connect(fServer,%s);',[FEventDisp[idx]]);
  1233. AddToImplementation('end;');
  1234. AddToImplementation('');
  1235. AddToImplementation('procedure T%s.EventSinkInvoke(Sender: TObject; DispID: Integer;',[BstrName]);
  1236. AddToImplementation(' const IID: TGUID; LocaleID: Integer; Flags: Word; Params: tagDISPPARAMS;');
  1237. AddToImplementation(' VarResult, ExcepInfo, ArgErr: Pointer);');
  1238. AddToImplementation('begin');
  1239. AddToImplementation(' case DispID of');
  1240. AddToImplementation(FEventImplementations[idx]);
  1241. AddToImplementation(' end;');
  1242. AddToImplementation('end;');
  1243. AddToImplementation('');
  1244. end;
  1245. TI.ReleaseTypeAttr(TA);
  1246. end;
  1247. end;
  1248. end;
  1249. Procedure TTypeLibImporter.CreateUnitHeader(Const TL : ITypeLib; const LA: lpTLIBATTR);
  1250. Var
  1251. BstrName, BstrDocString, BstrHelpFile : WideString;
  1252. dwHelpContext: DWORD;
  1253. begin
  1254. OleCheck(TL.GetDocumentation(-1, @BstrName, @BstrDocString, @dwHelpContext, @BstrHelpFile));
  1255. if (UnitName='') then
  1256. if FAppendVersionNumber then
  1257. UnitName:=format('%s_%d_%d_TLB',[BstrName,LA^.wMajorVerNum,LA^.wMinorVerNum])
  1258. else
  1259. UnitName:=format('%s_TLB',[BstrName]);
  1260. //header
  1261. AddToHeader('Unit %s;',[UnitName],True);
  1262. AddToHeader('',true);
  1263. AddToHeader('// Imported %s on %s from %s',[BstrName,DateTimeToStr(Now()),InputFilename],True);
  1264. AddToHeader('',true);
  1265. AddToHeader('{$mode delphi}{$H+}',true);
  1266. AddToHeader('',true);
  1267. AddToHeader('interface',true);
  1268. AddToHeader('',true);
  1269. FUses.Add('Windows');
  1270. FUses.Add('ActiveX');
  1271. FUses.Add('Classes');
  1272. //FUses.Add('OleServer');
  1273. FUses.Add('Variants');
  1274. AddToInterface('Const');
  1275. AddToInterface(' %sMajorVersion = %d;',[BstrName,LA^.wMajorVerNum]);
  1276. AddToInterface(' %sMinorVersion = %d;',[BstrName,LA^.wMinorVerNum]);
  1277. AddToInterface(' %sLCID = %x;',[BstrName,LA^.LCID]);
  1278. AddToInterface(' LIBID_%s : TGUID = ''%s'';',[BstrName,GUIDToString(LA^.GUID)]);
  1279. AddToInterface('');
  1280. end;
  1281. Procedure TTypeLibImporter.DoImportTypelib;
  1282. var
  1283. TL: ITypelib;
  1284. TIcount:integer;
  1285. LA: lpTLIBATTR;
  1286. begin
  1287. Header.Clear;
  1288. InterfaceSection.Clear;
  1289. OleCheck(LoadTypeLib(PWidechar(InputFileName), TL ));
  1290. OleCheck(TL.GetLibAttr(LA));
  1291. try
  1292. CreateUnitHeader(TL,LA);
  1293. TIcount:=TL.GetTypeInfoCount;
  1294. ImportGUIDs(TL,TICount);
  1295. ImportEnums(TL,TICount);
  1296. CreateForwards(TL,TICount);
  1297. CreateRecordsUnionsAliases(TL,TICount);
  1298. CreateInterFaces(TL,TICount);
  1299. CreateCoClasses(TL,TICount);
  1300. finally
  1301. TL.ReleaseTLibAttr(LA);
  1302. end;
  1303. BuildUnit;
  1304. end;
  1305. procedure TTypeLibImporter.BuildUnit;
  1306. Var
  1307. l : string;
  1308. I : Integer;
  1309. begin
  1310. UnitSource.AddStrings(Header);
  1311. UnitSource.Add('Uses');
  1312. L:=' ';
  1313. For I:=0 to FUses.Count-1 do
  1314. begin
  1315. L:=L+FUses[i];
  1316. If (I<Fuses.Count-1) then
  1317. L:=L+','
  1318. else
  1319. L:=L+';';
  1320. if (Length(L)>72) then
  1321. begin
  1322. UnitSource.Add(L);
  1323. L:=' ';
  1324. end;
  1325. end;
  1326. if (L<>' ') then
  1327. UnitSource.Add(L);
  1328. UnitSource.addStrings(InterfaceSection);
  1329. UnitSource.addStrings(ImplementationSection);
  1330. UnitSource.Add('end.');
  1331. end;
  1332. { TTypeLibImporter }
  1333. procedure TTypeLibImporter.SetOutputFileName(AValue: String);
  1334. Var
  1335. UN : String;
  1336. begin
  1337. if FOutputFileName=AValue then Exit;
  1338. UN:=ChangeFileExt(ExtractFileName(AValue),'');
  1339. if not IsValidIdent(UN) then
  1340. Raise Exception.CreateFmt(SErrInvalidUnitName,[UN]);
  1341. FOutputFileName:=AValue;
  1342. SetUnitName(UN)
  1343. end;
  1344. procedure TTypeLibImporter.SetUnitName(AValue: string);
  1345. begin
  1346. if FUnitname=AValue then Exit;
  1347. if not IsValidIdent(AVAlue) then
  1348. Raise Exception.CreateFmt(SErrInvalidUnitName,[AValue]);
  1349. FUnitname:=AValue;
  1350. if (OutputFileName<>'') then
  1351. OutputFileName:=ExtractFilePath(OutputFileName)+UnitName+'.pas';
  1352. end;
  1353. procedure TTypeLibImporter.AddToUses(const AUnit: String);
  1354. begin
  1355. If FUses.IndexOf(AUnit)=-1 then
  1356. FUses.add(AUnit);
  1357. end;
  1358. procedure TTypeLibImporter.AddToHeader(const ALine: String;
  1359. AllowDuplicate: Boolean);
  1360. begin
  1361. If (AllowDuplicate) or (FHeader.IndexOf(ALine)=-1) then
  1362. FHeader.Add(ALine);
  1363. end;
  1364. procedure TTypeLibImporter.AddToHeader(const Fmt: String; Args: array of const;
  1365. AllowDuplicate: Boolean);
  1366. begin
  1367. AddToheader(Format(Fmt,Args),AllowDuplicate)
  1368. end;
  1369. procedure TTypeLibImporter.AddToInterface(const ALine: String);
  1370. begin
  1371. FInterface.Add(ALine);
  1372. end;
  1373. procedure TTypeLibImporter.AddToInterface(const Fmt: String;
  1374. Args: array of const);
  1375. begin
  1376. FInterface.Add(Format(Fmt,Args));
  1377. end;
  1378. procedure TTypeLibImporter.AddToImplementation(const ALine: String);
  1379. begin
  1380. FImplementation.Add(ALine);
  1381. end;
  1382. procedure TTypeLibImporter.AddToImplementation(const Fmt: String;
  1383. Args: array of const);
  1384. begin
  1385. FImplementation.Add(Format(Fmt,Args));
  1386. end;
  1387. constructor TTypeLibImporter.Create(AOwner: TComponent);
  1388. begin
  1389. inherited Create(AOwner);
  1390. FDependencies:=TStringList.Create;
  1391. FUnitSource:=TStringList.Create;
  1392. FAppendVersionNumber:=true;
  1393. end;
  1394. destructor TTypeLibImporter.Destroy;
  1395. begin
  1396. FreeAndNil(FDependencies);
  1397. FreeAndNil(FUnitSource);
  1398. inherited Destroy;
  1399. end;
  1400. procedure TTypeLibImporter.Execute;
  1401. begin
  1402. FDependencies.Clear;
  1403. FUnitSource.Clear;
  1404. FHeader:=TStringList.Create;
  1405. FInterface:=TStringList.Create;
  1406. FImplementation:=TStringList.Create;
  1407. FUses:=TStringList.Create;
  1408. FTypes:=TStringList.Create;
  1409. FEventDisp:=TStringList.Create;
  1410. FEventIID:=TStringList.Create;
  1411. FEventSignatures:=TStringList.Create;
  1412. FEventFunctions:=TStringList.Create;
  1413. FEventProperties:=TStringList.Create;
  1414. FEventImplementations:=TStringList.Create;
  1415. try
  1416. DoImportTypeLib;
  1417. If (OutputFileName<>'') then
  1418. UnitSource.SaveToFile(OutputFileName);
  1419. finally
  1420. FreeAndNil(FEventImplementations);
  1421. FreeAndNil(FEventProperties);
  1422. FreeAndNil(FEventFunctions);
  1423. FreeAndNil(FEventSignatures);
  1424. FreeAndNil(FEventIID);
  1425. FreeAndNil(FEventDisp);
  1426. FreeAndNil(FTypes);
  1427. FreeAndNil(FUses);
  1428. FreeAndNil(FInterface);
  1429. FreeAndNil(FHeader);
  1430. FreeAndNil(FImplementation);
  1431. end;
  1432. end;
  1433. end.