objpas.inc 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839
  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. {$ifdef FPC_HAS_FEATURE_VARIANTS}
  12. procedure DoDispCallByIDError(res : Pointer; const disp : IDispatch;desc : PDispDesc; params : Pointer);
  13. begin
  14. handleerroraddrframeind(RuntimeErrorExitCodes[reVarDispatch],
  15. get_pc_addr,get_frame);
  16. end;
  17. procedure fpc_dispatch_by_id(Result: Pointer; const Dispatch: pointer;
  18. DispDesc: Pointer; Params: Pointer); compilerproc;
  19. type
  20. TDispProc = procedure(res : Pointer; const disp : IDispatch;desc : PDispDesc; params : Pointer);
  21. begin
  22. TDispProc(DispCallByIDProc)(Result,IDispatch(Dispatch),DispDesc,Params);
  23. end;
  24. {$endif FPC_HAS_FEATURE_VARIANTS}
  25. {****************************************************************************
  26. Internal Routines called from the Compiler
  27. ****************************************************************************}
  28. { the reverse order of the parameters make code generation easier }
  29. function fpc_do_is(aclass : tclass;aobject : tobject) : boolean;[public,alias: 'FPC_DO_IS']; compilerproc;
  30. begin
  31. fpc_do_is:=assigned(aobject) and assigned(aclass) and
  32. aobject.inheritsfrom(aclass);
  33. end;
  34. { the reverse order of the parameters make code generation easier }
  35. function fpc_do_as(aclass : tclass;aobject : tobject): tobject;[public,alias: 'FPC_DO_AS']; compilerproc;
  36. begin
  37. if assigned(aobject) and not(aobject.inheritsfrom(aclass)) then
  38. handleerroraddrframeInd(219,get_pc_addr,get_frame);
  39. result := aobject;
  40. end;
  41. { interface helpers }
  42. procedure fpc_intf_decr_ref(var i: pointer);[public,alias: 'FPC_INTF_DECR_REF']; compilerproc;
  43. begin
  44. if assigned(i) then
  45. begin
  46. IUnknown(i)._Release;
  47. i:=nil;
  48. end;
  49. end;
  50. { local declaration for intf_decr_ref for local access }
  51. procedure intf_decr_ref(var i: pointer); [external name 'FPC_INTF_DECR_REF'];
  52. procedure fpc_intf_incr_ref(i: pointer);[public,alias: 'FPC_INTF_INCR_REF']; compilerproc;
  53. begin
  54. if assigned(i) then
  55. IUnknown(i)._AddRef;
  56. end;
  57. { local declaration of intf_incr_ref for local access }
  58. procedure intf_incr_ref(i: pointer); [external name 'FPC_INTF_INCR_REF'];
  59. procedure fpc_intf_assign(var D: pointer; const S: pointer);[public,alias: 'FPC_INTF_ASSIGN']; compilerproc;
  60. begin
  61. if assigned(S) then
  62. IUnknown(S)._AddRef;
  63. if assigned(D) then
  64. IUnknown(D)._Release;
  65. D:=S;
  66. end;
  67. procedure fpc_intf_assign(var D: pointer; const s: pointer); [external name 'FPC_INTF_ASSIGN'];
  68. {procedure fpc_intf_assign_by_iid(var D: pointer; const S: pointer; const iid: TGUID);[public,alias: 'FPC_INTF_ASSIGN2']; compilerproc;
  69. var
  70. tmp : pointer;
  71. begin
  72. if assigned(S) then
  73. begin
  74. tmp:=nil;
  75. if IUnknown(S).QueryInterface(iid,tmp)<>S_OK then
  76. handleerror(219);
  77. if assigned(D) then
  78. IUnknown(D)._Release;
  79. D:=tmp;
  80. end
  81. else
  82. begin
  83. if assigned(D) then
  84. IUnknown(D)._Release;
  85. D:=nil;
  86. end;
  87. end;}
  88. function fpc_intf_is(const S: pointer; const iid: TGUID): Boolean;[public,alias: 'FPC_INTF_IS']; compilerproc;
  89. var
  90. tmpi: pointer;
  91. begin
  92. tmpi:=nil;
  93. fpc_intf_is:=Assigned(S) and (IUnknown(S).QueryInterface(iid,tmpi)=S_OK);
  94. if Assigned(tmpi) then
  95. IUnknown(tmpi)._Release;
  96. end;
  97. function fpc_intf_is_class(const S: pointer; const aclass: tclass): Boolean;[public,alias: 'FPC_INTF_IS_CLASS']; compilerproc;
  98. var
  99. tmpo: tobject;
  100. begin
  101. fpc_intf_is_class:=Assigned(S) and (IUnknown(S).QueryInterface(IObjectInstance,tmpo)=S_OK) and tmpo.InheritsFrom(aclass);
  102. end;
  103. function fpc_class_is_intf(const S: pointer; const iid: TGUID): Boolean;[public,alias: 'FPC_CLASS_IS_INTF']; compilerproc;
  104. var
  105. tmpi: pointer;
  106. tmpi2: pointer; // weak!
  107. begin
  108. tmpi:=nil;
  109. tmpi2:=nil;
  110. fpc_class_is_intf:=Assigned(S) and ((TObject(S).GetInterfaceWeak(IUnknown,tmpi2) and (IUnknown(tmpi2).QueryInterface(IID,tmpi)=S_OK)) or
  111. TObject(S).GetInterface(IID,tmpi));
  112. if Assigned(tmpi) then
  113. IUnknown(tmpi)._Release;
  114. end;
  115. function fpc_class_is_corbaintf(const S: pointer; const iid: Shortstring): Boolean;[public,alias: 'FPC_CLASS_IS_CORBAINTF']; compilerproc;
  116. begin
  117. fpc_class_is_corbaintf:=Assigned(S) and Assigned(TObject(S).GetInterfaceEntryByStr(iid));
  118. end;
  119. function fpc_intf_cast(const S: pointer; const iid: TGUID): IInterface;[public,alias: 'FPC_INTF_CAST']; compilerproc;
  120. var
  121. tmpi: pointer;
  122. begin
  123. tmpi:=nil;
  124. if Assigned(S) and (IUnknown(S).QueryInterface(iid,tmpi)=S_OK) then
  125. pointer(fpc_intf_cast):=tmpi
  126. else
  127. fpc_intf_cast:= nil;
  128. end;
  129. function fpc_intf_cast_class(const S: pointer; const aclass: tclass): pointer;[public,alias: 'FPC_INTF_CAST_CLASS']; compilerproc;
  130. var
  131. tmpo: tobject;
  132. begin
  133. if Assigned(S) and (IUnknown(S).QueryInterface(IObjectInstance,tmpo)=S_OK) and tmpo.InheritsFrom(aclass) then
  134. fpc_intf_cast_class:=tmpo
  135. else
  136. fpc_intf_cast_class:=nil;
  137. end;
  138. function fpc_class_cast_intf(const S: pointer; const iid: TGUID): IInterface;[public,alias: 'FPC_CLASS_CAST_INTF']; compilerproc;
  139. var
  140. tmpi: pointer;
  141. tmpi2: pointer; // weak!
  142. begin
  143. tmpi:=nil;
  144. tmpi2:=nil;
  145. if Assigned(S) and ((TObject(S).GetInterfaceWeak(IUnknown,tmpi2) and (IUnknown(tmpi2).QueryInterface(IID,tmpi)=S_OK)) or
  146. TObject(S).GetInterface(IID,tmpi)) then
  147. begin
  148. // decrease reference count
  149. fpc_class_cast_intf:=nil;
  150. pointer(fpc_class_cast_intf):=tmpi
  151. end
  152. else
  153. fpc_class_cast_intf:=nil;
  154. end;
  155. function fpc_class_cast_corbaintf(const S: pointer; const iid: Shortstring): Pointer;[public,alias: 'FPC_CLASS_CAST_CORBAINTF']; compilerproc;
  156. var
  157. tmpi: pointer;
  158. begin
  159. if Assigned(S) and TObject(S).GetInterface(iid,tmpi) then
  160. fpc_class_cast_corbaintf:=tmpi
  161. else
  162. fpc_class_cast_corbaintf:=nil;
  163. end;
  164. function fpc_intf_as(const S: pointer; const iid: TGUID): IInterface;[public,alias: 'FPC_INTF_AS']; compilerproc;
  165. var
  166. tmpi: pointer; // _AddRef before _Release
  167. begin
  168. if assigned(S) then
  169. begin
  170. tmpi:=nil;
  171. if IUnknown(S).QueryInterface(iid,tmpi)<>S_OK then
  172. handleerror(219);
  173. // decrease reference count
  174. fpc_intf_as:=nil;
  175. pointer(fpc_intf_as):=tmpi;
  176. end
  177. else
  178. fpc_intf_as:=nil;
  179. end;
  180. function fpc_intf_as_class(const S: pointer; const aclass: tclass): pointer;[public,alias: 'FPC_INTF_AS_CLASS']; compilerproc;
  181. var
  182. tmpo: tobject;
  183. begin
  184. if assigned(S) then
  185. begin
  186. if not ((IUnknown(S).QueryInterface(IObjectInstance,tmpo)=S_OK) and tmpo.inheritsfrom(aclass)) then
  187. handleerror(219);
  188. fpc_intf_as_class:=tmpo;
  189. end
  190. else
  191. fpc_intf_as_class:=nil;
  192. end;
  193. function fpc_class_as_intf(const S: pointer; const iid: TGUID): IInterface;[public,alias: 'FPC_CLASS_AS_INTF']; compilerproc;
  194. var
  195. tmpi: pointer; // _AddRef before _Release
  196. tmpi2: pointer; // weak!
  197. begin
  198. if assigned(S) then
  199. begin
  200. tmpi:=nil;
  201. tmpi2:=nil;
  202. if not ((TObject(S).GetInterfaceWeak(IUnknown,tmpi2) and (IUnknown(tmpi2).QueryInterface(IID,tmpi)=S_OK)) or TObject(S).GetInterface(IID,tmpi)) then
  203. handleerror(219);
  204. // decrease reference count
  205. fpc_class_as_intf:=nil;
  206. pointer(fpc_class_as_intf):=tmpi;
  207. end
  208. else
  209. fpc_class_as_intf:=nil;
  210. end;
  211. function fpc_class_as_corbaintf(const S: pointer; const iid: Shortstring): Pointer;[public,alias: 'FPC_CLASS_AS_CORBAINTF']; compilerproc;
  212. var
  213. tmpi: pointer; // _AddRef before _Release
  214. begin
  215. if assigned(S) then
  216. begin
  217. tmpi:=nil;
  218. if not TObject(S).GetInterface(iid,tmpi) then
  219. handleerror(219);
  220. fpc_class_as_corbaintf:=tmpi;
  221. end
  222. else
  223. fpc_class_as_corbaintf:=nil;
  224. end;
  225. {****************************************************************************
  226. TVMT
  227. ****************************************************************************}
  228. function TVmt.GetvParent: PVmt;
  229. begin
  230. {$ifdef VER3_0}
  231. GetvParent:=vParentRef;
  232. {$else VER3_0}
  233. if Assigned(vParentRef) then
  234. GetvParent:=vParentRef^
  235. else
  236. GetvParent:=Nil;
  237. {$endif VER3_0}
  238. end;
  239. {****************************************************************************
  240. TGUID
  241. ****************************************************************************}
  242. class operator TGUID.=(const aLeft, aRight: TGUID): Boolean;
  243. var
  244. P1,P2 : ^Cardinal;
  245. begin
  246. P1:=PCardinal(@aLeft);
  247. P2:=PCardinal(@aRight);
  248. Result:=(P1[0]=P2[0]) and (P1[1]=P2[1]) and (P1[2]=P2[2]) and (P1[3]=P2[3]);
  249. end;
  250. class operator TGUID.<>(const aLeft, aRight: TGUID): Boolean;
  251. begin
  252. Result:=Not (aLeft=aRight);
  253. end;
  254. class function TGUID.Empty: TGUID; static;
  255. begin
  256. Result:=Default(TGUID);
  257. end;
  258. class function TGUID.Create(const aData; aBigEndian: Boolean = False): TGUID; overload; static;
  259. begin
  260. Result:=Create(PByte(@aData),aBigEndian);
  261. end;
  262. class function TGUID.Create(const aData : PByte; aBigEndian: Boolean = False): TGUID; overload; static;
  263. const
  264. SysBigendian = {$IFDEF FPC_LITTLE_ENDIAN} false {$ELSE} true {$ENDIF};
  265. begin
  266. Result := PGuid(aData)^;
  267. if (aBigEndian=SysBigEndian) then
  268. exit;
  269. Result.D1:=SwapEndian(Result.D1);
  270. Result.D2:=SwapEndian(Result.D2);
  271. Result.D3:=SwapEndian(Result.D3);
  272. end;
  273. class function TGUID.Create(const aData: array of Byte; aStartIndex: Cardinal; aBigEndian: Boolean = False): TGUID; overload; static;
  274. begin
  275. if ((Length(aData)-aStartIndex)<16) then
  276. Result:=Empty
  277. else
  278. Result:=Create(PByte(@aData[aStartIndex]),aBigEndian);
  279. end;
  280. function TGUID.IsEmpty: Boolean;
  281. var
  282. P : ^Cardinal;
  283. begin
  284. P:=PCardinal(@Self);
  285. Result:=(P[0]=0) and (P[1]=0) and (P[2]=0) and (P[3]=0)
  286. end;
  287. {****************************************************************************
  288. TINTERFACEENTRY
  289. ****************************************************************************}
  290. function tinterfaceentry.GetIID: pguid;
  291. begin
  292. {$ifdef VER3_0}
  293. GetIID:=IIDRef;
  294. {$else VER3_0}
  295. if Assigned(IIDRef) then
  296. GetIID:=IIDRef^
  297. else
  298. GetIID:=Nil;
  299. {$endif VER3_0}
  300. end;
  301. function tinterfaceentry.GetIIDStr: pshortstring;
  302. begin
  303. {$ifdef VER3_0}
  304. GetIIDStr:=IIDStrRef;
  305. {$else VER3_0}
  306. if Assigned(IIDStrRef) then
  307. GetIIDStr:=IIDStrRef^
  308. else
  309. GetIIDStr:=Nil;
  310. {$endif VER3_0}
  311. end;
  312. {****************************************************************************
  313. TOBJECT
  314. ****************************************************************************}
  315. constructor TObject.Create;
  316. begin
  317. end;
  318. destructor TObject.Destroy;
  319. begin
  320. end;
  321. procedure TObject.Free;
  322. begin
  323. // the call via self avoids a warning
  324. if self<>nil then
  325. self.destroy;
  326. end;
  327. class function TObject.InstanceSize : SizeInt;
  328. begin
  329. InstanceSize := PVmt(Self)^.vInstanceSize;
  330. end;
  331. {$ifdef VER3_0}
  332. var
  333. emptyintf: ptruint; public name 'FPC_EMPTYINTF';
  334. {$endif VER3_0}
  335. procedure InitInterfacePointers(objclass: tclass;instance : pointer);
  336. var
  337. ovmt: PVmt;
  338. i: longint;
  339. intftable: pinterfacetable;
  340. Res: pinterfaceentry;
  341. begin
  342. ovmt := PVmt(objclass);
  343. while assigned(ovmt) and {$ifdef VER3_0}(ovmt^.vIntfTable <> @emptyintf){$else}assigned(ovmt^.vIntfTable){$endif} do
  344. begin
  345. intftable:=ovmt^.vIntfTable;
  346. {$ifdef VER3_0}
  347. if assigned(intftable) then
  348. {$endif VER3_0}
  349. begin
  350. i:=intftable^.EntryCount;
  351. Res:=@intftable^.Entries[0];
  352. while i>0 do begin
  353. if Res^.IType = etStandard then
  354. ppointer(@(pbyte(instance)[Res^.IOffset]))^:=
  355. pointer(Res^.VTable);
  356. inc(Res);
  357. dec(i);
  358. end;
  359. end;
  360. ovmt:=ovmt^.vParent;
  361. end;
  362. end;
  363. class function TObject.InitInstance(instance : pointer) : tobject;
  364. {$ifndef VER3_0}
  365. var
  366. vmt : PVmt;
  367. inittable : pointer;
  368. {$ifdef FPC_HAS_FEATURE_RTTI}
  369. mopinittable : PRTTIRecordOpOffsetTable;
  370. {$endif def FPC_HAS_FEATURE_RTTI}
  371. i : longint;
  372. {$endif VER3_0}
  373. begin
  374. { the size is saved at offset 0 }
  375. fillchar(instance^, InstanceSize, 0);
  376. { insert VMT pointer into the new created memory area }
  377. { (in class methods self contains the VMT!) }
  378. ppointer(instance)^:=pointer(self);
  379. if {$ifdef VER3_0}PVmt(self)^.vIntfTable <> @emptyintf{$else}assigned(PVmt(self)^.vIntfTable){$endif} then
  380. InitInterfacePointers(self,instance);
  381. {$ifndef VER3_0}
  382. {$ifdef FPC_HAS_FEATURE_RTTI}
  383. { for management operators like initialize call int_initialize }
  384. vmt := PVmt(self);
  385. if assigned(vmt) then
  386. begin
  387. inittable:=vmt^.vInitTable;
  388. if assigned(inittable) then
  389. begin
  390. mopinittable:=RTTIRecordMopInitTable(inittable);
  391. if assigned(mopinittable) then
  392. begin
  393. {$push}
  394. { ensure that no range check errors pop up with the [0..0] array }
  395. {$R-}
  396. for i:=0 to mopinittable^.Count-1 do
  397. TRTTIRecVarOp(mopinittable^.Entries[i].ManagmentOperator)(PByte(Instance)+mopinittable^.Entries[i].FieldOffset);
  398. {$pop}
  399. end;
  400. end;
  401. end;
  402. {$endif def FPC_HAS_FEATURE_RTTI}
  403. {$endif VER3_0}
  404. InitInstance:=TObject(Instance);
  405. end;
  406. class function TObject.ClassParent : tclass;
  407. begin
  408. { type of self is class of tobject => it points to the vmt }
  409. { the parent vmt is saved at offset vmtParent }
  410. classparent:=tclass(PVmt(Self)^.vParent);
  411. end;
  412. class function TObject.NewInstance : tobject;
  413. var
  414. p : pointer;
  415. begin
  416. getmem(p, InstanceSize);
  417. if p <> nil then
  418. InitInstance(p);
  419. NewInstance:=TObject(p);
  420. end;
  421. procedure TObject.FreeInstance;
  422. begin
  423. CleanupInstance;
  424. FreeMem(Pointer(Self));
  425. end;
  426. class function TObject.ClassType : TClass;
  427. begin
  428. ClassType:=TClass(Pointer(Self))
  429. end;
  430. type
  431. tmethodnamerec = packed record
  432. name : pshortstring;
  433. addr : codepointer;
  434. end;
  435. tmethodnametable = packed record
  436. count : dword;
  437. entries : packed array[0..0] of tmethodnamerec;
  438. end;
  439. pmethodnametable = ^tmethodnametable;
  440. class function TObject.MethodAddress(const name : shortstring) : codepointer;
  441. var
  442. methodtable : pmethodnametable;
  443. i : dword;
  444. ovmt : PVmt;
  445. begin
  446. ovmt:=PVmt(self);
  447. while assigned(ovmt) do
  448. begin
  449. methodtable:=pmethodnametable(ovmt^.vMethodTable);
  450. if assigned(methodtable) then
  451. begin
  452. for i:=0 to methodtable^.count-1 do
  453. if ShortCompareText(methodtable^.entries[i].name^, name)=0 then
  454. begin
  455. MethodAddress:=methodtable^.entries[i].addr;
  456. exit;
  457. end;
  458. end;
  459. ovmt := ovmt^.vParent;
  460. end;
  461. MethodAddress:=nil;
  462. end;
  463. class function TObject.MethodName(address : codepointer) : shortstring;
  464. var
  465. methodtable : pmethodnametable;
  466. i : dword;
  467. ovmt : PVmt;
  468. begin
  469. ovmt:=PVmt(self);
  470. while assigned(ovmt) do
  471. begin
  472. methodtable:=pmethodnametable(ovmt^.vMethodTable);
  473. if assigned(methodtable) then
  474. begin
  475. for i:=0 to methodtable^.count-1 do
  476. if methodtable^.entries[i].addr=address then
  477. begin
  478. MethodName:=methodtable^.entries[i].name^;
  479. exit;
  480. end;
  481. end;
  482. ovmt := ovmt^.vParent;
  483. end;
  484. MethodName:='';
  485. end;
  486. function TObject.FieldAddress(const name : shortstring) : pointer;
  487. {The following is copied to the typinfo unit. If it is changed here, change it there as well ! }
  488. type
  489. PFieldInfo = ^TFieldInfo;
  490. TFieldInfo =
  491. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  492. packed
  493. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  494. record
  495. FieldOffset: SizeUInt;
  496. ClassTypeIndex: Word;
  497. Name: ShortString;
  498. end;
  499. PFieldTable = ^TFieldTable;
  500. TFieldTable =
  501. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  502. packed
  503. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  504. record
  505. FieldCount: Word;
  506. ClassTable: Pointer;
  507. { should be array[Word] of TFieldInfo; but
  508. Elements have variant size! force at least proper alignment }
  509. Fields: array[0..0] of TFieldInfo
  510. end;
  511. var
  512. ovmt: PVmt;
  513. FieldTable: PFieldTable;
  514. FieldInfo: PFieldInfo;
  515. i: longint;
  516. begin
  517. if Length(name) > 0 then
  518. begin
  519. ovmt := PVmt(ClassType);
  520. while ovmt <> nil do
  521. begin
  522. FieldTable := PFieldTable(ovmt^.vFieldTable);
  523. if FieldTable <> nil then
  524. begin
  525. FieldInfo := @FieldTable^.Fields[0];
  526. for i := 0 to FieldTable^.FieldCount - 1 do
  527. begin
  528. if ShortCompareText(FieldInfo^.Name, name) = 0 then
  529. begin
  530. fieldaddress := Pointer(Self) + FieldInfo^.FieldOffset;
  531. exit;
  532. end;
  533. FieldInfo := PFieldInfo(PByte(@FieldInfo^.Name) + 1 + Length(FieldInfo^.Name));
  534. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  535. { align to largest field of TFieldInfo }
  536. FieldInfo := Align(FieldInfo, SizeOf(PtrUInt));
  537. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  538. end;
  539. end;
  540. { Try again with the parent class type }
  541. ovmt:=ovmt^.vParent;
  542. end;
  543. end;
  544. fieldaddress:=nil;
  545. end;
  546. function TObject.SafeCallException(exceptobject : tobject;
  547. exceptaddr : codepointer) : HResult;
  548. begin
  549. safecallexception:=E_UNEXPECTED;
  550. end;
  551. class function TObject.ClassInfo : pointer;
  552. begin
  553. ClassInfo := PVmt(Self)^.vTypeInfo;
  554. end;
  555. class function TObject.ClassName : ShortString;
  556. begin
  557. ClassName := PVmt(Self)^.vClassName^;
  558. end;
  559. class function TObject.ClassNameIs(const name : RTLString) : boolean;
  560. var
  561. SS : ShortString;
  562. begin
  563. SS:=ShortString(Name);
  564. ClassNameIs:=ShortCompareText(PVmt(Self)^.vClassName^, SS) = 0;
  565. end;
  566. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  567. var
  568. vmt: PVmt;
  569. begin
  570. if assigned(aclass) then
  571. begin
  572. vmt:=PVmt(self);
  573. while assigned(vmt) and (vmt <> PVmt(aclass)) do
  574. vmt := vmt^.vParent;
  575. InheritsFrom := (vmt = PVmt(aclass));
  576. end
  577. else
  578. inheritsFrom := False;
  579. end;
  580. class function TObject.stringmessagetable : pstringmessagetable;
  581. begin
  582. stringmessagetable:=PVmt(Self)^.vMsgStrPtr;
  583. end;
  584. type
  585. tmessagehandler = procedure(var msg) of object;
  586. procedure TObject.Dispatch(var message);
  587. type
  588. {$PUSH}
  589. {$PACKRECORDS NORMAL}
  590. PMsgIntTable = ^TMsgIntTable;
  591. TMsgIntTable = record
  592. index : dword;
  593. method : codepointer;
  594. end;
  595. PMsgInt = ^TMsgInt;
  596. TMsgInt = record
  597. count : longint;
  598. msgs : array[0..0] of TMsgIntTable;
  599. end;
  600. {$POP}
  601. var
  602. index : dword;
  603. count,i : longint;
  604. msgtable : PMsgIntTable;
  605. p : PMsgInt;
  606. ovmt : PVmt;
  607. msghandler : tmessagehandler;
  608. begin
  609. index:=dword(message);
  610. ovmt := PVmt(ClassType);
  611. while assigned(ovmt) do
  612. begin
  613. // See if we have messages at all in this class.
  614. p:=PMsgInt(ovmt^.vDynamicTable);
  615. If Assigned(p) then
  616. begin
  617. msgtable:=@p^.msgs;
  618. count:=p^.count;
  619. end
  620. else
  621. Count:=0;
  622. { later, we can implement a binary search here }
  623. for i:=0 to count-1 do
  624. begin
  625. if index=msgtable[i].index then
  626. begin
  627. TMethod(msghandler).Code:=msgtable[i].method;
  628. TMethod(msghandler).Data:=self;
  629. msghandler(message);
  630. exit;
  631. end;
  632. end;
  633. ovmt:=ovmt^.vParent;
  634. end;
  635. DefaultHandler(message);
  636. end;
  637. procedure TObject.DispatchStr(var message);
  638. var
  639. name : shortstring;
  640. count,i : longint;
  641. msgstrtable : pmsgstrtable;
  642. p: pstringmessagetable;
  643. ovmt : PVmt;
  644. msghandler : tmessagehandler;
  645. begin
  646. name:=pshortstring(@message)^;
  647. ovmt:=PVmt(ClassType);
  648. while assigned(ovmt) do
  649. begin
  650. p := ovmt^.vMsgStrPtr;
  651. if (P<>Nil) and (p^.count<>0) then
  652. begin
  653. count:=p^.count;
  654. msgstrtable:=@p^.msgstrtable;
  655. end
  656. else
  657. Count:=0;
  658. { later, we can implement a binary search here }
  659. for i:=0 to count-1 do
  660. begin
  661. if name=msgstrtable[i].name^ then
  662. begin
  663. TMethod(msghandler).Code:=msgstrtable[i].method;
  664. TMethod(msghandler).Data:=self;
  665. msghandler(message);
  666. exit;
  667. end;
  668. end;
  669. ovmt:=ovmt^.vParent;
  670. end;
  671. DefaultHandlerStr(message);
  672. end;
  673. procedure TObject.DefaultHandler(var message);
  674. begin
  675. end;
  676. procedure TObject.DefaultHandlerStr(var message);
  677. begin
  678. end;
  679. procedure TObject.CleanupInstance;
  680. var
  681. vmt : PVmt;
  682. temp : pointer;
  683. begin
  684. vmt := PVmt(ClassType);
  685. while vmt<>nil do
  686. begin
  687. Temp:= vmt^.vInitTable;
  688. {$ifdef FPC_HAS_FEATURE_RTTI}
  689. { The RTTI format matches one for records, except the type is tkClass.
  690. Since RecordRTTI does not check the type, calling it yields the desired result. }
  691. if Assigned(Temp) then
  692. RecordRTTI(Self,Temp,@int_finalize);
  693. {$endif def FPC_HAS_FEATURE_RTTI}
  694. vmt:= vmt^.vParent;
  695. end;
  696. end;
  697. procedure TObject.AfterConstruction;
  698. begin
  699. end;
  700. procedure TObject.BeforeDestruction;
  701. begin
  702. end;
  703. function IsGUIDEqual(const guid1, guid2: tguid): boolean;
  704. begin
  705. IsGUIDEqual:=
  706. (guid1.D1=guid2.D1) and
  707. (PDWORD(@guid1.D2)^=PDWORD(@guid2.D2)^) and
  708. (PDWORD(@guid1.D4[0])^=PDWORD(@guid2.D4[0])^) and
  709. (PDWORD(@guid1.D4[4])^=PDWORD(@guid2.D4[4])^);
  710. end;
  711. // Use of managed types should be avoided here; implicit _Addref/_Release
  712. // will end up in unpredictable behaviour if called on CORBA interfaces.
  713. type
  714. TInterfaceGetter = procedure(out Obj) of object;
  715. TClassGetter = function: TObject of object;
  716. function GetInterfaceByEntry(Instance: pointer; IEntry: pinterfaceentry; out obj): boolean;
  717. var
  718. Getter: TMethod;
  719. begin
  720. Pointer(Obj) := nil;
  721. Getter.Data := Instance;
  722. if Assigned(IEntry) and Assigned(Instance) then
  723. begin
  724. case IEntry^.IType of
  725. etStandard:
  726. Pointer(Obj) := PByte(instance)+IEntry^.IOffset;
  727. etFieldValue, etFieldValueClass:
  728. Pointer(obj) := PPointer(PByte(Instance)+IEntry^.IOffset)^;
  729. etVirtualMethodResult:
  730. begin
  731. // IOffset is relative to the VMT, not to instance.
  732. Getter.code := PCodePointer(PByte(PPointer(Instance)^) + IEntry^.IOffset)^;
  733. TInterfaceGetter(Getter)(obj);
  734. end;
  735. etVirtualMethodClass:
  736. begin
  737. // IOffset is relative to the VMT, not to instance.
  738. Getter.code := PCodePointer(PByte(PPointer(Instance)^) + IEntry^.IOffset)^;
  739. TObject(obj) := TClassGetter(Getter)();
  740. end;
  741. etStaticMethodResult:
  742. begin
  743. Getter.code := IEntry^.IOffsetAsCodePtr;
  744. TInterfaceGetter(Getter)(obj);
  745. end;
  746. etStaticMethodClass:
  747. begin
  748. Getter.code := IEntry^.IOffsetAsCodePtr;
  749. TObject(obj) := TClassGetter(Getter)();
  750. end;
  751. end;
  752. end;
  753. result := assigned(pointer(obj));
  754. end;
  755. function TObject.GetInterface(const iid : tguid;out obj) : boolean;
  756. var
  757. IEntry: PInterfaceEntry;
  758. Instance: TObject;
  759. begin
  760. if IsGUIDEqual(IObjectInstance,iid) then
  761. begin
  762. TObject(Obj) := Self;
  763. Result := True;
  764. Exit;
  765. end;
  766. Instance := self;
  767. repeat
  768. IEntry := Instance.GetInterfaceEntry(iid);
  769. result := GetInterfaceByEntry(Instance, IEntry, obj);
  770. if (not result) or
  771. (IEntry^.IType in [etStandard, etFieldValue,
  772. etStaticMethodResult, etVirtualMethodResult]) then
  773. Break;
  774. { if interface is implemented by a class-type property or field,
  775. continue search }
  776. Instance := TObject(obj);
  777. until False;
  778. { Getter function will normally AddRef, so adding another reference here
  779. will cause memleak. }
  780. if result and (IEntry^.IType in [etStandard, etFieldValue]) then
  781. IInterface(obj)._AddRef;
  782. end;
  783. function TObject.GetInterfaceWeak(const iid : tguid; out obj) : boolean;
  784. var
  785. IEntry: PInterfaceEntry;
  786. Instance: TObject;
  787. begin
  788. if IsGUIDEqual(IObjectInstance,iid) then
  789. begin
  790. TObject(Obj) := Self;
  791. Result := True;
  792. Exit;
  793. end;
  794. Instance := self;
  795. repeat
  796. IEntry := Instance.GetInterfaceEntry(iid);
  797. result := GetInterfaceByEntry(Instance, IEntry, obj);
  798. if (not result) or
  799. (IEntry^.IType in [etStandard, etFieldValue,
  800. etStaticMethodResult, etVirtualMethodResult]) then
  801. Break;
  802. { if interface is implemented by a class-type property or field,
  803. continue search }
  804. Instance := TObject(obj);
  805. until False;
  806. { Getter function will normally AddRef, so we have to release it,
  807. else the ref is not weak. }
  808. if result and not (IEntry^.IType in [etStandard, etFieldValue]) then
  809. IInterface(obj)._Release;
  810. end;
  811. function TObject.GetInterfaceByStr(const iidstr : shortstring;out obj) : boolean;
  812. var
  813. IEntry: PInterfaceEntry;
  814. Instance: TObject;
  815. begin
  816. Instance := self;
  817. repeat
  818. IEntry := Instance.GetInterfaceEntryByStr(iidstr);
  819. result := GetInterfaceByEntry(Instance, IEntry, obj);
  820. if (not result) or
  821. (IEntry^.IType in [etStandard, etFieldValue,
  822. etStaticMethodResult, etVirtualMethodResult]) then
  823. Break;
  824. { if interface is implemented by a class-type property or field,
  825. continue search }
  826. Instance := TObject(obj);
  827. until False;
  828. { Getter function will normally AddRef, so adding another reference here
  829. will cause memleak. (com interfaces only!) }
  830. if result and Assigned(IEntry^.IID) and (IEntry^.IType in [etStandard, etFieldValue]) then
  831. IInterface(obj)._AddRef;
  832. end;
  833. function TObject.GetInterface(const iidstr : shortstring;out obj) : boolean;
  834. begin
  835. Result := GetInterfaceByStr(iidstr,obj);
  836. end;
  837. class function TObject.GetInterfaceEntry(const iid : tguid) : pinterfaceentry;
  838. var
  839. i: longint;
  840. intftable: pinterfacetable;
  841. ovmt: PVmt;
  842. begin
  843. ovmt := PVmt(Self);
  844. while Assigned(ovmt) and {$ifdef VER3_0}(ovmt^.vIntfTable <> @emptyintf){$else}Assigned(ovmt^.vIntftable){$endif} do
  845. begin
  846. intftable:=ovmt^.vIntfTable;
  847. {$ifdef VER3_0}
  848. if assigned(intftable) then
  849. {$endif VER3_0}
  850. begin
  851. for i:=0 to intftable^.EntryCount-1 do
  852. begin
  853. result:=@intftable^.Entries[i];
  854. if assigned(Result^.iid) and IsGUIDEqual(Result^.iid^,iid) then
  855. Exit;
  856. end;
  857. end;
  858. ovmt := ovmt^.vParent;
  859. end;
  860. result := nil;
  861. end;
  862. class function TObject.GetInterfaceEntryByStr(const iidstr : shortstring) : pinterfaceentry;
  863. var
  864. i: longint;
  865. intftable: pinterfacetable;
  866. ovmt: PVmt;
  867. begin
  868. ovmt := PVmt(Self);
  869. while Assigned(ovmt) and {$ifdef VER3_0}(ovmt^.vIntfTable <> @emptyintf){$else}Assigned(ovmt^.vIntfTable){$endif} do
  870. begin
  871. intftable:=ovmt^.vIntfTable;
  872. {$ifdef VER3_0}
  873. if assigned(intftable) then
  874. {$endif VER3_0}
  875. begin
  876. for i:=0 to intftable^.EntryCount-1 do
  877. begin
  878. result:=@intftable^.Entries[i];
  879. if assigned(result^.iidstr) and (result^.iidstr^ = iidstr) then
  880. Exit;
  881. end;
  882. end;
  883. ovmt := ovmt^.vParent;
  884. end;
  885. result:=nil;
  886. end;
  887. class function TObject.GetInterfaceTable : pinterfacetable;
  888. begin
  889. getinterfacetable:=PVmt(Self)^.vIntfTable;
  890. end;
  891. class function TObject.UnitName : RTLString;
  892. {$ifdef FPC_HAS_FEATURE_RTTI}
  893. type
  894. TClassTypeInfo = {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  895. Attributes: Pointer;
  896. case TTypeKind of
  897. tkClass: (
  898. ClassType: TClass;
  899. ParentInfo: Pointer;
  900. PropCount: SmallInt;
  901. UnitName: ShortString;
  902. );
  903. { include for proper alignment }
  904. tkInt64: (
  905. Dummy: Int64;
  906. );
  907. end;
  908. PClassTypeInfo = ^TClassTypeInfo;
  909. var
  910. classtypeinfo: PClassTypeInfo;
  911. begin
  912. classtypeinfo:=ClassInfo;
  913. if Assigned(classtypeinfo) then
  914. begin
  915. // offset PTypeInfo by Length(Name) + 2 (ShortString length byte + SizeOf(Kind))
  916. inc(Pointer(classtypeinfo), PByte(Pointer(classtypeinfo)+1)^ + 2);
  917. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  918. classtypeinfo:=aligntoqword(classtypeinfo);
  919. {$endif}
  920. result:=classtypeinfo^.UnitName;
  921. end
  922. else
  923. result:='';
  924. end;
  925. {$else not FPC_HAS_FEATURE_RTTI}
  926. begin
  927. result:='';
  928. end;
  929. {$endif ndef FPC_HAS_FEATURE_RTTI}
  930. class function TObject.QualifiedClassName: RTLString;
  931. var
  932. uname: RTLString;
  933. begin
  934. uname := UnitName; //TODO: change 'UnitName' to 'UnitScope' as soon as RTL implement it
  935. if uname='' then
  936. result:=ClassName
  937. else
  938. result:=Concat(uname, '.', ClassName);
  939. end;
  940. function TObject.Equals(Obj: TObject) : boolean;
  941. begin
  942. result:=Obj=Self;
  943. end;
  944. function TObject.GetHashCode: PtrInt;
  945. begin
  946. result:=PtrInt(Self);
  947. end;
  948. function TObject.ToString: RTLString;
  949. begin
  950. result:=ClassName;
  951. end;
  952. procedure TObject.DisposeOf;
  953. begin
  954. Free;
  955. end;
  956. function TObject.GetDisposed : Boolean;
  957. begin
  958. Result:=False;
  959. end;
  960. procedure TObject.CheckDisposed;
  961. begin
  962. // Do nothing since we have no reference count.
  963. end;
  964. {****************************************************************************
  965. TINTERFACEDOBJECT
  966. ****************************************************************************}
  967. function TInterfacedObject.QueryInterface(
  968. {$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  969. begin
  970. if getinterface(iid,obj) then
  971. result:=S_OK
  972. else
  973. result:=longint(E_NOINTERFACE);
  974. end;
  975. function TInterfacedObject._AddRef : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  976. begin
  977. _addref:=interlockedincrement(frefcount);
  978. end;
  979. function TInterfacedObject._Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  980. begin
  981. _Release:=interlockeddecrement(frefcount);
  982. if _Release=0 then
  983. begin
  984. if interlockedincrement(fdestroycount)=1 then
  985. self.destroy;
  986. end;
  987. end;
  988. destructor TInterfacedObject.Destroy;
  989. begin
  990. // We must explicitly reset. Bug ID 32353
  991. FRefCount:=0;
  992. FDestroyCount:=0;
  993. inherited Destroy;
  994. end;
  995. procedure TInterfacedObject.AfterConstruction;
  996. begin
  997. { we need to fix the refcount we forced in newinstance }
  998. { further, it must be done in a thread safe way }
  999. declocked(frefcount);
  1000. end;
  1001. procedure TInterfacedObject.BeforeDestruction;
  1002. begin
  1003. if frefcount<>0 then
  1004. HandleError(204);
  1005. end;
  1006. class function TInterfacedObject.NewInstance : TObject;
  1007. begin
  1008. NewInstance:=inherited NewInstance;
  1009. if NewInstance<>nil then
  1010. TInterfacedObject(NewInstance).frefcount:=1;
  1011. end;
  1012. {****************************************************************************
  1013. TAGGREGATEDOBJECT
  1014. ****************************************************************************}
  1015. constructor TAggregatedObject.Create(const aController: IUnknown);
  1016. begin
  1017. inherited Create;
  1018. { do not keep a counted reference to the controller! }
  1019. fcontroller := Pointer(aController);
  1020. end;
  1021. function TAggregatedObject.QueryInterface(
  1022. {$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1023. begin
  1024. Result := IUnknown(fcontroller).QueryInterface(iid, obj);
  1025. end;
  1026. function TAggregatedObject._AddRef : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1027. begin
  1028. Result := IUnknown(fcontroller)._AddRef;
  1029. end;
  1030. function TAggregatedObject._Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1031. begin
  1032. Result := IUnknown(fcontroller)._Release;
  1033. end;
  1034. function TAggregatedObject.GetController : IUnknown;
  1035. begin
  1036. Result := IUnknown(fcontroller);
  1037. end;
  1038. {****************************************************************************
  1039. TContainedOBJECT
  1040. ****************************************************************************}
  1041. function TContainedObject.QueryInterface(
  1042. {$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1043. begin
  1044. if getinterface(iid,obj) then
  1045. result:=S_OK
  1046. else
  1047. result:=longint(E_NOINTERFACE);
  1048. end;
  1049. {****************************************************************************
  1050. TNoRefCountObject
  1051. ****************************************************************************}
  1052. function TNoRefCountObject.QueryInterface( {$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1053. begin
  1054. if getinterface(iid,obj) then
  1055. result:=S_OK
  1056. else
  1057. result:=longint(E_NOINTERFACE);
  1058. end;
  1059. function TNoRefCountObject._AddRef : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1060. begin
  1061. Result:=-1;
  1062. end;
  1063. function TNoRefCountObject._Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1064. begin
  1065. Result:=-1;
  1066. end;
  1067. {****************************************************************************
  1068. TCustomAttribute
  1069. ****************************************************************************}
  1070. constructor TCustomAttribute.Create;
  1071. begin
  1072. inherited;
  1073. end;
  1074. {****************************************************************************
  1075. TCustomStoredAttribute
  1076. ****************************************************************************}
  1077. constructor StoredAttribute.Create;
  1078. begin
  1079. end;
  1080. constructor StoredAttribute.Create(Const aFlag : Boolean);
  1081. begin
  1082. FFlag:=aFlag;
  1083. end;
  1084. constructor StoredAttribute.Create(Const aName : shortstring);
  1085. begin
  1086. FName:=aName;
  1087. end;
  1088. {****************************************************************************
  1089. TInterfaceThunk
  1090. ****************************************************************************}
  1091. Constructor TInterfaceThunk.Create(aCallback : TThunkCallback);
  1092. begin
  1093. FCallBack:=aCallBack;
  1094. end;
  1095. Procedure TInterfaceThunk.Thunk(aMethod: Longint; aCount : Longint; aData : PArgData);
  1096. begin
  1097. if Assigned(FCallBack) then
  1098. FCallBack(Self,aMethod,aCount,aData);
  1099. end;
  1100. function TInterfaceThunk.QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1101. begin
  1102. result:=longint(E_NOINTERFACE);
  1103. if (TMethod(FCallBack).Data<>Nil) then
  1104. // Query the object that created us, this is normally TVirtualInterface
  1105. // Take care: do not call QueryInterface, that would create a never-ending loop !!
  1106. if TObject(TMethod(FCallBack).Data).GetInterface(iid,obj) then
  1107. result:=S_OK;
  1108. if (Result<>S_OK) then
  1109. Result:=Inherited QueryInterface(iid,obj);
  1110. end;
  1111. function TInterfaceThunk.InterfaceVMTOffset : word;
  1112. begin
  1113. Result:=0;
  1114. end;
  1115. {****************************************************************************
  1116. Exception Support
  1117. ****************************************************************************}
  1118. {$ifdef FPC_HAS_FEATURE_EXCEPTIONS}
  1119. {$if defined(FPC_WASM_NATIVE_EXCEPTIONS)}
  1120. {$I except_native.inc}
  1121. {$elseif defined(FPC_WASM_BRANCHFUL_EXCEPTIONS)}
  1122. {$I except_branchful.inc}
  1123. {$else}
  1124. {$i except.inc}
  1125. {$endif}
  1126. {$endif FPC_HAS_FEATURE_EXCEPTIONS}
  1127. {****************************************************************************
  1128. Various Delphi constructs
  1129. ****************************************************************************}
  1130. function TPtrWrapper.ToPointer: Pointer;
  1131. begin
  1132. Result:=FValue;
  1133. end;
  1134. class function TPtrWrapper.GetNilValue: TPtrWrapper;
  1135. begin
  1136. Result.FValue:=Nil;
  1137. end;
  1138. constructor TPtrWrapper.Create(AValue: PtrInt);
  1139. begin
  1140. FValue:=Pointer(aValue);
  1141. end;
  1142. constructor TPtrWrapper.Create(AValue: Pointer);
  1143. begin
  1144. FValue:=aValue;
  1145. end;
  1146. function TPtrWrapper.ToInteger: PtrInt;
  1147. begin
  1148. Result:=PtrInt(FValue);
  1149. end;
  1150. class operator TPtrWrapper.=(Left, Right: TPtrWrapper): Boolean;
  1151. begin
  1152. Result:=Left.FValue=Right.FValue;
  1153. end;
  1154. constructor TMarshal.Create;
  1155. begin
  1156. System.Error(reInvalidPtr);
  1157. end;
  1158. class function TMarshal.AllocMem(Size: SizeInt): TPtrWrapper;
  1159. begin
  1160. Result.Value := System.AllocMem(Size);
  1161. end;
  1162. class function TMarshal.ReallocMem(OldPtr: TPtrWrapper; NewSize: SizeInt): TPtrWrapper;
  1163. var
  1164. P: Pointer;
  1165. begin
  1166. P := OldPtr.Value;
  1167. Result.Value := System.ReallocMem(P, NewSize);
  1168. end;
  1169. class procedure TMarshal.FreeMem(Ptr: TPtrWrapper);
  1170. begin
  1171. System.FreeMem(Ptr.Value);
  1172. end;
  1173. class procedure TMarshal.Move(Src, Dest: TPtrWrapper; Count: SizeInt); static;
  1174. begin
  1175. System.Move(Src.Value^, Dest.Value^, Count);
  1176. end;
  1177. class function TMarshal.UnsafeAddrOf(var Value): TPtrWrapper;
  1178. begin
  1179. Result.Value := @Value;
  1180. end;
  1181. class procedure TMarshal.Copy(const Src: TUint8Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1182. begin
  1183. System.Move(PUInt8(Src)[StartIndex], Dest.Value^, Count * SizeOf(UInt8));
  1184. end;
  1185. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TUint8Array; StartIndex: SizeInt; Count: SizeInt);
  1186. begin
  1187. System.Move(Src.Value^, PUInt8(Dest)[StartIndex], Count * SizeOf(UInt8));
  1188. end;
  1189. class procedure TMarshal.Copy(const Src: TInt8Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1190. begin
  1191. System.Move(PInt8(Src)[StartIndex], Dest.Value^, Count * SizeOf(Int8));
  1192. end;
  1193. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TInt8Array ; StartIndex: SizeInt; Count: SizeInt);
  1194. begin
  1195. System.Move(Src.Value^, PInt8(Dest)[StartIndex], Count * SizeOf(Int8));
  1196. end;
  1197. class procedure TMarshal.Copy(const Src: TUInt16Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1198. begin
  1199. System.Move(PUInt16(Src)[StartIndex], Dest.Value^, Count * SizeOf(UInt16));
  1200. end;
  1201. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TUint16Array; StartIndex: SizeInt; Count: SizeInt);
  1202. begin
  1203. System.Move(Src.Value^, PUInt16(Dest)[StartIndex], Count * SizeOf(UInt16));
  1204. end;
  1205. class procedure TMarshal.Copy(const Src: TInt16Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1206. begin
  1207. System.Move(PInt16(Src)[StartIndex], Dest.Value^, Count * SizeOf(Int16));
  1208. end;
  1209. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TInt16Array; StartIndex: SizeInt; Count: SizeInt);
  1210. begin
  1211. System.Move(Src.Value^, PInt16(Dest)[StartIndex], Count * SizeOf(Int16));
  1212. end;
  1213. class procedure TMarshal.Copy(const Src: TInt32Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1214. begin
  1215. System.Move(PInt32(Src)[StartIndex], Dest.Value^, Count * SizeOf(Int32));
  1216. end;
  1217. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TInt32Array; StartIndex: SizeInt; Count: SizeInt);
  1218. begin
  1219. System.Move(Src.Value^, PInt32(Dest)[StartIndex], Count * SizeOf(Int32));
  1220. end;
  1221. class procedure TMarshal.Copy(const Src: TInt64Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1222. begin
  1223. System.Move(PInt64(Src)[StartIndex], Dest.Value^, Count * SizeOf(Int64));
  1224. end;
  1225. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TInt64Array; StartIndex: SizeInt; Count: SizeInt);
  1226. begin
  1227. System.Move(Src.Value^, PInt64(Dest)[StartIndex], Count * SizeOf(Int64));
  1228. end;
  1229. class procedure TMarshal.Copy(const Src: TPtrWrapperArray; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1230. begin
  1231. System.Move(PPointer(Src)[StartIndex], Dest.Value^, Count * SizeOf(TPtrWrapper));
  1232. end;
  1233. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TPtrWrapperArray; StartIndex: SizeInt; Count: SizeInt);
  1234. begin
  1235. System.Move(Src.Value^, PPointer(Dest)[StartIndex], Count * SizeOf(TPtrWrapper));
  1236. end;
  1237. generic class function TMarshal.FixArray<T>(const Arr: specialize TArray<T>): TPtrWrapper;
  1238. begin
  1239. Result.Value := nil;
  1240. specialize TArray<T>(Result) := Arr;
  1241. end;
  1242. generic class procedure TMarshal.UnfixArray<T>(ArrPtr: TPtrWrapper);
  1243. begin
  1244. Finalize(specialize TArray<T>(ArrPtr));
  1245. end;
  1246. class function TMarshal.ReadByte(Ptr: TPtrWrapper; Ofs: SizeInt = 0): Byte;
  1247. begin
  1248. Result := PByte(Ptr.Value + Ofs)^;
  1249. end;
  1250. class procedure TMarshal.WriteByte(Ptr: TPtrWrapper; Ofs: SizeInt; Value: Byte);
  1251. begin
  1252. PByte(Ptr.Value + Ofs)^ := Value;
  1253. end;
  1254. class procedure TMarshal.WriteByte(Ptr: TPtrWrapper; Value: Byte);
  1255. begin
  1256. PByte(Ptr.Value)^ := Value;
  1257. end;
  1258. class function TMarshal.ReadInt16(Ptr: TPtrWrapper; Ofs: SizeInt = 0): Int16;
  1259. begin
  1260. Result := PInt16(Ptr.Value + Ofs)^;
  1261. end;
  1262. class procedure TMarshal.WriteInt16(Ptr: TPtrWrapper; Ofs: SizeInt; Value: Int16);
  1263. begin
  1264. PInt16(Ptr.Value + Ofs)^ := Value;
  1265. end;
  1266. class procedure TMarshal.WriteInt16(Ptr: TPtrWrapper; Value: Int16);
  1267. begin
  1268. PInt16(Ptr.Value)^ := Value;
  1269. end;
  1270. class function TMarshal.ReadInt32(Ptr: TPtrWrapper; Ofs: SizeInt = 0): Int32;
  1271. begin
  1272. Result := PInt32(Ptr.Value + Ofs)^;
  1273. end;
  1274. class procedure TMarshal.WriteInt32(Ptr: TPtrWrapper; Ofs: SizeInt; Value: Int32);
  1275. begin
  1276. PInt32(Ptr.Value + Ofs)^ := Value;
  1277. end;
  1278. class procedure TMarshal.WriteInt32(Ptr: TPtrWrapper; Value: Int32);
  1279. begin
  1280. PInt32(Ptr.Value)^ := Value;
  1281. end;
  1282. class function TMarshal.ReadInt64(Ptr: TPtrWrapper; Ofs: SizeInt = 0): Int64;
  1283. begin
  1284. Result := PInt64(Ptr.Value + Ofs)^;
  1285. end;
  1286. class procedure TMarshal.WriteInt64(Ptr: TPtrWrapper; Ofs: SizeInt; Value: Int64);
  1287. begin
  1288. PInt64(Ptr.Value + Ofs)^ := Value;
  1289. end;
  1290. class procedure TMarshal.WriteInt64(Ptr: TPtrWrapper; Value: Int64);
  1291. begin
  1292. PInt64(Ptr.Value)^ := Value;
  1293. end;
  1294. class function TMarshal.ReadPtr(Ptr: TPtrWrapper; Ofs: SizeInt = 0): TPtrWrapper;
  1295. begin
  1296. Result.Value := PPointer(Ptr.Value + Ofs)^;
  1297. end;
  1298. class procedure TMarshal.WritePtr(Ptr: TPtrWrapper; Ofs: SizeInt; Value: TPtrWrapper);
  1299. begin
  1300. PPointer(Ptr.Value + Ofs)^ := Value.Value;
  1301. end;
  1302. class procedure TMarshal.WritePtr(Ptr, Value: TPtrWrapper);
  1303. begin
  1304. PPointer(Ptr.Value)^ := Value.Value;
  1305. end;
  1306. {$IFDEF FPC_HAS_FEATURE_UNICODESTRINGS}
  1307. class function TMarshal.AsAnsi(const S: UnicodeString): AnsiString;
  1308. begin
  1309. Result := AnsiString(S);
  1310. end;
  1311. class function TMarshal.AsAnsi(S: PUnicodeChar): AnsiString;
  1312. begin
  1313. result := AnsiString(S);
  1314. end;
  1315. class function TMarshal.InOutString(const S: UnicodeString): PUnicodeChar;
  1316. begin
  1317. Result := PUnicodeChar(S);
  1318. end;
  1319. class function TMarshal.InString(const S: UnicodeString): PUnicodeChar;
  1320. begin
  1321. Result := PUnicodeChar(S);
  1322. end;
  1323. class function TMarshal.OutString(const S: UnicodeString): PUnicodeChar;
  1324. begin
  1325. Result := PUnicodeChar(S);
  1326. end;
  1327. class function TMarshal.FixString(var Str: UnicodeString): TPtrWrapper;
  1328. begin
  1329. UniqueString(Str);
  1330. Result := UnsafeFixString(Str);
  1331. end;
  1332. class procedure TMarshal.UnfixString(Ptr: TPtrWrapper);
  1333. begin
  1334. if Ptr.Value <> PUnicodeChar('') then
  1335. Finalize(UnicodeString(Ptr));
  1336. end;
  1337. class function TMarshal.UnsafeFixString(const Str: UnicodeString): TPtrWrapper;
  1338. begin
  1339. if Length(Str) = 0 then
  1340. begin
  1341. Result.Value := PUnicodeChar('');
  1342. Exit;
  1343. end;
  1344. Result.Value := nil;
  1345. UnicodeString(Result) := Str;
  1346. end;
  1347. class function TMarshal.AllocStringAsAnsi(const Str: UnicodeString): TPtrWrapper;
  1348. begin
  1349. Result := AllocStringAsAnsi(PUnicodeChar(Pointer(Str)), Length(Str), DefaultSystemCodePage);
  1350. end;
  1351. class function TMarshal.AllocStringAsAnsi(const Str: UnicodeString; CodePage: Word): TPtrWrapper;
  1352. begin
  1353. Result := AllocStringAsAnsi(PUnicodeChar(Pointer(Str)), Length(Str), CodePage);
  1354. end;
  1355. class function TMarshal.AllocStringAsAnsi(S: PUnicodeChar): TPtrWrapper;
  1356. begin
  1357. Result := AllocStringAsAnsi(S, Length(S), DefaultSystemCodePage);
  1358. end;
  1359. class function TMarshal.AllocStringAsAnsi(S: PUnicodeChar; CodePage: Word): TPtrWrapper;
  1360. begin
  1361. Result := AllocStringAsAnsi(S, Length(S), CodePage);
  1362. end;
  1363. class function TMarshal.AllocStringAsUnicode(const Str: UnicodeString): TPtrWrapper;
  1364. var
  1365. NBytes: SizeUint;
  1366. begin
  1367. NBytes := (Length(Str) + 1) * SizeOf(UnicodeChar);
  1368. Result.Value := System.GetMem(NBytes);
  1369. System.Move(PUnicodeChar(Str)^, Result.Value^, NBytes);
  1370. end;
  1371. class function TMarshal.AllocStringAsUtf8(const Str: UnicodeString): TPtrWrapper;
  1372. begin
  1373. Result := AllocStringAsAnsi(PUnicodeChar(Pointer(Str)), Length(Str), CP_UTF8);
  1374. end;
  1375. class function TMarshal.AllocStringAsUtf8(S: PUnicodeChar): TPtrWrapper;
  1376. begin
  1377. Result := AllocStringAsAnsi(S, Length(S), CP_UTF8);
  1378. end;
  1379. class function TMarshal.AllocStringAsAnsi(S: PUnicodeChar; Len: SizeInt; CodePage: Word): TPtrWrapper;
  1380. var
  1381. U2ARes: AnsiString;
  1382. NBytes: SizeInt;
  1383. begin
  1384. U2ARes := ''; { Suppress warning. }
  1385. WideStringManager.Unicode2AnsiMoveProc(S, U2ARes, CodePage, Len);
  1386. if Length(U2ARes) = 0 then
  1387. begin
  1388. Result.Value := nil;
  1389. Exit;
  1390. end;
  1391. { Could instead avoid the second allocation, assuming U2ARes.RefCount = 1:
  1392. System.Move(Pointer(U2ARes)^, (Pointer(U2ARes) - AnsiStringHeaderSize)^, (Length(U2ARes) + 1) * SizeOf(AnsiChar));
  1393. Result.FValue := Pointer(U2ARes) - AnsiStringHeaderSize;
  1394. Pointer(U2ARes) := nil; }
  1395. NBytes := (Length(U2ARes) + 1) * SizeOf(AnsiChar);
  1396. Result.Value := System.GetMem(NBytes);
  1397. System.Move(PAnsiChar(U2ARes)^, Result.Value^, NBytes);
  1398. end;
  1399. class procedure TMarshal.Copy(const Src: TUnicodeCharArray; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1400. begin
  1401. System.Move(PUnicodeChar(Src)[StartIndex], Dest.Value^, Count * SizeOf(UnicodeChar));
  1402. end;
  1403. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TUnicodeCharArray; StartIndex: SizeInt; Count: SizeInt);
  1404. begin
  1405. System.Move(Src.Value^, PUnicodeChar(Dest)[StartIndex], Count * SizeOf(UnicodeChar));
  1406. end;
  1407. class function TMarshal.ReadStringAsAnsi(Ptr: TPtrWrapper; Len: SizeInt = -1): UnicodeString;
  1408. begin
  1409. Result := ReadStringAsAnsi(DefaultSystemCodePage, Ptr, Len);
  1410. end;
  1411. class function TMarshal.ReadStringAsAnsi(CodePage: Word; Ptr: TPtrWrapper; Len: SizeInt = -1): UnicodeString;
  1412. begin
  1413. { Here and below, IndexByte/Word assume that, when Len >= 0, either:
  1414. - Up to Len characters are accessible in Ptr;
  1415. - IndexByte/Word cannot access invalid memory past the searched character
  1416. (e.g. i386.inc and x86_64.inc IndexByte/Word versions are specifically designed not to). }
  1417. if Len < 0 then
  1418. Len := IndexByte(Ptr.Value^, Len, 0);
  1419. Result := ''; { Suppress warning. }
  1420. WideStringManager.Ansi2UnicodeMoveProc(Ptr.Value, CodePage, Result, Len);
  1421. end;
  1422. class function TMarshal.ReadStringAsAnsiUpTo(CodePage: Word; Ptr: TPtrWrapper; MaxLen: SizeInt): UnicodeString;
  1423. var
  1424. Len: SizeInt;
  1425. begin
  1426. Len := IndexByte(Ptr.Value^, MaxLen, 0);
  1427. if Len < 0 then
  1428. Len := MaxLen;
  1429. Result := ReadStringAsAnsi(CodePage, Ptr, Len);
  1430. end;
  1431. class procedure TMarshal.WriteStringAsAnsi(Ptr: TPtrWrapper; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1432. begin
  1433. WriteStringAsAnsi(Ptr, 0, Value, MaxCharsIncNull, DefaultSystemCodePage);
  1434. end;
  1435. class procedure TMarshal.WriteStringAsAnsi(Ptr: TPtrWrapper; const Value: UnicodeString; MaxCharsIncNull: SizeInt; CodePage: Word);
  1436. begin
  1437. WriteStringAsAnsi(Ptr, 0, Value, MaxCharsIncNull, CodePage);
  1438. end;
  1439. class procedure TMarshal.WriteStringAsAnsi(Ptr: TPtrWrapper; Ofs: SizeInt; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1440. begin
  1441. WriteStringAsAnsi(Ptr, Ofs, Value, MaxCharsIncNull, DefaultSystemCodePage);
  1442. end;
  1443. class procedure TMarshal.WriteStringAsAnsi(Ptr: TPtrWrapper; Ofs: SizeInt; const Value: UnicodeString; MaxCharsIncNull: SizeInt; CodePage: Word);
  1444. var
  1445. U2ARes: AnsiString;
  1446. ValueLen, U2AResLen: SizeInt;
  1447. begin
  1448. U2ARes := ''; { Suppress warning. }
  1449. ValueLen := Length(Value);
  1450. { Delphi null-terminates iff MaxCharsIncNull < 0, so MaxCharsIncNull is actually just MaxChars. }
  1451. if (MaxCharsIncNull > 0) and (MaxCharsIncNull < ValueLen) then
  1452. ValueLen := MaxCharsIncNull; { UTF-16 → ANSI should never shrink element count, so limit the number of characters analyzed. }
  1453. WideStringManager.Unicode2AnsiMoveProc(PUnicodeChar(Pointer(Value)), U2ARes, CodePage, ValueLen);
  1454. U2AResLen := Length(U2ARes);
  1455. if (MaxCharsIncNull >= 0) and (MaxCharsIncNull < U2AResLen) then
  1456. U2AResLen := MaxCharsIncNull;
  1457. System.Move(PAnsiChar(Pointer(U2ARes))^, (Ptr.Value + Ofs)^, U2AResLen * SizeOf(AnsiChar));
  1458. if MaxCharsIncNull < 0 then
  1459. PAnsiChar(Ptr.Value + Ofs)[U2AResLen] := #0;
  1460. end;
  1461. class function TMarshal.ReadStringAsUnicode(Ptr: TPtrWrapper; Len: SizeInt = -1): UnicodeString;
  1462. begin
  1463. if Len < 0 then
  1464. Len := Length(PUnicodeChar(Ptr.Value));
  1465. Result := ''; { Suppress warning. }
  1466. SetLength(Result, Len);
  1467. System.Move(Ptr.Value^, Pointer(Result)^, Len * SizeOf(UnicodeChar));
  1468. end;
  1469. class function TMarshal.ReadStringAsUnicodeUpTo(Ptr: TPtrWrapper; MaxLen: SizeInt): UnicodeString;
  1470. var
  1471. Len: SizeInt;
  1472. begin
  1473. Len := IndexWord(Ptr.Value^, MaxLen, 0);
  1474. if Len < 0 then
  1475. Len := MaxLen;
  1476. Result := ReadStringAsUnicode(Ptr, Len);
  1477. end;
  1478. class procedure TMarshal.WriteStringAsUnicode(Ptr: TPtrWrapper; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1479. begin
  1480. WriteStringAsUnicode(Ptr, 0, Value, MaxCharsIncNull);
  1481. end;
  1482. class procedure TMarshal.WriteStringAsUnicode(Ptr: TPtrWrapper; Ofs: SizeInt; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1483. var
  1484. Len: SizeInt;
  1485. begin
  1486. { Again, Delphi null-terminates iff MaxCharsIncNull < 0, so MaxCharsIncNull is actually just MaxChars. }
  1487. Len := Length(Value);
  1488. if (MaxCharsIncNull >= 0) and (MaxCharsIncNull < Len) then
  1489. Len := MaxCharsIncNull;
  1490. System.Move(Pointer(Value)^, (Ptr.Value + Ofs)^, Len * SizeOf(UnicodeChar));
  1491. if MaxCharsIncNull < 0 then
  1492. PUnicodeChar(Ptr.Value + Ofs)[Len] := #0;
  1493. end;
  1494. class function TMarshal.ReadStringAsUtf8(Ptr: TPtrWrapper; Len: SizeInt = -1): UnicodeString;
  1495. begin
  1496. Result := ReadStringAsAnsi(CP_UTF8, Ptr, Len);
  1497. end;
  1498. class function TMarshal.ReadStringAsUtf8UpTo(Ptr: TPtrWrapper; MaxLen: SizeInt): UnicodeString;
  1499. begin
  1500. Result := ReadStringAsAnsiUpTo(CP_UTF8, Ptr, MaxLen);
  1501. end;
  1502. class procedure TMarshal.WriteStringAsUtf8(Ptr: TPtrWrapper; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1503. begin
  1504. WriteStringAsAnsi(Ptr, Value, MaxCharsIncNull, CP_UTF8);
  1505. end;
  1506. class procedure TMarshal.WriteStringAsUtf8(Ptr: TPtrWrapper; Ofs: SizeInt; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1507. begin
  1508. WriteStringAsAnsi(Ptr, Ofs, Value, MaxCharsIncNull, CP_UTF8);
  1509. end;
  1510. {$ENDIF}