objpas.inc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team
  4. This unit makes Free Pascal as much as possible Delphi compatible
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. procedure DoDispCallByIDError(res : Pointer; const disp : IDispatch;desc : PDispDesc; params : Pointer);
  12. begin
  13. handleerrorframe(RuntimeErrorExitCodes[reVarDispatch],get_frame);
  14. end;
  15. procedure fpc_dispatch_by_id(Result: Pointer; const Dispatch: pointer;
  16. DispDesc: Pointer; Params: Pointer); compilerproc;
  17. type
  18. TDispProc = procedure(res : Pointer; const disp : IDispatch;desc : PDispDesc; params : Pointer);
  19. begin
  20. TDispProc(DispCallByIDProc)(Result,IDispatch(Dispatch),DispDesc,Params);
  21. end;
  22. {****************************************************************************
  23. Internal Routines called from the Compiler
  24. ****************************************************************************}
  25. { the reverse order of the parameters make code generation easier }
  26. function fpc_do_is(aclass : tclass;aobject : tobject) : boolean;[public,alias: 'FPC_DO_IS']; compilerproc;
  27. begin
  28. fpc_do_is:=assigned(aobject) and assigned(aclass) and
  29. aobject.inheritsfrom(aclass);
  30. end;
  31. { the reverse order of the parameters make code generation easier }
  32. function fpc_do_as(aclass : tclass;aobject : tobject): tobject;[public,alias: 'FPC_DO_AS']; compilerproc;
  33. begin
  34. if assigned(aobject) and not(aobject.inheritsfrom(aclass)) then
  35. handleerrorframe(219,get_frame);
  36. result := aobject;
  37. end;
  38. { interface helpers }
  39. procedure fpc_intf_decr_ref(var i: pointer);[public,alias: 'FPC_INTF_DECR_REF']; compilerproc;
  40. begin
  41. if assigned(i) then
  42. begin
  43. IUnknown(i)._Release;
  44. i:=nil;
  45. end;
  46. end;
  47. { local declaration for intf_decr_ref for local access }
  48. procedure intf_decr_ref(var i: pointer); [external name 'FPC_INTF_DECR_REF'];
  49. procedure fpc_intf_incr_ref(i: pointer);[public,alias: 'FPC_INTF_INCR_REF']; compilerproc;
  50. begin
  51. if assigned(i) then
  52. IUnknown(i)._AddRef;
  53. end;
  54. { local declaration of intf_incr_ref for local access }
  55. procedure intf_incr_ref(i: pointer); [external name 'FPC_INTF_INCR_REF'];
  56. procedure fpc_intf_assign(var D: pointer; const S: pointer);[public,alias: 'FPC_INTF_ASSIGN']; compilerproc;
  57. begin
  58. if assigned(S) then
  59. IUnknown(S)._AddRef;
  60. if assigned(D) then
  61. IUnknown(D)._Release;
  62. D:=S;
  63. end;
  64. procedure fpc_intf_assign_by_iid(var D: pointer; const S: pointer; const iid: TGUID);[public,alias: 'FPC_INTF_ASSIGN2']; compilerproc;
  65. var
  66. tmp : pointer;
  67. begin
  68. if assigned(S) then
  69. begin
  70. if IUnknown(S).QueryInterface(iid,tmp)<>S_OK then
  71. handleerror(219);
  72. if assigned(D) then
  73. IUnknown(D)._Release;
  74. D:=tmp;
  75. end
  76. else
  77. begin
  78. if assigned(D) then
  79. IUnknown(D)._Release;
  80. D:=nil;
  81. end;
  82. end;
  83. function fpc_intf_as(const S: pointer; const iid: TGUID): IInterface;[public,alias: 'FPC_INTF_AS']; compilerproc;
  84. var
  85. tmpi: pointer; // _AddRef before _Release
  86. begin
  87. if assigned(S) then
  88. begin
  89. if IUnknown(S).QueryInterface(iid,tmpi)<>S_OK then
  90. handleerror(219);
  91. pointer(fpc_intf_as):=tmpi;
  92. end
  93. else
  94. fpc_intf_as:=nil;
  95. end;
  96. function fpc_class_as_intf(const S: pointer; const iid: TGUID): IInterface;[public,alias: 'FPC_CLASS_AS_INTF']; compilerproc;
  97. var
  98. tmpi: pointer; // _AddRef before _Release
  99. begin
  100. if assigned(S) then
  101. begin
  102. if not TObject(S).GetInterface(iid,tmpi) then
  103. handleerror(219);
  104. pointer(fpc_class_as_intf):=tmpi;
  105. end
  106. else
  107. fpc_class_as_intf:=nil;
  108. end;
  109. {****************************************************************************
  110. TOBJECT
  111. ****************************************************************************}
  112. constructor TObject.Create;
  113. begin
  114. end;
  115. destructor TObject.Destroy;
  116. begin
  117. end;
  118. procedure TObject.Free;
  119. begin
  120. // the call via self avoids a warning
  121. if self<>nil then
  122. self.destroy;
  123. end;
  124. class function TObject.InstanceSize : SizeInt;
  125. begin
  126. InstanceSize:=pSizeInt(pointer(self)+vmtInstanceSize)^;
  127. end;
  128. procedure InitInterfacePointers(objclass: tclass;instance : pointer);
  129. var
  130. i: integer;
  131. intftable: pinterfacetable;
  132. Res: pinterfaceentry;
  133. begin
  134. while assigned(objclass) do
  135. begin
  136. intftable:=pinterfacetable((pointer(objclass)+vmtIntfTable)^);
  137. if assigned(intftable) then
  138. begin
  139. i:=intftable^.EntryCount;
  140. Res:=@intftable^.Entries[0];
  141. while i>0 do begin
  142. if Res^.IType = etStandard then
  143. ppointer(@(pbyte(instance)[Res^.IOffset]))^:=
  144. pointer(Res^.VTable);
  145. inc(Res);
  146. dec(i);
  147. end;
  148. end;
  149. objclass:=pclass(pointer(objclass)+vmtParent)^;
  150. end;
  151. end;
  152. class function TObject.InitInstance(instance : pointer) : tobject; {$ifdef SYSTEMINLINE} inline; {$ENDIF}
  153. begin
  154. { the size is saved at offset 0 }
  155. fillchar(instance^, InstanceSize, 0);
  156. { insert VMT pointer into the new created memory area }
  157. { (in class methods self contains the VMT!) }
  158. ppointer(instance)^:=pointer(self);
  159. InitInterfacePointers(self,instance);
  160. InitInstance:=TObject(Instance);
  161. end;
  162. class function TObject.ClassParent : tclass;
  163. begin
  164. { type of self is class of tobject => it points to the vmt }
  165. { the parent vmt is saved at offset vmtParent }
  166. classparent:=pclass(pointer(self)+vmtParent)^;
  167. end;
  168. class function TObject.NewInstance : tobject;
  169. var
  170. p : pointer;
  171. begin
  172. getmem(p, InstanceSize);
  173. if p <> nil then
  174. InitInstance(p);
  175. NewInstance:=TObject(p);
  176. end;
  177. procedure TObject.FreeInstance;
  178. begin
  179. CleanupInstance;
  180. FreeMem(Pointer(Self));
  181. end;
  182. class function TObject.ClassType : TClass;
  183. begin
  184. ClassType:=TClass(Pointer(Self))
  185. end;
  186. type
  187. tmethodnamerec = packed record
  188. name : pshortstring;
  189. addr : pointer;
  190. end;
  191. tmethodnametable = packed record
  192. count : dword;
  193. entries : packed array[0..0] of tmethodnamerec;
  194. end;
  195. pmethodnametable = ^tmethodnametable;
  196. class function TObject.MethodAddress(const name : shortstring) : pointer;
  197. var
  198. methodtable : pmethodnametable;
  199. i : dword;
  200. vmt : tclass;
  201. begin
  202. vmt:=self;
  203. while assigned(vmt) do
  204. begin
  205. methodtable:=pmethodnametable((Pointer(vmt)+vmtMethodTable)^);
  206. if assigned(methodtable) then
  207. begin
  208. for i:=0 to methodtable^.count-1 do
  209. if ShortCompareText(methodtable^.entries[i].name^, name)=0 then
  210. begin
  211. MethodAddress:=methodtable^.entries[i].addr;
  212. exit;
  213. end;
  214. end;
  215. vmt:=pclass(pointer(vmt)+vmtParent)^;
  216. end;
  217. MethodAddress:=nil;
  218. end;
  219. class function TObject.MethodName(address : pointer) : shortstring;
  220. var
  221. methodtable : pmethodnametable;
  222. i : dword;
  223. vmt : tclass;
  224. begin
  225. vmt:=self;
  226. while assigned(vmt) do
  227. begin
  228. methodtable:=pmethodnametable((Pointer(vmt)+vmtMethodTable)^);
  229. if assigned(methodtable) then
  230. begin
  231. for i:=0 to methodtable^.count-1 do
  232. if methodtable^.entries[i].addr=address then
  233. begin
  234. MethodName:=methodtable^.entries[i].name^;
  235. exit;
  236. end;
  237. end;
  238. vmt:=pclass(pointer(vmt)+vmtParent)^;
  239. end;
  240. MethodName:='';
  241. end;
  242. function TObject.FieldAddress(const name : shortstring) : pointer;
  243. type
  244. PFieldInfo = ^TFieldInfo;
  245. TFieldInfo =
  246. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  247. packed
  248. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  249. record
  250. FieldOffset: PtrUInt;
  251. ClassTypeIndex: Word;
  252. Name: ShortString;
  253. end;
  254. PFieldTable = ^TFieldTable;
  255. TFieldTable =
  256. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  257. packed
  258. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  259. record
  260. FieldCount: Word;
  261. ClassTable: Pointer;
  262. { should be array[Word] of TFieldInfo; but
  263. Elements have variant size! force at least proper alignment }
  264. Fields: array[0..0] of TFieldInfo
  265. end;
  266. var
  267. CurClassType: TClass;
  268. FieldTable: PFieldTable;
  269. FieldInfo: PFieldInfo;
  270. i: Integer;
  271. begin
  272. if Length(name) > 0 then
  273. begin
  274. CurClassType := ClassType;
  275. while CurClassType <> nil do
  276. begin
  277. FieldTable := PFieldTable((Pointer(CurClassType) + vmtFieldTable)^);
  278. if FieldTable <> nil then
  279. begin
  280. FieldInfo := @FieldTable^.Fields[0];
  281. for i := 0 to FieldTable^.FieldCount - 1 do
  282. begin
  283. if ShortCompareText(FieldInfo^.Name, name) = 0 then
  284. begin
  285. fieldaddress := Pointer(Self) + FieldInfo^.FieldOffset;
  286. exit;
  287. end;
  288. FieldInfo := PFieldInfo(PByte(@FieldInfo^.Name) + 1 + Length(FieldInfo^.Name));
  289. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  290. { align to largest field of TFieldInfo }
  291. FieldInfo := Align(FieldInfo, SizeOf(PtrUInt));
  292. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  293. end;
  294. end;
  295. { Try again with the parent class type }
  296. CurClassType:=pclass(pointer(CurClassType)+vmtParent)^;
  297. end;
  298. end;
  299. fieldaddress:=nil;
  300. end;
  301. function TObject.SafeCallException(exceptobject : tobject;
  302. exceptaddr : pointer) : longint;
  303. begin
  304. safecallexception:=0;
  305. end;
  306. class function TObject.ClassInfo : pointer;
  307. begin
  308. ClassInfo:=ppointer(Pointer(self)+vmtTypeInfo)^;
  309. end;
  310. class function TObject.ClassName : ShortString;
  311. begin
  312. ClassName:=PShortString((Pointer(Self)+vmtClassName)^)^;
  313. end;
  314. class function TObject.ClassNameIs(const name : string) : boolean;
  315. begin
  316. ClassNameIs:=ShortCompareText(ClassName, name) = 0;
  317. end;
  318. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  319. var
  320. vmt : tclass;
  321. begin
  322. vmt:=self;
  323. while assigned(vmt) do
  324. begin
  325. if vmt=aclass then
  326. begin
  327. InheritsFrom:=true;
  328. exit;
  329. end;
  330. vmt:=pclass(pointer(vmt)+vmtParent)^;
  331. end;
  332. InheritsFrom:=false;
  333. end;
  334. class function TObject.stringmessagetable : pstringmessagetable;
  335. begin
  336. stringmessagetable:=pstringmessagetable((pointer(Self)+vmtMsgStrPtr)^);
  337. end;
  338. type
  339. tmessagehandler = procedure(var msg) of object;
  340. tmessagehandlerrec = packed record
  341. proc : pointer;
  342. obj : pointer;
  343. end;
  344. procedure TObject.Dispatch(var message);
  345. type
  346. tmsgtable = packed record
  347. index : dword;
  348. method : pointer;
  349. end;
  350. pmsgtable = ^tmsgtable;
  351. var
  352. index : dword;
  353. count,i : longint;
  354. msgtable : pmsgtable;
  355. p : pointer;
  356. vmt : tclass;
  357. msghandler : tmessagehandler;
  358. begin
  359. index:=dword(message);
  360. vmt:=ClassType;
  361. while assigned(vmt) do
  362. begin
  363. // See if we have messages at all in this class.
  364. p:=pointer(vmt)+vmtDynamicTable;
  365. If assigned(PPointer(p)^) then
  366. begin
  367. msgtable:=pmsgtable(Pointer(p^)+4);
  368. count:=pdword(p^)^;
  369. end
  370. else
  371. Count:=0;
  372. { later, we can implement a binary search here }
  373. for i:=0 to count-1 do
  374. begin
  375. if index=msgtable[i].index then
  376. begin
  377. p:=msgtable[i].method;
  378. tmessagehandlerrec(msghandler).proc:=p;
  379. tmessagehandlerrec(msghandler).obj:=self;
  380. msghandler(message);
  381. exit;
  382. end;
  383. end;
  384. vmt:=pclass(pointer(vmt)+vmtParent)^;
  385. end;
  386. DefaultHandler(message);
  387. end;
  388. procedure TObject.DispatchStr(var message);
  389. type
  390. PSizeUInt = ^SizeUInt;
  391. var
  392. name : shortstring;
  393. count,i : longint;
  394. msgstrtable : pmsgstrtable;
  395. p : pointer;
  396. vmt : tclass;
  397. msghandler : tmessagehandler;
  398. begin
  399. name:=pshortstring(@message)^;
  400. vmt:=ClassType;
  401. while assigned(vmt) do
  402. begin
  403. p:=(pointer(vmt)+vmtMsgStrPtr);
  404. If (P<>Nil) and (PPtruInt(P)^<>0) then
  405. begin
  406. count:=Pptruint(PSizeUInt(p)^)^;
  407. msgstrtable:=pmsgstrtable(PSizeUInt(P)^+sizeof(ptruint));
  408. end
  409. else
  410. Count:=0;
  411. { later, we can implement a binary search here }
  412. for i:=0 to count-1 do
  413. begin
  414. if name=msgstrtable[i].name^ then
  415. begin
  416. p:=msgstrtable[i].method;
  417. tmessagehandlerrec(msghandler).proc:=p;
  418. tmessagehandlerrec(msghandler).obj:=self;
  419. msghandler(message);
  420. exit;
  421. end;
  422. end;
  423. vmt:=pclass(pointer(vmt)+vmtParent)^;
  424. end;
  425. DefaultHandlerStr(message);
  426. end;
  427. procedure TObject.DefaultHandler(var message);
  428. begin
  429. end;
  430. procedure TObject.DefaultHandlerStr(var message);
  431. begin
  432. end;
  433. procedure TObject.CleanupInstance;
  434. Type
  435. TRecElem = packed Record
  436. Info : Pointer;
  437. Offset : Longint;
  438. end;
  439. TRecElemArray = packed array[1..Maxint] of TRecElem;
  440. PRecRec = ^TRecRec;
  441. TRecRec = record
  442. Size,Count : Longint;
  443. Elements : TRecElemArray;
  444. end;
  445. var
  446. vmt : tclass;
  447. temp : pbyte;
  448. count,
  449. i : longint;
  450. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  451. recelem : TRecElem;
  452. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  453. begin
  454. vmt:=ClassType;
  455. while vmt<>nil do
  456. begin
  457. { This need to be included here, because Finalize()
  458. has should support for tkClass }
  459. Temp:=Pointer((Pointer(vmt)+vmtInitTable)^);
  460. if Assigned(Temp) then
  461. begin
  462. inc(Temp);
  463. I:=Temp^;
  464. inc(temp,I+1); // skip name string;
  465. temp:=aligntoptr(temp);
  466. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  467. move(PRecRec(Temp)^.Count,Count,sizeof(Count));
  468. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  469. Count:=PRecRec(Temp)^.Count; // get element Count
  470. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  471. For I:=1 to count do
  472. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  473. begin
  474. move(PRecRec(Temp)^.elements[I],RecElem,sizeof(RecElem));
  475. With RecElem do
  476. int_Finalize (pointer(self)+Offset,Info);
  477. end;
  478. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  479. With PRecRec(Temp)^.elements[I] do
  480. int_Finalize (pointer(self)+Offset,Info);
  481. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  482. end;
  483. vmt:=pclass(pointer(vmt)+vmtParent)^;
  484. end;
  485. end;
  486. procedure TObject.AfterConstruction;
  487. begin
  488. end;
  489. procedure TObject.BeforeDestruction;
  490. begin
  491. end;
  492. function IsGUIDEqual(const guid1, guid2: tguid): boolean;
  493. begin
  494. IsGUIDEqual:=
  495. (guid1.D1=guid2.D1) and
  496. (PDWORD(@guid1.D2)^=PDWORD(@guid2.D2)^) and
  497. (PDWORD(@guid1.D4[0])^=PDWORD(@guid2.D4[0])^) and
  498. (PDWORD(@guid1.D4[4])^=PDWORD(@guid2.D4[4])^);
  499. end;
  500. function getinterfacebyentry(Instance: pointer; IEntry: pinterfaceentry; out obj): boolean;
  501. var
  502. Getter: function: IInterface of object;
  503. begin
  504. Pointer(Obj) := nil;
  505. if Assigned(IEntry) and Assigned(Instance) then
  506. begin
  507. case IEntry^.IType of
  508. etStandard:
  509. begin
  510. //writeln('Doing etStandard cast of ', TObject(Instance).classname(), ' with self = ', ptruint(Instance), ' and offset = ', IEntry^.IOffset);
  511. Pbyte(Obj):=Pbyte(instance)+IEntry^.IOffset;
  512. end;
  513. etFieldValue:
  514. begin
  515. //writeln('Doing etFieldValue cast of ', TObject(Instance).classname(), ' with offset = ', IEntry^.IOffset);
  516. Pointer(obj) := ppointer(Pbyte(Instance)+IEntry^.IOffset)^;
  517. end;
  518. etVirtualMethodResult:
  519. begin
  520. //writeln('Doing etVirtualMethodResult cast of ', TObject(Instance).classname());
  521. TMethod(Getter).data := Instance;
  522. TMethod(Getter).code := ppointer(Pbyte(Instance) + IEntry^.IOffset)^;
  523. Pointer(obj) := Pointer(Getter());
  524. end;
  525. etStaticMethodResult:
  526. begin
  527. //writeln('Doing etStaticMethodResult cast of ', TObject(Instance).classname());
  528. TMethod(Getter).data := Instance;
  529. TMethod(Getter).code := pointer(IEntry^.IOffset);
  530. Pointer(obj) := Pointer(Getter());
  531. end;
  532. end;
  533. end;
  534. result := assigned(pointer(obj));
  535. if result then
  536. IInterface(obj)._AddRef;
  537. end;
  538. function TObject.getinterface(const iid : tguid;out obj) : boolean;
  539. begin
  540. Result := getinterfacebyentry(self, getinterfaceentry(iid), obj);
  541. end;
  542. function TObject.getinterfacebystr(const iidstr : string;out obj) : boolean;
  543. begin
  544. Result := getinterfacebyentry(self, getinterfaceentrybystr(iidstr), obj);
  545. end;
  546. class function TObject.getinterfaceentry(const iid : tguid) : pinterfaceentry;
  547. var
  548. i: integer;
  549. intftable: pinterfacetable;
  550. Res: pinterfaceentry;
  551. begin
  552. getinterfaceentry:=nil;
  553. intftable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
  554. if assigned(intftable) then begin
  555. i:=intftable^.EntryCount;
  556. Res:=@intftable^.Entries[0];
  557. while (i>0) and
  558. not (assigned(Res^.iid) and IsGUIDEqual(Res^.iid^,iid)) do begin
  559. inc(Res);
  560. dec(i);
  561. end;
  562. if (i>0) then
  563. getinterfaceentry:=Res;
  564. end;
  565. if (getinterfaceentry=nil)and not(classparent=nil) then
  566. getinterfaceentry:=classparent.getinterfaceentry(iid)
  567. end;
  568. class function TObject.getinterfaceentrybystr(const iidstr : string) : pinterfaceentry;
  569. var
  570. i: integer;
  571. intftable: pinterfacetable;
  572. Res: pinterfaceentry;
  573. begin
  574. getinterfaceentrybystr:=nil;
  575. intftable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
  576. if assigned(intftable) then begin
  577. i:=intftable^.EntryCount;
  578. Res:=@intftable^.Entries[0];
  579. while (i>0) and (Res^.iidstr^<>iidstr) do begin
  580. inc(Res);
  581. dec(i);
  582. end;
  583. if (i>0) then
  584. getinterfaceentrybystr:=Res;
  585. end;
  586. if (getinterfaceentrybystr=nil) and not(classparent=nil) then
  587. getinterfaceentrybystr:=classparent.getinterfaceentrybystr(iidstr)
  588. end;
  589. class function TObject.getinterfacetable : pinterfacetable;
  590. begin
  591. getinterfacetable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
  592. end;
  593. {****************************************************************************
  594. TINTERFACEDOBJECT
  595. ****************************************************************************}
  596. function TInterfacedObject.QueryInterface(
  597. const iid : tguid;out obj) : longint;stdcall;
  598. begin
  599. if getinterface(iid,obj) then
  600. result:=0
  601. else
  602. result:=longint(E_NOINTERFACE);
  603. end;
  604. function TInterfacedObject._AddRef : longint;stdcall;
  605. begin
  606. _addref:=interlockedincrement(frefcount);
  607. end;
  608. function TInterfacedObject._Release : longint;stdcall;
  609. begin
  610. _Release:=interlockeddecrement(frefcount);
  611. if _Release=0 then
  612. self.destroy;
  613. end;
  614. procedure TInterfacedObject.AfterConstruction;
  615. begin
  616. { we need to fix the refcount we forced in newinstance }
  617. { further, it must be done in a thread safe way }
  618. declocked(frefcount);
  619. end;
  620. procedure TInterfacedObject.BeforeDestruction;
  621. begin
  622. if frefcount<>0 then
  623. HandleError(204);
  624. end;
  625. class function TInterfacedObject.NewInstance : TObject;
  626. begin
  627. NewInstance:=inherited NewInstance;
  628. if NewInstance<>nil then
  629. TInterfacedObject(NewInstance).frefcount:=1;
  630. end;
  631. {****************************************************************************
  632. TAGGREGATEDOBJECT
  633. ****************************************************************************}
  634. constructor TAggregatedObject.Create(const aController: IUnknown);
  635. begin
  636. inherited Create;
  637. { do not keep a counted reference to the controller! }
  638. fcontroller := Pointer(aController);
  639. end;
  640. function TAggregatedObject.QueryInterface(
  641. const iid : tguid;out obj) : longint;stdcall;
  642. begin
  643. Result := IUnknown(fcontroller).QueryInterface(iid, obj);
  644. end;
  645. function TAggregatedObject._AddRef : longint;stdcall;
  646. begin
  647. Result := IUnknown(fcontroller)._AddRef;
  648. end;
  649. function TAggregatedObject._Release : longint;stdcall;
  650. begin
  651. Result := IUnknown(fcontroller)._Release;
  652. end;
  653. function TAggregatedObject.GetController : IUnknown;
  654. begin
  655. Result := IUnknown(fcontroller);
  656. end;
  657. {****************************************************************************
  658. Exception Support
  659. ****************************************************************************}
  660. {$ifdef FPC_HAS_FEATURE_EXCEPTIONS}
  661. {$i except.inc}
  662. {$endif FPC_HAS_FEATURE_EXCEPTIONS}