objpas.inc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  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;
  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. UName : ShortString;
  199. methodtable : pmethodnametable;
  200. i : dword;
  201. vmt : tclass;
  202. begin
  203. UName := UpCase(name);
  204. vmt:=self;
  205. while assigned(vmt) do
  206. begin
  207. methodtable:=pmethodnametable((Pointer(vmt)+vmtMethodTable)^);
  208. if assigned(methodtable) then
  209. begin
  210. for i:=0 to methodtable^.count-1 do
  211. if UpCase(methodtable^.entries[i].name^)=UName then
  212. begin
  213. MethodAddress:=methodtable^.entries[i].addr;
  214. exit;
  215. end;
  216. end;
  217. vmt:=pclass(pointer(vmt)+vmtParent)^;
  218. end;
  219. MethodAddress:=nil;
  220. end;
  221. class function TObject.MethodName(address : pointer) : shortstring;
  222. var
  223. methodtable : pmethodnametable;
  224. i : dword;
  225. vmt : tclass;
  226. begin
  227. vmt:=self;
  228. while assigned(vmt) do
  229. begin
  230. methodtable:=pmethodnametable((Pointer(vmt)+vmtMethodTable)^);
  231. if assigned(methodtable) then
  232. begin
  233. for i:=0 to methodtable^.count-1 do
  234. if methodtable^.entries[i].addr=address then
  235. begin
  236. MethodName:=methodtable^.entries[i].name^;
  237. exit;
  238. end;
  239. end;
  240. vmt:=pclass(pointer(vmt)+vmtParent)^;
  241. end;
  242. MethodName:='';
  243. end;
  244. function TObject.FieldAddress(const name : shortstring) : pointer;
  245. type
  246. PFieldInfo = ^TFieldInfo;
  247. TFieldInfo =
  248. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  249. packed
  250. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  251. record
  252. FieldOffset: PtrUInt;
  253. ClassTypeIndex: Word;
  254. Name: ShortString;
  255. end;
  256. PFieldTable = ^TFieldTable;
  257. TFieldTable =
  258. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  259. packed
  260. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  261. record
  262. FieldCount: Word;
  263. ClassTable: Pointer;
  264. { should be array[Word] of TFieldInfo; but
  265. Elements have variant size! force at least proper alignment }
  266. Fields: array[0..0] of TFieldInfo
  267. end;
  268. var
  269. UName: ShortString;
  270. CurClassType: TClass;
  271. FieldTable: PFieldTable;
  272. FieldInfo: PFieldInfo;
  273. i: Integer;
  274. begin
  275. if Length(name) > 0 then
  276. begin
  277. UName := UpCase(name);
  278. CurClassType := ClassType;
  279. while CurClassType <> nil do
  280. begin
  281. FieldTable := PFieldTable((Pointer(CurClassType) + vmtFieldTable)^);
  282. if FieldTable <> nil then
  283. begin
  284. FieldInfo := @FieldTable^.Fields[0];
  285. for i := 0 to FieldTable^.FieldCount - 1 do
  286. begin
  287. if UpCase(FieldInfo^.Name) = UName then
  288. begin
  289. fieldaddress := Pointer(Self) + FieldInfo^.FieldOffset;
  290. exit;
  291. end;
  292. FieldInfo := PFieldInfo(PByte(@FieldInfo^.Name) + 1 + Length(FieldInfo^.Name));
  293. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  294. { align to largest field of TFieldInfo }
  295. FieldInfo := Align(FieldInfo, SizeOf(PtrUInt));
  296. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  297. end;
  298. end;
  299. { Try again with the parent class type }
  300. CurClassType:=pclass(pointer(CurClassType)+vmtParent)^;
  301. end;
  302. end;
  303. fieldaddress:=nil;
  304. end;
  305. function TObject.SafeCallException(exceptobject : tobject;
  306. exceptaddr : pointer) : longint;
  307. begin
  308. safecallexception:=0;
  309. end;
  310. class function TObject.ClassInfo : pointer;
  311. begin
  312. ClassInfo:=ppointer(Pointer(self)+vmtTypeInfo)^;
  313. end;
  314. class function TObject.ClassName : ShortString;
  315. begin
  316. ClassName:=PShortString((Pointer(Self)+vmtClassName)^)^;
  317. end;
  318. class function TObject.ClassNameIs(const name : string) : boolean;
  319. begin
  320. ClassNameIs:=Upcase(ClassName)=Upcase(name);
  321. end;
  322. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  323. var
  324. vmt : tclass;
  325. begin
  326. vmt:=self;
  327. while assigned(vmt) do
  328. begin
  329. if vmt=aclass then
  330. begin
  331. InheritsFrom:=true;
  332. exit;
  333. end;
  334. vmt:=pclass(pointer(vmt)+vmtParent)^;
  335. end;
  336. InheritsFrom:=false;
  337. end;
  338. class function TObject.stringmessagetable : pstringmessagetable;
  339. begin
  340. stringmessagetable:=pstringmessagetable((pointer(Self)+vmtMsgStrPtr)^);
  341. end;
  342. type
  343. tmessagehandler = procedure(var msg) of object;
  344. tmessagehandlerrec = packed record
  345. proc : pointer;
  346. obj : pointer;
  347. end;
  348. procedure TObject.Dispatch(var message);
  349. type
  350. tmsgtable = packed record
  351. index : dword;
  352. method : pointer;
  353. end;
  354. pmsgtable = ^tmsgtable;
  355. var
  356. index : dword;
  357. count,i : longint;
  358. msgtable : pmsgtable;
  359. p : pointer;
  360. vmt : tclass;
  361. msghandler : tmessagehandler;
  362. begin
  363. index:=dword(message);
  364. vmt:=ClassType;
  365. while assigned(vmt) do
  366. begin
  367. // See if we have messages at all in this class.
  368. p:=pointer(vmt)+vmtDynamicTable;
  369. If assigned(PPointer(p)^) then
  370. begin
  371. msgtable:=pmsgtable(Pointer(p^)+4);
  372. count:=pdword(p^)^;
  373. end
  374. else
  375. Count:=0;
  376. { later, we can implement a binary search here }
  377. for i:=0 to count-1 do
  378. begin
  379. if index=msgtable[i].index then
  380. begin
  381. p:=msgtable[i].method;
  382. tmessagehandlerrec(msghandler).proc:=p;
  383. tmessagehandlerrec(msghandler).obj:=self;
  384. msghandler(message);
  385. exit;
  386. end;
  387. end;
  388. vmt:=pclass(pointer(vmt)+vmtParent)^;
  389. end;
  390. DefaultHandler(message);
  391. end;
  392. procedure TObject.DispatchStr(var message);
  393. type
  394. PSizeUInt = ^SizeUInt;
  395. var
  396. name : shortstring;
  397. count,i : longint;
  398. msgstrtable : pmsgstrtable;
  399. p : pointer;
  400. vmt : tclass;
  401. msghandler : tmessagehandler;
  402. begin
  403. name:=pshortstring(@message)^;
  404. vmt:=ClassType;
  405. while assigned(vmt) do
  406. begin
  407. p:=(pointer(vmt)+vmtMsgStrPtr);
  408. If (P<>Nil) and (PPtrInt(P)^<>0) then
  409. begin
  410. count:=PPtrInt(PSizeUInt(p)^)^;
  411. msgstrtable:=pmsgstrtable(PSizeUInt(P)^+sizeof(ptrint));
  412. end
  413. else
  414. Count:=0;
  415. { later, we can implement a binary search here }
  416. for i:=0 to count-1 do
  417. begin
  418. if name=msgstrtable[i].name^ then
  419. begin
  420. p:=msgstrtable[i].method;
  421. tmessagehandlerrec(msghandler).proc:=p;
  422. tmessagehandlerrec(msghandler).obj:=self;
  423. msghandler(message);
  424. exit;
  425. end;
  426. end;
  427. vmt:=pclass(pointer(vmt)+vmtParent)^;
  428. end;
  429. DefaultHandlerStr(message);
  430. end;
  431. procedure TObject.DefaultHandler(var message);
  432. begin
  433. end;
  434. procedure TObject.DefaultHandlerStr(var message);
  435. begin
  436. end;
  437. procedure TObject.CleanupInstance;
  438. Type
  439. TRecElem = packed Record
  440. Info : Pointer;
  441. Offset : Longint;
  442. end;
  443. TRecElemArray = packed array[1..Maxint] of TRecElem;
  444. PRecRec = ^TRecRec;
  445. TRecRec = record
  446. Size,Count : Longint;
  447. Elements : TRecElemArray;
  448. end;
  449. var
  450. vmt : tclass;
  451. temp : pbyte;
  452. count,
  453. i : longint;
  454. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  455. recelem : TRecElem;
  456. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  457. begin
  458. vmt:=ClassType;
  459. while vmt<>nil do
  460. begin
  461. { This need to be included here, because Finalize()
  462. has should support for tkClass }
  463. Temp:=Pointer((Pointer(vmt)+vmtInitTable)^);
  464. if Assigned(Temp) then
  465. begin
  466. inc(Temp);
  467. I:=Temp^;
  468. inc(temp,I+1); // skip name string;
  469. temp:=aligntoptr(temp);
  470. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  471. move(PRecRec(Temp)^.Count,Count,sizeof(Count));
  472. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  473. Count:=PRecRec(Temp)^.Count; // get element Count
  474. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  475. For I:=1 to count do
  476. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  477. begin
  478. move(PRecRec(Temp)^.elements[I],RecElem,sizeof(RecElem));
  479. With RecElem do
  480. int_Finalize (pointer(self)+Offset,Info);
  481. end;
  482. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  483. With PRecRec(Temp)^.elements[I] do
  484. int_Finalize (pointer(self)+Offset,Info);
  485. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  486. end;
  487. vmt:=pclass(pointer(vmt)+vmtParent)^;
  488. end;
  489. end;
  490. procedure TObject.AfterConstruction;
  491. begin
  492. end;
  493. procedure TObject.BeforeDestruction;
  494. begin
  495. end;
  496. function IsGUIDEqual(const guid1, guid2: tguid): boolean;
  497. begin
  498. IsGUIDEqual:=
  499. (guid1.D1=guid2.D1) and
  500. (PDWORD(@guid1.D2)^=PDWORD(@guid2.D2)^) and
  501. (PDWORD(@guid1.D4[0])^=PDWORD(@guid2.D4[0])^) and
  502. (PDWORD(@guid1.D4[4])^=PDWORD(@guid2.D4[4])^);
  503. end;
  504. function getinterfacebyentry(Instance: pointer; IEntry: pinterfaceentry; out obj): boolean;
  505. var
  506. Getter: function: IInterface of object;
  507. begin
  508. Pointer(Obj) := nil;
  509. if Assigned(IEntry) and Assigned(Instance) then
  510. begin
  511. case IEntry^.IType of
  512. etStandard:
  513. begin
  514. //writeln('Doing etStandard cast of ', TObject(Instance).classname(), ' with self = ', ptruint(Instance), ' and offset = ', IEntry^.IOffset);
  515. Pointer(Obj) := Pointer(PtrInt(Instance) + IEntry^.IOffset);
  516. end;
  517. etFieldValue:
  518. begin
  519. //writeln('Doing etFieldValue cast of ', TObject(Instance).classname(), ' with offset = ', IEntry^.IOffset);
  520. Pointer(obj) := ppointer(Pointer(Instance)+IEntry^.IOffset)^;
  521. end;
  522. etVirtualMethodResult:
  523. begin
  524. //writeln('Doing etVirtualMethodResult cast of ', TObject(Instance).classname());
  525. TMethod(Getter).data := Instance;
  526. TMethod(Getter).code := ppointer(ptrint(Instance) + IEntry^.IOffset)^;
  527. Pointer(obj) := Pointer(Getter());
  528. end;
  529. etStaticMethodResult:
  530. begin
  531. //writeln('Doing etStaticMethodResult cast of ', TObject(Instance).classname());
  532. TMethod(Getter).data := Instance;
  533. TMethod(Getter).code := pointer(IEntry^.IOffset);
  534. Pointer(obj) := Pointer(Getter());
  535. end;
  536. end;
  537. end;
  538. result := assigned(pointer(obj));
  539. if result then
  540. IInterface(obj)._AddRef;
  541. end;
  542. function TObject.getinterface(const iid : tguid;out obj) : boolean;
  543. begin
  544. Result := getinterfacebyentry(self, getinterfaceentry(iid), obj);
  545. end;
  546. function TObject.getinterfacebystr(const iidstr : string;out obj) : boolean;
  547. begin
  548. Result := getinterfacebyentry(self, getinterfaceentrybystr(iidstr), obj);
  549. end;
  550. class function TObject.getinterfaceentry(const iid : tguid) : pinterfaceentry;
  551. var
  552. i: integer;
  553. intftable: pinterfacetable;
  554. Res: pinterfaceentry;
  555. begin
  556. getinterfaceentry:=nil;
  557. intftable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
  558. if assigned(intftable) then begin
  559. i:=intftable^.EntryCount;
  560. Res:=@intftable^.Entries[0];
  561. while (i>0) and
  562. not (assigned(Res^.iid) and IsGUIDEqual(Res^.iid^,iid)) do begin
  563. inc(Res);
  564. dec(i);
  565. end;
  566. if (i>0) then
  567. getinterfaceentry:=Res;
  568. end;
  569. if (getinterfaceentry=nil)and not(classparent=nil) then
  570. getinterfaceentry:=classparent.getinterfaceentry(iid)
  571. end;
  572. class function TObject.getinterfaceentrybystr(const iidstr : string) : pinterfaceentry;
  573. var
  574. i: integer;
  575. intftable: pinterfacetable;
  576. Res: pinterfaceentry;
  577. begin
  578. getinterfaceentrybystr:=nil;
  579. intftable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
  580. if assigned(intftable) then begin
  581. i:=intftable^.EntryCount;
  582. Res:=@intftable^.Entries[0];
  583. while (i>0) and (Res^.iidstr^<>iidstr) do begin
  584. inc(Res);
  585. dec(i);
  586. end;
  587. if (i>0) then
  588. getinterfaceentrybystr:=Res;
  589. end;
  590. if (getinterfaceentrybystr=nil) and not(classparent=nil) then
  591. getinterfaceentrybystr:=classparent.getinterfaceentrybystr(iidstr)
  592. end;
  593. class function TObject.getinterfacetable : pinterfacetable;
  594. begin
  595. getinterfacetable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
  596. end;
  597. {****************************************************************************
  598. TINTERFACEDOBJECT
  599. ****************************************************************************}
  600. function TInterfacedObject.QueryInterface(
  601. const iid : tguid;out obj) : longint;stdcall;
  602. begin
  603. if getinterface(iid,obj) then
  604. result:=0
  605. else
  606. result:=longint(E_NOINTERFACE);
  607. end;
  608. function TInterfacedObject._AddRef : longint;stdcall;
  609. begin
  610. _addref:=interlockedincrement(frefcount);
  611. end;
  612. function TInterfacedObject._Release : longint;stdcall;
  613. begin
  614. _Release:=interlockeddecrement(frefcount);
  615. if _Release=0 then
  616. self.destroy;
  617. end;
  618. procedure TInterfacedObject.AfterConstruction;
  619. begin
  620. { we need to fix the refcount we forced in newinstance }
  621. { further, it must be done in a thread safe way }
  622. declocked(frefcount);
  623. end;
  624. procedure TInterfacedObject.BeforeDestruction;
  625. begin
  626. if frefcount<>0 then
  627. HandleError(204);
  628. end;
  629. class function TInterfacedObject.NewInstance : TObject;
  630. begin
  631. NewInstance:=inherited NewInstance;
  632. if NewInstance<>nil then
  633. TInterfacedObject(NewInstance).frefcount:=1;
  634. end;
  635. {****************************************************************************
  636. TAGGREGATEDOBJECT
  637. ****************************************************************************}
  638. constructor TAggregatedObject.Create(const aController: IUnknown);
  639. begin
  640. inherited Create;
  641. { do not keep a counted reference to the controller! }
  642. fcontroller := Pointer(aController);
  643. end;
  644. function TAggregatedObject.QueryInterface(
  645. const iid : tguid;out obj) : longint;stdcall;
  646. begin
  647. Result := IUnknown(fcontroller).QueryInterface(iid, obj);
  648. end;
  649. function TAggregatedObject._AddRef : longint;stdcall;
  650. begin
  651. Result := IUnknown(fcontroller)._AddRef;
  652. end;
  653. function TAggregatedObject._Release : longint;stdcall;
  654. begin
  655. Result := IUnknown(fcontroller)._Release;
  656. end;
  657. function TAggregatedObject.GetController : IUnknown;
  658. begin
  659. Result := IUnknown(fcontroller);
  660. end;
  661. {****************************************************************************
  662. Exception Support
  663. ****************************************************************************}
  664. {$ifdef FPC_HAS_FEATURE_EXCEPTIONS}
  665. {$i except.inc}
  666. {$endif FPC_HAS_FEATURE_EXCEPTIONS}