objpas.inc 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865
  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. {$PUSH}
  432. {$PACKRECORDS NORMAL}
  433. tmethodnamerec =
  434. {$IFNDEF FPC_REQUIRES_PROPER_ALIGNMENT}
  435. packed
  436. {$ENDIF FPC_REQUIRES_PROPER_ALIGNMENT}
  437. record
  438. name : pshortstring;
  439. addr : codepointer;
  440. end;
  441. tmethodnametable =
  442. {$IFNDEF FPC_REQUIRES_PROPER_ALIGNMENT}
  443. packed
  444. {$ENDIF FPC_REQUIRES_PROPER_ALIGNMENT}
  445. record
  446. count : dword;
  447. entries : packed array[0..0] of tmethodnamerec;
  448. end;
  449. {$POP}
  450. pmethodnametable = ^tmethodnametable;
  451. class function TObject.MethodAddress(const name : shortstring) : codepointer;
  452. var
  453. methodtable : pmethodnametable;
  454. i : longint; // in case count=0
  455. ovmt : PVmt;
  456. begin
  457. ovmt:=PVmt(self);
  458. while assigned(ovmt) do
  459. begin
  460. methodtable:=pmethodnametable(ovmt^.vMethodTable);
  461. if assigned(methodtable) then
  462. begin
  463. for i:=0 to methodtable^.count-1 do
  464. if ShortCompareText(methodtable^.entries[i].name^, name)=0 then
  465. begin
  466. MethodAddress:=methodtable^.entries[i].addr;
  467. exit;
  468. end;
  469. end;
  470. ovmt := ovmt^.vParent;
  471. end;
  472. MethodAddress:=nil;
  473. end;
  474. class function TObject.MethodName(address : codepointer) : shortstring;
  475. var
  476. methodtable : pmethodnametable;
  477. i : longint; // in case count=0
  478. ovmt : PVmt;
  479. begin
  480. ovmt:=PVmt(self);
  481. while assigned(ovmt) do
  482. begin
  483. methodtable:=pmethodnametable(ovmt^.vMethodTable);
  484. if assigned(methodtable) then
  485. begin
  486. for i:=0 to methodtable^.count-1 do
  487. if methodtable^.entries[i].addr=address then
  488. begin
  489. MethodName:=methodtable^.entries[i].name^;
  490. exit;
  491. end;
  492. end;
  493. ovmt := ovmt^.vParent;
  494. end;
  495. MethodName:='';
  496. end;
  497. function TObject.FieldAddress(const name : shortstring) : pointer;
  498. {The following is copied to the typinfo unit. If it is changed here, change it there as well ! }
  499. type
  500. {$PUSH}
  501. {$PACKRECORDS NORMAL}
  502. PFieldInfo = ^TFieldInfo;
  503. TFieldInfo =
  504. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  505. packed
  506. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  507. record
  508. FieldOffset: SizeUInt;
  509. ClassTypeIndex: Word;
  510. Name: ShortString;
  511. end;
  512. PFieldTable = ^TFieldTable;
  513. TFieldTable =
  514. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  515. packed
  516. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  517. record
  518. FieldCount: Word;
  519. ClassTable: Pointer;
  520. { should be array[Word] of TFieldInfo; but
  521. Elements have variant size! force at least proper alignment }
  522. Fields: array[0..0] of TFieldInfo
  523. end;
  524. {$POP}
  525. var
  526. ovmt: PVmt;
  527. FieldTable: PFieldTable;
  528. FieldInfo: PFieldInfo;
  529. i: longint;
  530. begin
  531. if Length(name) > 0 then
  532. begin
  533. ovmt := PVmt(ClassType);
  534. while ovmt <> nil do
  535. begin
  536. FieldTable := PFieldTable(ovmt^.vFieldTable);
  537. if FieldTable <> nil then
  538. begin
  539. FieldInfo := @FieldTable^.Fields[0];
  540. for i := 0 to FieldTable^.FieldCount - 1 do
  541. begin
  542. if ShortCompareText(FieldInfo^.Name, name) = 0 then
  543. begin
  544. fieldaddress := Pointer(Self) + FieldInfo^.FieldOffset;
  545. exit;
  546. end;
  547. FieldInfo := PFieldInfo(PByte(@FieldInfo^.Name) + 1 + Length(FieldInfo^.Name));
  548. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  549. { align to largest field of TFieldInfo }
  550. FieldInfo := Align(FieldInfo, SizeOf(PtrUInt));
  551. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  552. end;
  553. end;
  554. { Try again with the parent class type }
  555. ovmt:=ovmt^.vParent;
  556. end;
  557. end;
  558. fieldaddress:=nil;
  559. end;
  560. function TObject.SafeCallException(exceptobject : tobject;
  561. exceptaddr : codepointer) : HResult;
  562. begin
  563. safecallexception:=E_UNEXPECTED;
  564. end;
  565. class function TObject.ClassInfo : pointer;
  566. begin
  567. ClassInfo := PVmt(Self)^.vTypeInfo;
  568. end;
  569. class function TObject.ClassName : ShortString;
  570. begin
  571. ClassName := PVmt(Self)^.vClassName^;
  572. end;
  573. class function TObject.ClassNameIs(const name : RTLString) : boolean;
  574. var
  575. SS : ShortString;
  576. begin
  577. SS:=ShortString(Name);
  578. ClassNameIs:=ShortCompareText(PVmt(Self)^.vClassName^, SS) = 0;
  579. end;
  580. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  581. var
  582. vmt: PVmt;
  583. begin
  584. if assigned(aclass) then
  585. begin
  586. vmt:=PVmt(self);
  587. while assigned(vmt) and (vmt <> PVmt(aclass)) do
  588. vmt := vmt^.vParent;
  589. InheritsFrom := (vmt = PVmt(aclass));
  590. end
  591. else
  592. inheritsFrom := False;
  593. end;
  594. class function TObject.stringmessagetable : pstringmessagetable;
  595. begin
  596. stringmessagetable:=PVmt(Self)^.vMsgStrPtr;
  597. end;
  598. type
  599. tmessagehandler = procedure(var msg) of object;
  600. procedure TObject.Dispatch(var message);
  601. type
  602. {$PUSH}
  603. {$PACKRECORDS NORMAL}
  604. PMsgIntTable = ^TMsgIntTable;
  605. TMsgIntTable = record
  606. index : dword;
  607. method : codepointer;
  608. end;
  609. PMsgInt = ^TMsgInt;
  610. TMsgInt = record
  611. count : longint;
  612. msgs : array[0..0] of TMsgIntTable;
  613. end;
  614. {$POP}
  615. var
  616. index : dword;
  617. count,i : longint;
  618. msgtable : PMsgIntTable;
  619. p : PMsgInt;
  620. ovmt : PVmt;
  621. msghandler : tmessagehandler;
  622. begin
  623. index:=dword(message);
  624. ovmt := PVmt(ClassType);
  625. while assigned(ovmt) do
  626. begin
  627. // See if we have messages at all in this class.
  628. p:=PMsgInt(ovmt^.vDynamicTable);
  629. If Assigned(p) then
  630. begin
  631. msgtable:=@p^.msgs;
  632. count:=p^.count;
  633. end
  634. else
  635. Count:=0;
  636. { later, we can implement a binary search here }
  637. for i:=0 to count-1 do
  638. begin
  639. if index=msgtable[i].index then
  640. begin
  641. TMethod(msghandler).Code:=msgtable[i].method;
  642. TMethod(msghandler).Data:=self;
  643. msghandler(message);
  644. exit;
  645. end;
  646. end;
  647. ovmt:=ovmt^.vParent;
  648. end;
  649. DefaultHandler(message);
  650. end;
  651. procedure TObject.DispatchStr(var message);
  652. var
  653. name : shortstring;
  654. count,i : longint;
  655. msgstrtable : pmsgstrtable;
  656. p: pstringmessagetable;
  657. ovmt : PVmt;
  658. msghandler : tmessagehandler;
  659. begin
  660. name:=pshortstring(@message)^;
  661. ovmt:=PVmt(ClassType);
  662. while assigned(ovmt) do
  663. begin
  664. p := ovmt^.vMsgStrPtr;
  665. if (P<>Nil) and (p^.count<>0) then
  666. begin
  667. count:=p^.count;
  668. msgstrtable:=@p^.msgstrtable;
  669. end
  670. else
  671. Count:=0;
  672. { later, we can implement a binary search here }
  673. for i:=0 to count-1 do
  674. begin
  675. if name=msgstrtable[i].name^ then
  676. begin
  677. TMethod(msghandler).Code:=msgstrtable[i].method;
  678. TMethod(msghandler).Data:=self;
  679. msghandler(message);
  680. exit;
  681. end;
  682. end;
  683. ovmt:=ovmt^.vParent;
  684. end;
  685. DefaultHandlerStr(message);
  686. end;
  687. procedure TObject.DefaultHandler(var message);
  688. begin
  689. end;
  690. procedure TObject.DefaultHandlerStr(var message);
  691. begin
  692. end;
  693. procedure TObject.CleanupInstance;
  694. var
  695. vmt : PVmt;
  696. temp : pointer;
  697. begin
  698. vmt := PVmt(ClassType);
  699. while vmt<>nil do
  700. begin
  701. Temp:= vmt^.vInitTable;
  702. {$ifdef FPC_HAS_FEATURE_RTTI}
  703. { The RTTI format matches one for records, except the type is tkClass.
  704. Since RecordRTTI does not check the type, calling it yields the desired result. }
  705. if Assigned(Temp) then
  706. RecordRTTI(Self,Temp,@int_finalize);
  707. {$endif def FPC_HAS_FEATURE_RTTI}
  708. vmt:= vmt^.vParent;
  709. end;
  710. end;
  711. procedure TObject.AfterConstruction;
  712. begin
  713. end;
  714. procedure TObject.BeforeDestruction;
  715. begin
  716. end;
  717. function IsGUIDEqual(const guid1, guid2: tguid): boolean;
  718. begin
  719. IsGUIDEqual:=
  720. (guid1.D1=guid2.D1) and
  721. (PDWORD(@guid1.D2)^=PDWORD(@guid2.D2)^) and
  722. (PDWORD(@guid1.D4[0])^=PDWORD(@guid2.D4[0])^) and
  723. (PDWORD(@guid1.D4[4])^=PDWORD(@guid2.D4[4])^);
  724. end;
  725. // Use of managed types should be avoided here; implicit _Addref/_Release
  726. // will end up in unpredictable behaviour if called on CORBA interfaces.
  727. type
  728. TInterfaceGetter = procedure(out Obj) of object;
  729. TClassGetter = function: TObject of object;
  730. function GetInterfaceByEntry(Instance: pointer; IEntry: pinterfaceentry; out obj): boolean;
  731. var
  732. Getter: TMethod;
  733. begin
  734. Pointer(Obj) := nil;
  735. Getter.Data := Instance;
  736. if Assigned(IEntry) and Assigned(Instance) then
  737. begin
  738. case IEntry^.IType of
  739. etStandard:
  740. Pointer(Obj) := PByte(instance)+IEntry^.IOffset;
  741. etFieldValue, etFieldValueClass:
  742. Pointer(obj) := PPointer(PByte(Instance)+IEntry^.IOffset)^;
  743. etVirtualMethodResult:
  744. begin
  745. // IOffset is relative to the VMT, not to instance.
  746. Getter.code := PCodePointer(PByte(PPointer(Instance)^) + IEntry^.IOffset)^;
  747. TInterfaceGetter(Getter)(obj);
  748. end;
  749. etVirtualMethodClass:
  750. begin
  751. // IOffset is relative to the VMT, not to instance.
  752. Getter.code := PCodePointer(PByte(PPointer(Instance)^) + IEntry^.IOffset)^;
  753. TObject(obj) := TClassGetter(Getter)();
  754. end;
  755. etStaticMethodResult:
  756. begin
  757. Getter.code := IEntry^.IOffsetAsCodePtr;
  758. TInterfaceGetter(Getter)(obj);
  759. end;
  760. etStaticMethodClass:
  761. begin
  762. Getter.code := IEntry^.IOffsetAsCodePtr;
  763. TObject(obj) := TClassGetter(Getter)();
  764. end;
  765. end;
  766. end;
  767. result := assigned(pointer(obj));
  768. end;
  769. function TObject.GetInterface(const iid : tguid;out obj) : boolean;
  770. var
  771. IEntry: PInterfaceEntry;
  772. Instance: TObject;
  773. begin
  774. if IsGUIDEqual(IObjectInstance,iid) then
  775. begin
  776. TObject(Obj) := Self;
  777. Result := True;
  778. Exit;
  779. end;
  780. Instance := self;
  781. repeat
  782. IEntry := Instance.GetInterfaceEntry(iid);
  783. result := GetInterfaceByEntry(Instance, IEntry, obj);
  784. if (not result) or
  785. (IEntry^.IType in [etStandard, etFieldValue,
  786. etStaticMethodResult, etVirtualMethodResult]) then
  787. Break;
  788. { if interface is implemented by a class-type property or field,
  789. continue search }
  790. Instance := TObject(obj);
  791. until False;
  792. { Getter function will normally AddRef, so adding another reference here
  793. will cause memleak. }
  794. if result and (IEntry^.IType in [etStandard, etFieldValue]) then
  795. IInterface(obj)._AddRef;
  796. end;
  797. function TObject.GetInterfaceWeak(const iid : tguid; out obj) : boolean;
  798. var
  799. IEntry: PInterfaceEntry;
  800. Instance: TObject;
  801. begin
  802. if IsGUIDEqual(IObjectInstance,iid) then
  803. begin
  804. TObject(Obj) := Self;
  805. Result := True;
  806. Exit;
  807. end;
  808. Instance := self;
  809. repeat
  810. IEntry := Instance.GetInterfaceEntry(iid);
  811. result := GetInterfaceByEntry(Instance, IEntry, obj);
  812. if (not result) or
  813. (IEntry^.IType in [etStandard, etFieldValue,
  814. etStaticMethodResult, etVirtualMethodResult]) then
  815. Break;
  816. { if interface is implemented by a class-type property or field,
  817. continue search }
  818. Instance := TObject(obj);
  819. until False;
  820. { Getter function will normally AddRef, so we have to release it,
  821. else the ref is not weak. }
  822. if result and not (IEntry^.IType in [etStandard, etFieldValue]) then
  823. IInterface(obj)._Release;
  824. end;
  825. function TObject.GetInterfaceByStr(const iidstr : shortstring;out obj) : boolean;
  826. var
  827. IEntry: PInterfaceEntry;
  828. Instance: TObject;
  829. begin
  830. Instance := self;
  831. repeat
  832. IEntry := Instance.GetInterfaceEntryByStr(iidstr);
  833. result := GetInterfaceByEntry(Instance, IEntry, obj);
  834. if (not result) or
  835. (IEntry^.IType in [etStandard, etFieldValue,
  836. etStaticMethodResult, etVirtualMethodResult]) then
  837. Break;
  838. { if interface is implemented by a class-type property or field,
  839. continue search }
  840. Instance := TObject(obj);
  841. until False;
  842. { Getter function will normally AddRef, so adding another reference here
  843. will cause memleak. (com interfaces only!) }
  844. if result and Assigned(IEntry^.IID) and (IEntry^.IType in [etStandard, etFieldValue]) then
  845. IInterface(obj)._AddRef;
  846. end;
  847. function TObject.GetInterface(const iidstr : shortstring;out obj) : boolean;
  848. begin
  849. Result := GetInterfaceByStr(iidstr,obj);
  850. end;
  851. class function TObject.GetInterfaceEntry(const iid : tguid) : pinterfaceentry;
  852. var
  853. i: longint;
  854. intftable: pinterfacetable;
  855. ovmt: PVmt;
  856. begin
  857. ovmt := PVmt(Self);
  858. while Assigned(ovmt) and {$ifdef VER3_0}(ovmt^.vIntfTable <> @emptyintf){$else}Assigned(ovmt^.vIntftable){$endif} do
  859. begin
  860. intftable:=ovmt^.vIntfTable;
  861. {$ifdef VER3_0}
  862. if assigned(intftable) then
  863. {$endif VER3_0}
  864. begin
  865. for i:=0 to intftable^.EntryCount-1 do
  866. begin
  867. result:=@intftable^.Entries[i];
  868. if assigned(Result^.iid) and IsGUIDEqual(Result^.iid^,iid) then
  869. Exit;
  870. end;
  871. end;
  872. ovmt := ovmt^.vParent;
  873. end;
  874. result := nil;
  875. end;
  876. class function TObject.GetInterfaceEntryByStr(const iidstr : shortstring) : pinterfaceentry;
  877. var
  878. i: longint;
  879. intftable: pinterfacetable;
  880. ovmt: PVmt;
  881. begin
  882. ovmt := PVmt(Self);
  883. while Assigned(ovmt) and {$ifdef VER3_0}(ovmt^.vIntfTable <> @emptyintf){$else}Assigned(ovmt^.vIntfTable){$endif} do
  884. begin
  885. intftable:=ovmt^.vIntfTable;
  886. {$ifdef VER3_0}
  887. if assigned(intftable) then
  888. {$endif VER3_0}
  889. begin
  890. for i:=0 to intftable^.EntryCount-1 do
  891. begin
  892. result:=@intftable^.Entries[i];
  893. if assigned(result^.iidstr) and (result^.iidstr^ = iidstr) then
  894. Exit;
  895. end;
  896. end;
  897. ovmt := ovmt^.vParent;
  898. end;
  899. result:=nil;
  900. end;
  901. class function TObject.GetInterfaceTable : pinterfacetable;
  902. begin
  903. getinterfacetable:=PVmt(Self)^.vIntfTable;
  904. end;
  905. class function TObject.UnitName : RTLString;
  906. {$ifdef FPC_HAS_FEATURE_RTTI}
  907. type
  908. TClassTypeInfo = {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  909. Attributes: Pointer;
  910. case TTypeKind of
  911. tkClass: (
  912. ClassType: TClass;
  913. ParentInfo: Pointer;
  914. PropCount: SmallInt;
  915. UnitName: ShortString;
  916. );
  917. { include for proper alignment }
  918. tkInt64: (
  919. Dummy: Int64;
  920. );
  921. end;
  922. PClassTypeInfo = ^TClassTypeInfo;
  923. var
  924. classtypeinfo: PClassTypeInfo;
  925. begin
  926. classtypeinfo:=ClassInfo;
  927. if Assigned(classtypeinfo) then
  928. begin
  929. // offset PTypeInfo by Length(Name) + 2 (ShortString length byte + SizeOf(Kind))
  930. inc(Pointer(classtypeinfo), PByte(Pointer(classtypeinfo)+1)^ + 2);
  931. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  932. classtypeinfo:=aligntoqword(classtypeinfo);
  933. {$endif}
  934. result:=classtypeinfo^.UnitName;
  935. end
  936. else
  937. result:='';
  938. end;
  939. {$else not FPC_HAS_FEATURE_RTTI}
  940. begin
  941. result:='';
  942. end;
  943. {$endif ndef FPC_HAS_FEATURE_RTTI}
  944. class function TObject.QualifiedClassName: RTLString;
  945. var
  946. uname: RTLString;
  947. begin
  948. uname := UnitName; //TODO: change 'UnitName' to 'UnitScope' as soon as RTL implement it
  949. if uname='' then
  950. result:=ClassName
  951. else
  952. result:=Concat(uname, '.', ClassName);
  953. end;
  954. function TObject.Equals(Obj: TObject) : boolean;
  955. begin
  956. result:=Obj=Self;
  957. end;
  958. function TObject.GetHashCode: PtrInt;
  959. begin
  960. result:=PtrInt(Self);
  961. end;
  962. function TObject.ToString: RTLString;
  963. begin
  964. result:=ClassName;
  965. end;
  966. procedure TObject.DisposeOf;
  967. begin
  968. Free;
  969. end;
  970. function TObject.GetDisposed : Boolean;
  971. begin
  972. Result:=False;
  973. end;
  974. procedure TObject.CheckDisposed;
  975. begin
  976. // Do nothing since we have no reference count.
  977. end;
  978. {****************************************************************************
  979. TINTERFACEDOBJECT
  980. ****************************************************************************}
  981. function TInterfacedObject.QueryInterface(
  982. {$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  983. begin
  984. if getinterface(iid,obj) then
  985. result:=S_OK
  986. else
  987. result:=longint(E_NOINTERFACE);
  988. end;
  989. function TInterfacedObject._AddRef : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  990. begin
  991. _addref:=interlockedincrement(frefcount);
  992. end;
  993. function TInterfacedObject._Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  994. begin
  995. _Release:=interlockeddecrement(frefcount);
  996. if _Release=0 then
  997. begin
  998. if interlockedincrement(fdestroycount)=1 then
  999. self.destroy;
  1000. end;
  1001. end;
  1002. destructor TInterfacedObject.Destroy;
  1003. begin
  1004. // We must explicitly reset. Bug ID 32353
  1005. FRefCount:=0;
  1006. FDestroyCount:=0;
  1007. inherited Destroy;
  1008. end;
  1009. procedure TInterfacedObject.AfterConstruction;
  1010. begin
  1011. { we need to fix the refcount we forced in newinstance }
  1012. { further, it must be done in a thread safe way }
  1013. declocked(frefcount);
  1014. end;
  1015. procedure TInterfacedObject.BeforeDestruction;
  1016. begin
  1017. if frefcount<>0 then
  1018. HandleError(204);
  1019. end;
  1020. class function TInterfacedObject.NewInstance : TObject;
  1021. begin
  1022. NewInstance:=inherited NewInstance;
  1023. if NewInstance<>nil then
  1024. TInterfacedObject(NewInstance).frefcount:=1;
  1025. end;
  1026. {****************************************************************************
  1027. TAGGREGATEDOBJECT
  1028. ****************************************************************************}
  1029. constructor TAggregatedObject.Create(const aController: IUnknown);
  1030. begin
  1031. inherited Create;
  1032. { do not keep a counted reference to the controller! }
  1033. fcontroller := Pointer(aController);
  1034. end;
  1035. function TAggregatedObject.QueryInterface(
  1036. {$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1037. begin
  1038. Result := IUnknown(fcontroller).QueryInterface(iid, obj);
  1039. end;
  1040. function TAggregatedObject._AddRef : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1041. begin
  1042. Result := IUnknown(fcontroller)._AddRef;
  1043. end;
  1044. function TAggregatedObject._Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1045. begin
  1046. Result := IUnknown(fcontroller)._Release;
  1047. end;
  1048. function TAggregatedObject.GetController : IUnknown;
  1049. begin
  1050. Result := IUnknown(fcontroller);
  1051. end;
  1052. {****************************************************************************
  1053. TContainedOBJECT
  1054. ****************************************************************************}
  1055. function TContainedObject.QueryInterface(
  1056. {$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1057. begin
  1058. if getinterface(iid,obj) then
  1059. result:=S_OK
  1060. else
  1061. result:=longint(E_NOINTERFACE);
  1062. end;
  1063. {****************************************************************************
  1064. TNoRefCountObject
  1065. ****************************************************************************}
  1066. function TNoRefCountObject.QueryInterface( {$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1067. begin
  1068. if getinterface(iid,obj) then
  1069. result:=S_OK
  1070. else
  1071. result:=longint(E_NOINTERFACE);
  1072. end;
  1073. function TNoRefCountObject._AddRef : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1074. begin
  1075. Result:=-1;
  1076. end;
  1077. function TNoRefCountObject._Release : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1078. begin
  1079. Result:=-1;
  1080. end;
  1081. {****************************************************************************
  1082. TCustomAttribute
  1083. ****************************************************************************}
  1084. constructor TCustomAttribute.Create;
  1085. begin
  1086. inherited;
  1087. end;
  1088. {****************************************************************************
  1089. TUnimplementedAttribute
  1090. ****************************************************************************}
  1091. constructor TUnimplementedAttribute.Create;
  1092. begin
  1093. inherited;
  1094. end;
  1095. {****************************************************************************
  1096. TCustomStoredAttribute
  1097. ****************************************************************************}
  1098. constructor StoredAttribute.Create;
  1099. begin
  1100. end;
  1101. constructor StoredAttribute.Create(Const aFlag : Boolean);
  1102. begin
  1103. FFlag:=aFlag;
  1104. end;
  1105. constructor StoredAttribute.Create(Const aName : shortstring);
  1106. begin
  1107. FName:=aName;
  1108. end;
  1109. {****************************************************************************
  1110. TInterfaceThunk
  1111. ****************************************************************************}
  1112. Constructor TInterfaceThunk.Create(aCallback : TThunkCallback);
  1113. begin
  1114. FCallBack:=aCallBack;
  1115. end;
  1116. Procedure TInterfaceThunk.Thunk(aMethod: Longint; aCount : Longint; aData : PArgData);
  1117. begin
  1118. if Assigned(FCallBack) then
  1119. FCallBack(Self,aMethod,aCount,aData);
  1120. end;
  1121. function TInterfaceThunk.QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  1122. begin
  1123. result:=longint(E_NOINTERFACE);
  1124. if (TMethod(FCallBack).Data<>Nil) then
  1125. // Query the object that created us, this is normally TVirtualInterface
  1126. // Take care: do not call QueryInterface, that would create a never-ending loop !!
  1127. if TObject(TMethod(FCallBack).Data).GetInterface(iid,obj) then
  1128. result:=S_OK;
  1129. if (Result<>S_OK) then
  1130. Result:=Inherited QueryInterface(iid,obj);
  1131. end;
  1132. function TInterfaceThunk.InterfaceVMTOffset : word;
  1133. begin
  1134. Result:=0;
  1135. end;
  1136. {****************************************************************************
  1137. Exception Support
  1138. ****************************************************************************}
  1139. {$ifdef FPC_HAS_FEATURE_EXCEPTIONS}
  1140. {$if defined(FPC_WASM_NATIVE_EXCEPTIONS)}
  1141. {$I except_native.inc}
  1142. {$elseif defined(FPC_WASM_BRANCHFUL_EXCEPTIONS)}
  1143. {$I except_branchful.inc}
  1144. {$else}
  1145. {$i except.inc}
  1146. {$endif}
  1147. {$endif FPC_HAS_FEATURE_EXCEPTIONS}
  1148. {****************************************************************************
  1149. Various Delphi constructs
  1150. ****************************************************************************}
  1151. function TPtrWrapper.ToPointer: Pointer;
  1152. begin
  1153. Result:=FValue;
  1154. end;
  1155. class function TPtrWrapper.GetNilValue: TPtrWrapper;
  1156. begin
  1157. Result.FValue:=Nil;
  1158. end;
  1159. constructor TPtrWrapper.Create(AValue: PtrInt);
  1160. begin
  1161. FValue:=Pointer(aValue);
  1162. end;
  1163. constructor TPtrWrapper.Create(AValue: Pointer);
  1164. begin
  1165. FValue:=aValue;
  1166. end;
  1167. function TPtrWrapper.ToInteger: PtrInt;
  1168. begin
  1169. Result:=PtrInt(FValue);
  1170. end;
  1171. class operator TPtrWrapper.=(Left, Right: TPtrWrapper): Boolean;
  1172. begin
  1173. Result:=Left.FValue=Right.FValue;
  1174. end;
  1175. constructor TMarshal.Create;
  1176. begin
  1177. System.Error(reInvalidPtr);
  1178. end;
  1179. class function TMarshal.AllocMem(Size: SizeInt): TPtrWrapper;
  1180. begin
  1181. Result.Value := System.AllocMem(Size);
  1182. end;
  1183. class function TMarshal.ReallocMem(OldPtr: TPtrWrapper; NewSize: SizeInt): TPtrWrapper;
  1184. var
  1185. P: Pointer;
  1186. begin
  1187. P := OldPtr.Value;
  1188. Result.Value := System.ReallocMem(P, NewSize);
  1189. end;
  1190. class procedure TMarshal.FreeMem(Ptr: TPtrWrapper);
  1191. begin
  1192. System.FreeMem(Ptr.Value);
  1193. end;
  1194. class procedure TMarshal.Move(Src, Dest: TPtrWrapper; Count: SizeInt); static;
  1195. begin
  1196. System.Move(Src.Value^, Dest.Value^, Count);
  1197. end;
  1198. class function TMarshal.UnsafeAddrOf(var Value): TPtrWrapper;
  1199. begin
  1200. Result.Value := @Value;
  1201. end;
  1202. class procedure TMarshal.Copy(const Src: TUint8Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1203. begin
  1204. System.Move(PUInt8(Src)[StartIndex], Dest.Value^, Count * SizeOf(UInt8));
  1205. end;
  1206. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TUint8Array; StartIndex: SizeInt; Count: SizeInt);
  1207. begin
  1208. System.Move(Src.Value^, PUInt8(Dest)[StartIndex], Count * SizeOf(UInt8));
  1209. end;
  1210. class procedure TMarshal.Copy(const Src: TInt8Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1211. begin
  1212. System.Move(PInt8(Src)[StartIndex], Dest.Value^, Count * SizeOf(Int8));
  1213. end;
  1214. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TInt8Array ; StartIndex: SizeInt; Count: SizeInt);
  1215. begin
  1216. System.Move(Src.Value^, PInt8(Dest)[StartIndex], Count * SizeOf(Int8));
  1217. end;
  1218. class procedure TMarshal.Copy(const Src: TUInt16Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1219. begin
  1220. System.Move(PUInt16(Src)[StartIndex], Dest.Value^, Count * SizeOf(UInt16));
  1221. end;
  1222. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TUint16Array; StartIndex: SizeInt; Count: SizeInt);
  1223. begin
  1224. System.Move(Src.Value^, PUInt16(Dest)[StartIndex], Count * SizeOf(UInt16));
  1225. end;
  1226. class procedure TMarshal.Copy(const Src: TInt16Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1227. begin
  1228. System.Move(PInt16(Src)[StartIndex], Dest.Value^, Count * SizeOf(Int16));
  1229. end;
  1230. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TInt16Array; StartIndex: SizeInt; Count: SizeInt);
  1231. begin
  1232. System.Move(Src.Value^, PInt16(Dest)[StartIndex], Count * SizeOf(Int16));
  1233. end;
  1234. class procedure TMarshal.Copy(const Src: TInt32Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1235. begin
  1236. System.Move(PInt32(Src)[StartIndex], Dest.Value^, Count * SizeOf(Int32));
  1237. end;
  1238. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TInt32Array; StartIndex: SizeInt; Count: SizeInt);
  1239. begin
  1240. System.Move(Src.Value^, PInt32(Dest)[StartIndex], Count * SizeOf(Int32));
  1241. end;
  1242. class procedure TMarshal.Copy(const Src: TInt64Array; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1243. begin
  1244. System.Move(PInt64(Src)[StartIndex], Dest.Value^, Count * SizeOf(Int64));
  1245. end;
  1246. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TInt64Array; StartIndex: SizeInt; Count: SizeInt);
  1247. begin
  1248. System.Move(Src.Value^, PInt64(Dest)[StartIndex], Count * SizeOf(Int64));
  1249. end;
  1250. class procedure TMarshal.Copy(const Src: TPtrWrapperArray; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1251. begin
  1252. System.Move(PPointer(Src)[StartIndex], Dest.Value^, Count * SizeOf(TPtrWrapper));
  1253. end;
  1254. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TPtrWrapperArray; StartIndex: SizeInt; Count: SizeInt);
  1255. begin
  1256. System.Move(Src.Value^, PPointer(Dest)[StartIndex], Count * SizeOf(TPtrWrapper));
  1257. end;
  1258. generic class function TMarshal.FixArray<T>(const Arr: specialize TArray<T>): TPtrWrapper;
  1259. begin
  1260. Result.Value := nil;
  1261. specialize TArray<T>(Result) := Arr;
  1262. end;
  1263. generic class procedure TMarshal.UnfixArray<T>(ArrPtr: TPtrWrapper);
  1264. begin
  1265. Finalize(specialize TArray<T>(ArrPtr));
  1266. end;
  1267. class function TMarshal.ReadByte(Ptr: TPtrWrapper; Ofs: SizeInt = 0): Byte;
  1268. begin
  1269. Result := PByte(Ptr.Value + Ofs)^;
  1270. end;
  1271. class procedure TMarshal.WriteByte(Ptr: TPtrWrapper; Ofs: SizeInt; Value: Byte);
  1272. begin
  1273. PByte(Ptr.Value + Ofs)^ := Value;
  1274. end;
  1275. class procedure TMarshal.WriteByte(Ptr: TPtrWrapper; Value: Byte);
  1276. begin
  1277. PByte(Ptr.Value)^ := Value;
  1278. end;
  1279. class function TMarshal.ReadInt16(Ptr: TPtrWrapper; Ofs: SizeInt = 0): Int16;
  1280. begin
  1281. Result := PInt16(Ptr.Value + Ofs)^;
  1282. end;
  1283. class procedure TMarshal.WriteInt16(Ptr: TPtrWrapper; Ofs: SizeInt; Value: Int16);
  1284. begin
  1285. PInt16(Ptr.Value + Ofs)^ := Value;
  1286. end;
  1287. class procedure TMarshal.WriteInt16(Ptr: TPtrWrapper; Value: Int16);
  1288. begin
  1289. PInt16(Ptr.Value)^ := Value;
  1290. end;
  1291. class function TMarshal.ReadInt32(Ptr: TPtrWrapper; Ofs: SizeInt = 0): Int32;
  1292. begin
  1293. Result := PInt32(Ptr.Value + Ofs)^;
  1294. end;
  1295. class procedure TMarshal.WriteInt32(Ptr: TPtrWrapper; Ofs: SizeInt; Value: Int32);
  1296. begin
  1297. PInt32(Ptr.Value + Ofs)^ := Value;
  1298. end;
  1299. class procedure TMarshal.WriteInt32(Ptr: TPtrWrapper; Value: Int32);
  1300. begin
  1301. PInt32(Ptr.Value)^ := Value;
  1302. end;
  1303. class function TMarshal.ReadInt64(Ptr: TPtrWrapper; Ofs: SizeInt = 0): Int64;
  1304. begin
  1305. Result := PInt64(Ptr.Value + Ofs)^;
  1306. end;
  1307. class procedure TMarshal.WriteInt64(Ptr: TPtrWrapper; Ofs: SizeInt; Value: Int64);
  1308. begin
  1309. PInt64(Ptr.Value + Ofs)^ := Value;
  1310. end;
  1311. class procedure TMarshal.WriteInt64(Ptr: TPtrWrapper; Value: Int64);
  1312. begin
  1313. PInt64(Ptr.Value)^ := Value;
  1314. end;
  1315. class function TMarshal.ReadPtr(Ptr: TPtrWrapper; Ofs: SizeInt = 0): TPtrWrapper;
  1316. begin
  1317. Result.Value := PPointer(Ptr.Value + Ofs)^;
  1318. end;
  1319. class procedure TMarshal.WritePtr(Ptr: TPtrWrapper; Ofs: SizeInt; Value: TPtrWrapper);
  1320. begin
  1321. PPointer(Ptr.Value + Ofs)^ := Value.Value;
  1322. end;
  1323. class procedure TMarshal.WritePtr(Ptr, Value: TPtrWrapper);
  1324. begin
  1325. PPointer(Ptr.Value)^ := Value.Value;
  1326. end;
  1327. {$IFDEF FPC_HAS_FEATURE_UNICODESTRINGS}
  1328. class function TMarshal.AsAnsi(const S: UnicodeString): AnsiString;
  1329. begin
  1330. Result := AnsiString(S);
  1331. end;
  1332. class function TMarshal.AsAnsi(S: PUnicodeChar): AnsiString;
  1333. begin
  1334. result := AnsiString(S);
  1335. end;
  1336. class function TMarshal.InOutString(const S: UnicodeString): PUnicodeChar;
  1337. begin
  1338. Result := PUnicodeChar(S);
  1339. end;
  1340. class function TMarshal.InString(const S: UnicodeString): PUnicodeChar;
  1341. begin
  1342. Result := PUnicodeChar(S);
  1343. end;
  1344. class function TMarshal.OutString(const S: UnicodeString): PUnicodeChar;
  1345. begin
  1346. Result := PUnicodeChar(S);
  1347. end;
  1348. class function TMarshal.FixString(var Str: UnicodeString): TPtrWrapper;
  1349. begin
  1350. UniqueString(Str);
  1351. Result := UnsafeFixString(Str);
  1352. end;
  1353. class procedure TMarshal.UnfixString(Ptr: TPtrWrapper);
  1354. begin
  1355. if Ptr.Value <> PUnicodeChar('') then
  1356. Finalize(UnicodeString(Ptr));
  1357. end;
  1358. class function TMarshal.UnsafeFixString(const Str: UnicodeString): TPtrWrapper;
  1359. begin
  1360. if Length(Str) = 0 then
  1361. begin
  1362. Result.Value := PUnicodeChar('');
  1363. Exit;
  1364. end;
  1365. Result.Value := nil;
  1366. UnicodeString(Result) := Str;
  1367. end;
  1368. class function TMarshal.AllocStringAsAnsi(const Str: UnicodeString): TPtrWrapper;
  1369. begin
  1370. Result := AllocStringAsAnsi(PUnicodeChar(Pointer(Str)), Length(Str), DefaultSystemCodePage);
  1371. end;
  1372. class function TMarshal.AllocStringAsAnsi(const Str: UnicodeString; CodePage: Word): TPtrWrapper;
  1373. begin
  1374. Result := AllocStringAsAnsi(PUnicodeChar(Pointer(Str)), Length(Str), CodePage);
  1375. end;
  1376. class function TMarshal.AllocStringAsAnsi(S: PUnicodeChar): TPtrWrapper;
  1377. begin
  1378. Result := AllocStringAsAnsi(S, Length(S), DefaultSystemCodePage);
  1379. end;
  1380. class function TMarshal.AllocStringAsAnsi(S: PUnicodeChar; CodePage: Word): TPtrWrapper;
  1381. begin
  1382. Result := AllocStringAsAnsi(S, Length(S), CodePage);
  1383. end;
  1384. class function TMarshal.AllocStringAsUnicode(const Str: UnicodeString): TPtrWrapper;
  1385. var
  1386. NBytes: SizeUint;
  1387. begin
  1388. NBytes := (Length(Str) + 1) * SizeOf(UnicodeChar);
  1389. Result.Value := System.GetMem(NBytes);
  1390. System.Move(PUnicodeChar(Str)^, Result.Value^, NBytes);
  1391. end;
  1392. class function TMarshal.AllocStringAsUtf8(const Str: UnicodeString): TPtrWrapper;
  1393. begin
  1394. Result := AllocStringAsAnsi(PUnicodeChar(Pointer(Str)), Length(Str), CP_UTF8);
  1395. end;
  1396. class function TMarshal.AllocStringAsUtf8(S: PUnicodeChar): TPtrWrapper;
  1397. begin
  1398. Result := AllocStringAsAnsi(S, Length(S), CP_UTF8);
  1399. end;
  1400. class function TMarshal.AllocStringAsAnsi(S: PUnicodeChar; Len: SizeInt; CodePage: Word): TPtrWrapper;
  1401. var
  1402. U2ARes: AnsiString;
  1403. NBytes: SizeInt;
  1404. begin
  1405. U2ARes := ''; { Suppress warning. }
  1406. WideStringManager.Unicode2AnsiMoveProc(S, U2ARes, CodePage, Len);
  1407. if Length(U2ARes) = 0 then
  1408. begin
  1409. Result.Value := nil;
  1410. Exit;
  1411. end;
  1412. { Could instead avoid the second allocation, assuming U2ARes.RefCount = 1:
  1413. System.Move(Pointer(U2ARes)^, (Pointer(U2ARes) - AnsiStringHeaderSize)^, (Length(U2ARes) + 1) * SizeOf(AnsiChar));
  1414. Result.FValue := Pointer(U2ARes) - AnsiStringHeaderSize;
  1415. Pointer(U2ARes) := nil; }
  1416. NBytes := (Length(U2ARes) + 1) * SizeOf(AnsiChar);
  1417. Result.Value := System.GetMem(NBytes);
  1418. System.Move(PAnsiChar(U2ARes)^, Result.Value^, NBytes);
  1419. end;
  1420. class procedure TMarshal.Copy(const Src: TUnicodeCharArray; StartIndex: SizeInt; Dest: TPtrWrapper; Count: SizeInt);
  1421. begin
  1422. System.Move(PUnicodeChar(Src)[StartIndex], Dest.Value^, Count * SizeOf(UnicodeChar));
  1423. end;
  1424. class procedure TMarshal.Copy(Src: TPtrWrapper; var Dest: TUnicodeCharArray; StartIndex: SizeInt; Count: SizeInt);
  1425. begin
  1426. System.Move(Src.Value^, PUnicodeChar(Dest)[StartIndex], Count * SizeOf(UnicodeChar));
  1427. end;
  1428. class function TMarshal.ReadStringAsAnsi(Ptr: TPtrWrapper; Len: SizeInt = -1): UnicodeString;
  1429. begin
  1430. Result := ReadStringAsAnsi(DefaultSystemCodePage, Ptr, Len);
  1431. end;
  1432. class function TMarshal.ReadStringAsAnsi(CodePage: Word; Ptr: TPtrWrapper; Len: SizeInt = -1): UnicodeString;
  1433. begin
  1434. { Here and below, IndexByte/Word assume that, when Len >= 0, either:
  1435. - Up to Len characters are accessible in Ptr;
  1436. - IndexByte/Word cannot access invalid memory past the searched character
  1437. (e.g. i386.inc and x86_64.inc IndexByte/Word versions are specifically designed not to). }
  1438. if Len < 0 then
  1439. Len := IndexByte(Ptr.Value^, Len, 0);
  1440. Result := ''; { Suppress warning. }
  1441. WideStringManager.Ansi2UnicodeMoveProc(Ptr.Value, CodePage, Result, Len);
  1442. end;
  1443. class function TMarshal.ReadStringAsAnsiUpTo(CodePage: Word; Ptr: TPtrWrapper; MaxLen: SizeInt): UnicodeString;
  1444. var
  1445. Len: SizeInt;
  1446. begin
  1447. Len := IndexByte(Ptr.Value^, MaxLen, 0);
  1448. if Len < 0 then
  1449. Len := MaxLen;
  1450. Result := ReadStringAsAnsi(CodePage, Ptr, Len);
  1451. end;
  1452. class procedure TMarshal.WriteStringAsAnsi(Ptr: TPtrWrapper; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1453. begin
  1454. WriteStringAsAnsi(Ptr, 0, Value, MaxCharsIncNull, DefaultSystemCodePage);
  1455. end;
  1456. class procedure TMarshal.WriteStringAsAnsi(Ptr: TPtrWrapper; const Value: UnicodeString; MaxCharsIncNull: SizeInt; CodePage: Word);
  1457. begin
  1458. WriteStringAsAnsi(Ptr, 0, Value, MaxCharsIncNull, CodePage);
  1459. end;
  1460. class procedure TMarshal.WriteStringAsAnsi(Ptr: TPtrWrapper; Ofs: SizeInt; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1461. begin
  1462. WriteStringAsAnsi(Ptr, Ofs, Value, MaxCharsIncNull, DefaultSystemCodePage);
  1463. end;
  1464. class procedure TMarshal.WriteStringAsAnsi(Ptr: TPtrWrapper; Ofs: SizeInt; const Value: UnicodeString; MaxCharsIncNull: SizeInt; CodePage: Word);
  1465. var
  1466. U2ARes: AnsiString;
  1467. ValueLen, U2AResLen: SizeInt;
  1468. begin
  1469. U2ARes := ''; { Suppress warning. }
  1470. ValueLen := Length(Value);
  1471. { Delphi null-terminates iff MaxCharsIncNull < 0, so MaxCharsIncNull is actually just MaxChars. }
  1472. if (MaxCharsIncNull > 0) and (MaxCharsIncNull < ValueLen) then
  1473. ValueLen := MaxCharsIncNull; { UTF-16 → ANSI should never shrink element count, so limit the number of characters analyzed. }
  1474. WideStringManager.Unicode2AnsiMoveProc(PUnicodeChar(Pointer(Value)), U2ARes, CodePage, ValueLen);
  1475. U2AResLen := Length(U2ARes);
  1476. if (MaxCharsIncNull >= 0) and (MaxCharsIncNull < U2AResLen) then
  1477. U2AResLen := MaxCharsIncNull;
  1478. System.Move(PAnsiChar(Pointer(U2ARes))^, (Ptr.Value + Ofs)^, U2AResLen * SizeOf(AnsiChar));
  1479. if MaxCharsIncNull < 0 then
  1480. PAnsiChar(Ptr.Value + Ofs)[U2AResLen] := #0;
  1481. end;
  1482. class function TMarshal.ReadStringAsUnicode(Ptr: TPtrWrapper; Len: SizeInt = -1): UnicodeString;
  1483. begin
  1484. if Len < 0 then
  1485. Len := Length(PUnicodeChar(Ptr.Value));
  1486. Result := ''; { Suppress warning. }
  1487. SetLength(Result, Len);
  1488. System.Move(Ptr.Value^, Pointer(Result)^, Len * SizeOf(UnicodeChar));
  1489. end;
  1490. class function TMarshal.ReadStringAsUnicodeUpTo(Ptr: TPtrWrapper; MaxLen: SizeInt): UnicodeString;
  1491. var
  1492. Len: SizeInt;
  1493. begin
  1494. Len := IndexWord(Ptr.Value^, MaxLen, 0);
  1495. if Len < 0 then
  1496. Len := MaxLen;
  1497. Result := ReadStringAsUnicode(Ptr, Len);
  1498. end;
  1499. class procedure TMarshal.WriteStringAsUnicode(Ptr: TPtrWrapper; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1500. begin
  1501. WriteStringAsUnicode(Ptr, 0, Value, MaxCharsIncNull);
  1502. end;
  1503. class procedure TMarshal.WriteStringAsUnicode(Ptr: TPtrWrapper; Ofs: SizeInt; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1504. var
  1505. Len: SizeInt;
  1506. begin
  1507. { Again, Delphi null-terminates iff MaxCharsIncNull < 0, so MaxCharsIncNull is actually just MaxChars. }
  1508. Len := Length(Value);
  1509. if (MaxCharsIncNull >= 0) and (MaxCharsIncNull < Len) then
  1510. Len := MaxCharsIncNull;
  1511. System.Move(Pointer(Value)^, (Ptr.Value + Ofs)^, Len * SizeOf(UnicodeChar));
  1512. if MaxCharsIncNull < 0 then
  1513. PUnicodeChar(Ptr.Value + Ofs)[Len] := #0;
  1514. end;
  1515. class function TMarshal.ReadStringAsUtf8(Ptr: TPtrWrapper; Len: SizeInt = -1): UnicodeString;
  1516. begin
  1517. Result := ReadStringAsAnsi(CP_UTF8, Ptr, Len);
  1518. end;
  1519. class function TMarshal.ReadStringAsUtf8UpTo(Ptr: TPtrWrapper; MaxLen: SizeInt): UnicodeString;
  1520. begin
  1521. Result := ReadStringAsAnsiUpTo(CP_UTF8, Ptr, MaxLen);
  1522. end;
  1523. class procedure TMarshal.WriteStringAsUtf8(Ptr: TPtrWrapper; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1524. begin
  1525. WriteStringAsAnsi(Ptr, Value, MaxCharsIncNull, CP_UTF8);
  1526. end;
  1527. class procedure TMarshal.WriteStringAsUtf8(Ptr: TPtrWrapper; Ofs: SizeInt; const Value: UnicodeString; MaxCharsIncNull: SizeInt);
  1528. begin
  1529. WriteStringAsAnsi(Ptr, Ofs, Value, MaxCharsIncNull, CP_UTF8);
  1530. end;
  1531. {$ENDIF}