remotemono
RMonoAPI_Impl.h
1 /*
2  Copyright 2020 David "Alemarius Nexus" Lerch
3 
4  This file is part of RemoteMono.
5 
6  RemoteMono is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published
8  by the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  RemoteMono is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with RemoteMono. If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #pragma once
21 
22 #include "../config.h"
23 
24 #include "RMonoAPI_Def.h"
25 
26 #include "mono/metadata/blob.h"
27 #include "mono/metadata/row-indexes.h"
28 #include "mono/metadata/tabledefs.h"
29 #include "../log.h"
30 
31 
32 
33 #define REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(apiname) \
34  do { \
35  apid->apply([&](auto& e) { \
36  checkAPIFunctionSupported(e.api.apiname); \
37  }); \
38  } while (0);
39 
40 
41 
42 
43 namespace remotemono
44 {
45 
46 
47 
48 RMonoAPI::RMonoAPI(blackbone::Process& process)
49  : RMonoAPIBase(process), attached(false)
50 {
51 }
52 
53 
55 {
56  detach();
57 }
58 
59 
61 {
62  if (attached) {
63  return;
64  }
65 
66  static bool versionPrinted = false;
67 
68  if (!versionPrinted) {
69  RMonoLogInfo("RemoteMono version %u.%u.%u", REMOTEMONO_VERSION_MAJOR, REMOTEMONO_VERSION_MINOR, REMOTEMONO_VERSION_PATCH);
70  versionPrinted = true;
71  }
72 
73  RemoteExec& rem = process.remote();
74 
75  rem.CreateRPCEnvironment(Worker_CreateNew, true);
76 
77  worker = rem.getWorker();
78 
79  selectABI();
80 
81  apid->apply([&](auto& e) {
82  e.api.injectAPI(this, process, worker);
83  });
84 
85  attached = true;
86 
87  rootDomain = getRootDomain();
88 
89  monoThread = threadAttach(rootDomain);
90 }
91 
92 
94 {
95  if (!attached) {
96  return;
97  }
98 
99  rmono_gchandle monoThreadGchandle = *monoThread;
100  monoThread.takeOwnership();
101 
102  size_t numRegisteredHandles = registeredHandles.size();
103 
104  if (numRegisteredHandles > 1) {
105  RMonoLogDebug("%llu RemoteMonoHandles still reachable when detaching. Will force-delete them now.",
106  (long long unsigned) (numRegisteredHandles-1));
107  }
108 
109  for (RMonoHandleBackendBase* backend : registeredHandles) {
110  backend->forceDelete();
111  }
112  registeredHandles.clear();
113 
114  threadDetach(monoThread);
115 
116  // TODO: It may be illegal to free the MonoThread's GCHandle (by calling gchandle_free(), as the destructor does) after we've already
117  // detached from the thread. However, freeing it before detaching sounds even worse: That probably gives the GC an opportunity to
118  // collect (or more likely: move) the MonoThread, which would leave us with an invalid MonoThreadPtrRaw so we can't safely detach.
119  // I think this is the less dangerous option, because we likely don't even need to be attached to free a GCHandle.
120  gchandleFree(monoThreadGchandle);
121  monoThread.reset();
122 
123  apid->apply([&](auto& e) {
124  e.api.uninjectAPI();
125  });
126 
127  attached = false;
128 }
129 
130 
132 {
133  return attached;
134 }
135 
136 
137 bool RMonoAPI::isAPIFunctionSupported(const std::string& name) const
138 {
139  return apid->apply([&](auto& e) {
140  return e.api.isAPIFunctionSupported(name);
141  });
142 }
143 
144 
145 void RMonoAPI::selectABI()
146 {
147  SYSTEM_INFO sysinfo;
148  GetNativeSystemInfo(&sysinfo);
149 
150  bool x64;
151 
152  if (sysinfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) {
153  x64 = false;
154  } else {
155  x64 = !process.core().isWow64();
156  }
157 
158  apid->foreach([&](auto& e) {
159  typedef decltype(e.abi) ABI;
160  if (x64 && sizeof(typename ABI::irmono_voidp) == 8) {
161  apid->selectABI<ABI>();
162  } else if (!x64 && sizeof(typename ABI::irmono_voidp) == 4) {
163  apid->selectABI<ABI>();
164  }
165  });
166 
167  assert(apid->hasSelectedABI());
168 
169  apid->apply([&](auto& e) {
170  RMonoLogDebug("Using Mono ABI: %s", typeid(e.abi).name());
171  });
172 }
173 
174 
175 template <typename ABI>
176 blackbone::MemBlock RMonoAPI::prepareIterator()
177 {
178  blackbone::MemBlock rIter = std::move(process.memory().Allocate(sizeof(typename ABI::irmono_voidp), PAGE_READWRITE).result());
179  typename ABI::irmono_voidp nullPtr = 0;
180  rIter.Write(0, sizeof(typename ABI::irmono_voidp), &nullPtr);
181  return std::move(rIter);
182 }
183 
184 
185 void RMonoAPI::checkAttached()
186 {
187  if (!attached) {
188  throw RMonoException("RMonoAPI is not attached.");
189  }
190 }
191 
192 
193 template <typename FuncT>
194 void RMonoAPI::checkAPIFunctionSupported(const FuncT& f)
195 {
196  if (!f) {
197  throw RMonoUnsupportedAPIException(f.getName());
198  }
199 }
200 
201 
202 
203 
204 
205 
206 
207 
208 
209 
210 
211 
212 // **************************************************************************
213 // * *
214 // * MONO API WRAPPERS *
215 // * *
216 // **************************************************************************
217 
218 
219 void RMonoAPI::free(rmono_voidp p)
220 {
221  checkAttached();
222 
223  apid->apply([&](auto& e) {
224  if (e.api.free) {
225  e.api.free(e.abi.p2i_rmono_voidp(p));
226  } else if (e.api.g_free) {
227  e.api.g_free(e.abi.p2i_rmono_voidp(p));
228  } else {
229  throw RMonoUnsupportedAPIException("mono_free");
230  }
231  });
232 }
233 
234 
235 
236 RMonoDomainPtr RMonoAPI::jitInit(const std::string_view& filename)
237 {
238  checkAttached();
239  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(jit_init);
240 
241  return apid->apply([&](auto& e) {
242  return e.abi.i2p_RMonoDomainPtr(e.api.jit_init(filename));
243  });
244 }
245 
246 
247 void RMonoAPI::jitCleanup(RMonoDomainPtr domain)
248 {
249  checkAttached();
250  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(jit_cleanup);
251 
252  apid->apply([&](auto& e) {
253  e.api.jit_cleanup(e.abi.p2i_RMonoDomainPtr(domain));
254  });
255 }
256 
257 
258 
259 RMonoDomainPtr RMonoAPI::getRootDomain()
260 {
261  checkAttached();
262  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_root_domain);
263 
264  return apid->apply([&](auto& e) {
265  return e.abi.i2p_RMonoDomainPtr(e.api.get_root_domain());
266  });
267 }
268 
269 
270 bool RMonoAPI::domainSet(RMonoDomainPtr domain, bool force)
271 {
272  checkAttached();
273  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(domain_set);
274 
275  return (bool) apid->apply([&](auto& e) {
276  return e.abi.i2p_rmono_bool(e.api.domain_set(e.abi.p2i_RMonoDomainPtr(domain), e.abi.p2i_rmono_bool(force ? 1 : 0)));
277  });
278 }
279 
280 
281 RMonoDomainPtr RMonoAPI::domainGet()
282 {
283  checkAttached();
284  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(domain_get);
285 
286  return apid->apply([&](auto& e) {
287  return e.abi.i2p_RMonoDomainPtr(e.api.domain_get());
288  });
289 }
290 
291 
292 std::vector<RMonoDomainPtr> RMonoAPI::domainList()
293 {
294  checkAttached();
295  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(domain_foreach);
296 
297  std::vector<RMonoDomainPtr> out;
298 
299  apid->apply([&](auto& e) {
300  typedef decltype(e.abi) ABI;
301  std::vector<typename ABI::IRMonoDomainPtrRaw> iout;
302  e.api.getIPCVector().vectorClear(e.api.getIPCVectorInstance());
303  e.api.domain_foreach(e.abi.p2i_rmono_funcp((rmono_funcp) e.api.rmono_foreach_ipcvec_adapter.getAddress()),
304  e.abi.p2i_rmono_voidp(e.api.getIPCVectorInstance()));
305  e.api.getIPCVector().read(e.api.getIPCVectorInstance(), iout);
306  for (auto p : iout) {
307  out.push_back(e.abi.hi2p_RMonoDomainPtr(p, this, false));
308  }
309  });
310 
311  return out;
312 }
313 
314 
315 RMonoDomainPtr RMonoAPI::domainCreateAppdomain(const std::string_view& friendlyName, const std::string_view& configFile)
316 {
317  checkAttached();
318  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(domain_create_appdomain);
319 
320  // TODO: Should be able to pass NULL for configFile
321  return apid->apply([&](auto& e) {
322  return e.abi.i2p_RMonoDomainPtr(e.api.domain_create_appdomain(friendlyName, configFile));
323  });
324 }
325 
326 
327 RMonoAssemblyPtr RMonoAPI::domainAssemblyOpen(RMonoDomainPtr domain, const std::string_view& name)
328 {
329  checkAttached();
330  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(domain_assembly_open);
331 
332  return apid->apply([&](auto& e) {
333  return e.abi.i2p_RMonoAssemblyPtr(e.api.domain_assembly_open(e.abi.p2i_RMonoDomainPtr(domain), name));
334  });
335 }
336 
337 
338 void RMonoAPI::domainUnload(RMonoDomainPtr domain)
339 {
340  checkAttached();
341  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(domain_unload);
342 
343  apid->apply([&](auto& e) {
344  e.api.domain_unload(e.abi.p2i_RMonoDomainPtr(domain));
345  });
346 }
347 
348 
349 std::string RMonoAPI::domainGetFriendlyName(RMonoDomainPtr domain)
350 {
351  checkAttached();
352  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(domain_get_friendly_name);
353 
354  return apid->apply([&](auto& e) {
355  return e.api.domain_get_friendly_name(e.abi.p2i_RMonoDomainPtr(domain));
356  });
357 }
358 
359 
360 
361 RMonoThreadPtr RMonoAPI::threadAttach(RMonoDomainPtr domain)
362 {
363  checkAttached();
364  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(thread_attach);
365 
366  return apid->apply([&](auto& e) {
367  return e.abi.i2p_RMonoThreadPtr(e.api.thread_attach(e.abi.p2i_RMonoDomainPtr(domain)));
368  });
369 }
370 
371 
372 void RMonoAPI::threadDetach(RMonoThreadPtr thread)
373 {
374  checkAttached();
375  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(thread_detach);
376 
377  apid->apply([&](auto& e) {
378  e.api.thread_detach(e.abi.p2i_RMonoThreadPtr(thread));
379  });
380 }
381 
382 
383 
384 void RMonoAPI::assemblyClose(RMonoAssemblyPtr assembly)
385 {
386  checkAttached();
387  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(assembly_close);
388 
389  apid->apply([&](auto& e) {
390  e.api.assembly_close(e.abi.p2i_RMonoAssemblyPtr(assembly));
391  });
392 }
393 
394 
395 std::vector<RMonoAssemblyPtr> RMonoAPI::assemblyList()
396 {
397  checkAttached();
398  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(assembly_foreach);
399 
400  std::vector<RMonoAssemblyPtr> out;
401 
402  apid->apply([&](auto& e) {
403  typedef decltype(e.abi) ABI;
404  std::vector<typename ABI::IRMonoAssemblyPtrRaw> iout;
405  e.api.getIPCVector().vectorClear(e.api.getIPCVectorInstance());
406  e.api.assembly_foreach(e.abi.p2i_rmono_funcp((rmono_funcp) e.api.rmono_foreach_ipcvec_adapter.getAddress()),
407  e.abi.p2i_rmono_voidp(e.api.getIPCVectorInstance()));
408  e.api.getIPCVector().read(e.api.getIPCVectorInstance(), iout);
409  for (auto p : iout) {
410  out.push_back(e.abi.hi2p_RMonoDomainPtr(p, this, false));
411  }
412  });
413 
414  return out;
415 }
416 
417 
418 RMonoImagePtr RMonoAPI::assemblyGetImage(RMonoAssemblyPtr assembly)
419 {
420  checkAttached();
421  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(assembly_get_image);
422 
423  return apid->apply([&](auto& e) {
424  return e.abi.i2p_RMonoImagePtr(e.api.assembly_get_image(e.abi.p2i_RMonoAssemblyPtr(assembly)));
425  });
426 }
427 
428 
429 RMonoAssemblyNamePtr RMonoAPI::assemblyGetName(RMonoAssemblyPtr assembly)
430 {
431  checkAttached();
432  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(assembly_get_name);
433 
434  return apid->apply([&](auto& e) {
435  return e.abi.i2p_RMonoAssemblyNamePtr(e.api.assembly_get_name(e.abi.p2i_RMonoAssemblyPtr(assembly)));
436  });
437 }
438 
439 
440 RMonoAssemblyNamePtr RMonoAPI::assemblyNameNew(const std::string_view& name)
441 {
442  checkAttached();
443  //REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(assembly_name_new);
444 
445  return apid->apply([&](auto& e) {
446  if (e.api.assembly_name_new) {
447  return e.abi.i2p_RMonoAssemblyNamePtr(e.api.assembly_name_new(name));
448  } else if (e.api.assembly_name_parse) {
449  blackbone::MemBlock block = std::move(process.memory().Allocate(256, PAGE_READWRITE, 0, false).result());
450  RMonoAssemblyNamePtr aname((RMonoAssemblyNamePtrRaw) block.ptr(), this, true);
451  if (!assemblyNameParse(name, aname)) {
452  block.Free();
453  return RMonoAssemblyNamePtr();
454  }
455  return aname;
456  } else {
457  throw RMonoUnsupportedAPIException("assembly_name_new");
458  }
459  });
460 }
461 
462 
463 bool RMonoAPI::assemblyNameParse(const std::string_view& name, RMonoAssemblyNamePtr aname)
464 {
465  checkAttached();
466  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(assembly_name_parse);
467 
468  return apid->apply([&](auto& e) {
469  return e.abi.i2p_rmono_bool(e.api.assembly_name_parse(name, e.abi.p2i_RMonoAssemblyNamePtr(aname))) != 0;
470  });
471 }
472 
473 
474 void RMonoAPI::assemblyNameFree(RMonoAssemblyNamePtrRaw name)
475 {
476  checkAttached();
477  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(assembly_name_free);
478 
479  apid->apply([&](auto& e) {
480  e.api.assembly_name_free(e.abi.p2i_RMonoAssemblyNamePtrRaw(name));
481  });
482 }
483 
484 
485 std::string RMonoAPI::assemblyNameGetName(RMonoAssemblyNamePtr assembly)
486 {
487  checkAttached();
488  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(assembly_name_get_name);
489 
490  return apid->apply([&](auto& e) {
491  return e.api.assembly_name_get_name(e.abi.p2i_RMonoAssemblyNamePtr(assembly));
492  });
493 }
494 
495 
496 std::string RMonoAPI::assemblyNameGetCulture(RMonoAssemblyNamePtr assembly)
497 {
498  checkAttached();
499  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(assembly_name_get_culture);
500 
501  return apid->apply([&](auto& e) {
502  return e.api.assembly_name_get_culture(e.abi.p2i_RMonoAssemblyNamePtr(assembly));
503  });
504 }
505 
506 
507 uint16_t RMonoAPI::assemblyNameGetVersion(RMonoAssemblyNamePtr assembly, uint16_t* minor, uint16_t* build, uint16_t* revision)
508 {
509  checkAttached();
510  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(assembly_name_get_version);
511 
512  return apid->apply([&](auto& e) {
513  return e.api.assembly_name_get_version(e.abi.p2i_RMonoAssemblyNamePtr(assembly), minor, build, revision);
514  });
515 }
516 
517 
518 std::string RMonoAPI::stringifyAssemblyName(RMonoAssemblyNamePtr assembly)
519 {
520  checkAttached();
521  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(stringify_assembly_name);
522 
523  return apid->apply([&](auto& e) {
524  return e.api.stringify_assembly_name(e.abi.p2i_RMonoAssemblyNamePtr(assembly));
525  });
526 }
527 
528 
529 std::string RMonoAPI::assemblyNameStringify(RMonoAssemblyNamePtr assembly)
530 {
531  return stringifyAssemblyName(assembly);
532 }
533 
534 
535 RMonoAssemblyPtr RMonoAPI::assemblyLoaded(RMonoAssemblyNamePtr name)
536 {
537  checkAttached();
538  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(assembly_loaded);
539 
540  return apid->apply([&](auto& e) {
541  return e.abi.i2p_RMonoAssemblyPtr(e.api.assembly_loaded(e.abi.p2i_RMonoAssemblyNamePtr(name)));
542  });
543 }
544 
545 
546 RMonoAssemblyPtr RMonoAPI::assemblyLoaded(const std::string_view& name)
547 {
548  return assemblyLoaded(assemblyNameNew(name));
549 }
550 
551 
552 
553 std::string RMonoAPI::imageGetName(RMonoImagePtr image)
554 {
555  checkAttached();
556  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(image_get_name);
557 
558  return apid->apply([&](auto& e) {
559  return e.api.image_get_name(e.abi.p2i_RMonoImagePtr(image));
560  });
561 }
562 
563 
564 std::string RMonoAPI::imageGetFilename(RMonoImagePtr image)
565 {
566  checkAttached();
567  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(image_get_filename);
568 
569  return apid->apply([&](auto& e) {
570  return e.api.image_get_filename(e.abi.p2i_RMonoImagePtr(image));
571  });
572 }
573 
574 
575 RMonoTableInfoPtr RMonoAPI::imageGetTableInfo(RMonoImagePtr image, rmono_int tableID)
576 {
577  checkAttached();
578  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(image_get_table_info);
579 
580  return apid->apply([&](auto& e) {
581  return e.abi.i2p_RMonoTableInfoPtr(e.api.image_get_table_info(e.abi.p2i_RMonoImagePtr(image), e.abi.p2i_rmono_int(tableID)));
582  });
583 }
584 
585 
586 rmono_int RMonoAPI::tableInfoGetRows(RMonoTableInfoPtr table)
587 {
588  checkAttached();
589  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(table_info_get_rows);
590 
591  return apid->apply([&](auto& e) {
592  return e.abi.i2p_rmono_int(e.api.table_info_get_rows(e.abi.p2i_RMonoTableInfoPtr(table)));
593  });
594 }
595 
596 
597 rmono_voidp RMonoAPI::imageRVAMap(RMonoImagePtr image, uint32_t addr)
598 {
599  checkAttached();
600  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(image_rva_map);
601 
602  return apid->apply([&](auto& e) {
603  return e.abi.i2p_rmono_voidp(e.api.image_rva_map(e.abi.p2i_RMonoImagePtr(image), addr));
604  });
605 }
606 
607 
608 
609 uint32_t RMonoAPI::metadataDecodeRowCol(RMonoTableInfoPtr table, rmono_int idx, rmono_uint col)
610 {
611  checkAttached();
612  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(metadata_decode_row_col);
613 
614  return apid->apply([&](auto& e) {
615  return e.api.metadata_decode_row_col(e.abi.p2i_RMonoTableInfoPtr(table), e.abi.p2i_rmono_int(idx), e.abi.p2i_rmono_uint(col));
616  });
617 }
618 
619 
620 rmono_voidp RMonoAPI::metadataGuidHeap(RMonoImagePtr image, uint32_t idx, uint8_t* outGuid)
621 {
622  checkAttached();
623  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(metadata_guid_heap);
624 
625  rmono_voidp p = apid->apply([&](auto& e) {
626  return e.abi.i2p_rmono_voidp(e.api.metadata_guid_heap(e.abi.p2i_RMonoImagePtr(image), idx));
627  });
628 
629  if (outGuid) {
630  process.memory().Read((blackbone::ptr_t) p, 16, outGuid);
631  }
632 
633  return p;
634 }
635 
636 
637 std::string RMonoAPI::metadataStringHeap(RMonoImagePtr image, uint32_t idx)
638 {
639  checkAttached();
640  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(metadata_string_heap);
641 
642  return apid->apply([&](auto& e) {
643  return e.api.metadata_string_heap(e.abi.p2i_RMonoImagePtr(image), idx);
644  });
645 }
646 
647 
648 rmono_voidp RMonoAPI::metadataStringHeapRaw(RMonoImagePtr image, uint32_t idx)
649 {
650  checkAttached();
651  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(metadata_string_heap);
652 
653  return apid->apply([&](auto& e) {
654  return e.abi.i2p_rmono_voidp(e.api.metadata_string_heap.invokeRaw(e.abi.p2i_RMonoImagePtrRaw(*image), idx));
655  });
656 }
657 
658 
659 rmono_voidp RMonoAPI::metadataBlobHeap(RMonoImagePtr image, uint32_t idx)
660 {
661  checkAttached();
662  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(metadata_blob_heap);
663 
664  return apid->apply([&](auto& e) {
665  return e.abi.i2p_rmono_voidp(e.api.metadata_blob_heap(e.abi.p2i_RMonoImagePtr(image), idx));
666  });
667 }
668 
669 
670 std::string RMonoAPI::metadataUserString(RMonoImagePtr image, uint32_t idx)
671 {
672  checkAttached();
673  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(metadata_user_string);
674 
675  return apid->apply([&](auto& e) {
676  return e.api.metadata_user_string(e.abi.p2i_RMonoImagePtr(image), idx);
677  });
678 }
679 
680 
681 rmono_voidp RMonoAPI::metadataUserStringRaw(RMonoImagePtr image, uint32_t idx)
682 {
683  checkAttached();
684  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(metadata_user_string);
685 
686  return apid->apply([&](auto& e) {
687  return e.abi.i2p_rmono_voidp(e.api.metadata_user_string.invokeRaw(e.abi.p2i_RMonoImagePtrRaw(*image), idx));
688  });
689 }
690 
691 
692 uint32_t RMonoAPI::metadataDecodeBlobSize(rmono_voidp blobPtr, rmono_voidp* outBlobPtr)
693 {
694  checkAttached();
695  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(metadata_decode_blob_size);
696 
697  return apid->apply([&](auto& e) {
698  typedef typename decltype(e.abi)::irmono_voidp irmono_voidp;
699 
700  irmono_voidp ip;
701  uint32_t size = e.api.metadata_decode_blob_size(e.abi.p2i_rmono_voidp(blobPtr), &ip);
702 
703  *outBlobPtr = e.abi.i2p_rmono_voidp(ip);
704  return size;
705  });
706 }
707 
708 
709 
710 RMonoClassPtr RMonoAPI::getObjectClass()
711 {
712  checkAttached();
713  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_object_class);
714 
715  return apid->apply([&](auto& e) {
716  return e.abi.i2p_RMonoClassPtr(e.api.get_object_class());
717  });
718 }
719 
720 
721 RMonoClassPtr RMonoAPI::getInt16Class()
722 {
723  checkAttached();
724  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_int16_class);
725 
726  return apid->apply([&](auto& e) {
727  return e.abi.i2p_RMonoClassPtr(e.api.get_int16_class());
728  });
729 }
730 
731 
732 RMonoClassPtr RMonoAPI::getInt32Class()
733 {
734  checkAttached();
735  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_int32_class);
736 
737  return apid->apply([&](auto& e) {
738  return e.abi.i2p_RMonoClassPtr(e.api.get_int32_class());
739  });
740 }
741 
742 
743 RMonoClassPtr RMonoAPI::getInt64Class()
744 {
745  checkAttached();
746  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_int64_class);
747 
748  return apid->apply([&](auto& e) {
749  return e.abi.i2p_RMonoClassPtr(e.api.get_int64_class());
750  });
751 }
752 
753 
754 RMonoClassPtr RMonoAPI::getDoubleClass()
755 {
756  checkAttached();
757  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_double_class);
758 
759  return apid->apply([&](auto& e) {
760  return e.abi.i2p_RMonoClassPtr(e.api.get_double_class());
761  });
762 }
763 
764 
765 RMonoClassPtr RMonoAPI::getSingleClass()
766 {
767  checkAttached();
768  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_single_class);
769 
770  return apid->apply([&](auto& e) {
771  return e.abi.i2p_RMonoClassPtr(e.api.get_single_class());
772  });
773 }
774 
775 
776 RMonoClassPtr RMonoAPI::getStringClass()
777 {
778  checkAttached();
779  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_string_class);
780 
781  return apid->apply([&](auto& e) {
782  return e.abi.i2p_RMonoClassPtr(e.api.get_string_class());
783  });
784 }
785 
786 
787 RMonoClassPtr RMonoAPI::getThreadClass()
788 {
789  checkAttached();
790  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_thread_class);
791 
792  return apid->apply([&](auto& e) {
793  return e.abi.i2p_RMonoClassPtr(e.api.get_thread_class());
794  });
795 }
796 
797 
798 RMonoClassPtr RMonoAPI::getUInt16Class()
799 {
800  checkAttached();
801  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_uint16_class);
802 
803  return apid->apply([&](auto& e) {
804  return e.abi.i2p_RMonoClassPtr(e.api.get_uint16_class());
805  });
806 }
807 
808 
809 RMonoClassPtr RMonoAPI::getUInt32Class()
810 {
811  checkAttached();
812  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_uint32_class);
813 
814  return apid->apply([&](auto& e) {
815  return e.abi.i2p_RMonoClassPtr(e.api.get_uint32_class());
816  });
817 }
818 
819 
820 RMonoClassPtr RMonoAPI::getUInt64Class()
821 {
822  checkAttached();
823  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_uint64_class);
824 
825  return apid->apply([&](auto& e) {
826  return e.abi.i2p_RMonoClassPtr(e.api.get_uint64_class());
827  });
828 }
829 
830 
831 RMonoClassPtr RMonoAPI::getVoidClass()
832 {
833  checkAttached();
834  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_void_class);
835 
836  return apid->apply([&](auto& e) {
837  return e.abi.i2p_RMonoClassPtr(e.api.get_void_class());
838  });
839 }
840 
841 
842 RMonoClassPtr RMonoAPI::getArrayClass()
843 {
844  checkAttached();
845  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_array_class);
846 
847  return apid->apply([&](auto& e) {
848  return e.abi.i2p_RMonoClassPtr(e.api.get_array_class());
849  });
850 }
851 
852 
853 RMonoClassPtr RMonoAPI::getBooleanClass()
854 {
855  checkAttached();
856  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_boolean_class);
857 
858  return apid->apply([&](auto& e) {
859  return e.abi.i2p_RMonoClassPtr(e.api.get_boolean_class());
860  });
861 }
862 
863 
864 RMonoClassPtr RMonoAPI::getByteClass()
865 {
866  checkAttached();
867  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_byte_class);
868 
869  return apid->apply([&](auto& e) {
870  return e.abi.i2p_RMonoClassPtr(e.api.get_byte_class());
871  });
872 }
873 
874 
875 RMonoClassPtr RMonoAPI::getSByteClass()
876 {
877  checkAttached();
878  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_sbyte_class);
879 
880  return apid->apply([&](auto& e) {
881  return e.abi.i2p_RMonoClassPtr(e.api.get_sbyte_class());
882  });
883 }
884 
885 
886 RMonoClassPtr RMonoAPI::getCharClass()
887 {
888  checkAttached();
889  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_char_class);
890 
891  return apid->apply([&](auto& e) {
892  return e.abi.i2p_RMonoClassPtr(e.api.get_char_class());
893  });
894 }
895 
896 
897 RMonoClassPtr RMonoAPI::getExceptionClass()
898 {
899  checkAttached();
900  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(get_exception_class);
901 
902  return apid->apply([&](auto& e) {
903  return e.abi.i2p_RMonoClassPtr(e.api.get_exception_class());
904  });
905 }
906 
907 
908 
909 RMonoVTablePtr RMonoAPI::classVTable(RMonoDomainPtr domain, RMonoClassPtr cls)
910 {
911  checkAttached();
912  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_vtable);
913 
914  return apid->apply([&](auto& e) {
915  return e.abi.i2p_RMonoVTablePtr(e.api.class_vtable(e.abi.p2i_RMonoDomainPtr(domain), e.abi.p2i_RMonoClassPtr(cls)));
916  });
917 }
918 
919 
920 RMonoVTablePtr RMonoAPI::classVTable(RMonoClassPtr cls)
921 {
922  return classVTable(domainGet(), cls);
923 }
924 
925 
926 void RMonoAPI::runtimeClassInit(RMonoVTablePtr vtable)
927 {
928  checkAttached();
929  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(runtime_class_init);
930 
931  apid->apply([&](auto& e) {
932  e.api.runtime_class_init(e.abi.p2i_RMonoVTablePtr(vtable));
933  });
934 }
935 
936 
937 RMonoClassPtr RMonoAPI::classGetParent(RMonoClassPtr cls)
938 {
939  checkAttached();
940  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_get_parent);
941 
942  return apid->apply([&](auto& e) {
943  return e.abi.i2p_RMonoClassPtr(e.api.class_get_parent(e.abi.p2i_RMonoClassPtr(cls)));
944  });
945 }
946 
947 
948 RMonoTypePtr RMonoAPI::classGetType(RMonoClassPtr cls)
949 {
950  checkAttached();
951  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_get_type);
952 
953  return apid->apply([&](auto& e) {
954  return e.abi.i2p_RMonoTypePtr(e.api.class_get_type(e.abi.p2i_RMonoClassPtr(cls)));
955  });
956 }
957 
958 
959 RMonoClassPtr RMonoAPI::classFromName(RMonoImagePtr image, const std::string_view& nameSpace, const std::string_view& name)
960 {
961  checkAttached();
962  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_from_name);
963 
964  return apid->apply([&](auto& e) {
965  return e.abi.i2p_RMonoClassPtr(e.api.class_from_name(e.abi.p2i_RMonoImagePtr(image), nameSpace, name));
966  });
967 }
968 
969 
970 RMonoClassPtr RMonoAPI::classFromMonoType(RMonoTypePtr type)
971 {
972  checkAttached();
973  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_from_mono_type);
974 
975  return apid->apply([&](auto& e) {
976  return e.abi.i2p_RMonoClassPtr(e.api.class_from_mono_type(e.abi.p2i_RMonoTypePtr(type)));
977  });
978 }
979 
980 
981 std::string RMonoAPI::classGetName(RMonoClassPtr cls)
982 {
983  checkAttached();
984  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_get_name);
985 
986  return apid->apply([&](auto& e) {
987  return e.api.class_get_name(e.abi.p2i_RMonoClassPtr(cls));
988  });
989 }
990 
991 
992 std::string RMonoAPI::classGetNamespace(RMonoClassPtr cls)
993 {
994  checkAttached();
995  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_get_namespace);
996 
997  return apid->apply([&](auto& e) {
998  return e.api.class_get_namespace(e.abi.p2i_RMonoClassPtr(cls));
999  });
1000 }
1001 
1002 
1003 std::vector<RMonoClassFieldPtr> RMonoAPI::classGetFields(RMonoClassPtr cls)
1004 {
1005  checkAttached();
1006  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_get_fields);
1007 
1008  std::vector<RMonoClassFieldPtr> out;
1009 
1010  apid->apply([&](auto& e) {
1011  typedef decltype(e.abi) ABI;
1012 
1013  blackbone::MemBlock rIter = prepareIterator<ABI>();
1014  typename ABI::irmono_voidpp iptr = (typename ABI::irmono_voidpp) rIter.ptr();
1015 
1016  typename ABI::IRMonoClassFieldPtr field;
1017  typename ABI::IRMonoClassPtr icls = e.abi.p2i_RMonoClassPtr(cls);
1018 
1019  do {
1020  field = e.api.class_get_fields(icls, iptr);
1021  if (field) {
1022  out.push_back(e.abi.i2p_RMonoClassFieldPtr(field));
1023  }
1024  } while (field);
1025  });
1026 
1027  return out;
1028 }
1029 
1030 
1031 std::vector<RMonoMethodPtr> RMonoAPI::classGetMethods(RMonoClassPtr cls)
1032 {
1033  checkAttached();
1034  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_get_methods);
1035 
1036  std::vector<RMonoMethodPtr> out;
1037 
1038  apid->apply([&](auto& e) {
1039  typedef decltype(e.abi) ABI;
1040 
1041  blackbone::MemBlock rIter = prepareIterator<ABI>();
1042  typename ABI::irmono_voidpp iptr = (typename ABI::irmono_voidpp) rIter.ptr();
1043 
1044  typename ABI::IRMonoMethodPtr method;
1045  typename ABI::IRMonoClassPtr icls = e.abi.p2i_RMonoClassPtr(cls);
1046 
1047  do {
1048  method = e.api.class_get_methods(icls, iptr);
1049  if (method) {
1050  out.push_back(e.abi.i2p_RMonoMethodPtr(method));
1051  }
1052  } while (method);
1053  });
1054 
1055  return out;
1056 }
1057 
1058 
1059 std::vector<RMonoPropertyPtr> RMonoAPI::classGetProperties(RMonoClassPtr cls)
1060 {
1061  checkAttached();
1062  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_get_properties);
1063 
1064  std::vector<RMonoPropertyPtr> out;
1065 
1066  apid->apply([&](auto& e) {
1067  typedef decltype(e.abi) ABI;
1068 
1069  blackbone::MemBlock rIter = prepareIterator<ABI>();
1070  typename ABI::irmono_voidpp iptr = (typename ABI::irmono_voidpp) rIter.ptr();
1071 
1072  typename ABI::IRMonoPropertyPtr prop;
1073  typename ABI::IRMonoClassPtr icls = e.abi.p2i_RMonoClassPtr(cls);
1074 
1075  do {
1076  prop = e.api.class_get_properties(icls, iptr);
1077  if (prop) {
1078  out.push_back(e.abi.i2p_RMonoPropertyPtr(prop));
1079  }
1080  } while (prop);
1081  });
1082 
1083  return out;
1084 }
1085 
1086 
1087 RMonoClassFieldPtr RMonoAPI::classGetFieldFromName(RMonoClassPtr cls, const std::string_view& name)
1088 {
1089  checkAttached();
1090  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_get_field_from_name);
1091 
1092  return apid->apply([&](auto& e) {
1093  return e.abi.i2p_RMonoClassFieldPtr(e.api.class_get_field_from_name(e.abi.p2i_RMonoClassPtr(cls), name));
1094  });
1095 }
1096 
1097 
1098 RMonoMethodPtr RMonoAPI::classGetMethodFromName(RMonoClassPtr cls, const std::string_view& name, int32_t paramCount)
1099 {
1100  checkAttached();
1101  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_get_method_from_name);
1102 
1103  return apid->apply([&](auto& e) {
1104  return e.abi.i2p_RMonoMethodPtr(e.api.class_get_method_from_name(e.abi.p2i_RMonoClassPtr(cls), name, paramCount));
1105  });
1106 }
1107 
1108 
1109 RMonoPropertyPtr RMonoAPI::classGetPropertyFromName(RMonoClassPtr cls, const std::string_view& name)
1110 {
1111  checkAttached();
1112  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_get_property_from_name);
1113 
1114  return apid->apply([&](auto& e) {
1115  return e.abi.i2p_RMonoPropertyPtr(e.api.class_get_property_from_name(e.abi.p2i_RMonoClassPtr(cls), name));
1116  });
1117 }
1118 
1119 
1120 RMonoClassPtr RMonoAPI::classGetElementClass(RMonoClassPtr cls)
1121 {
1122  checkAttached();
1123  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_get_element_class);
1124 
1125  return apid->apply([&](auto& e) {
1126  return e.abi.i2p_RMonoClassPtr(e.api.class_get_element_class(e.abi.p2i_RMonoClassPtr(cls)));
1127  });
1128 }
1129 
1130 
1131 uint32_t RMonoAPI::classGetFlags(RMonoClassPtr cls)
1132 {
1133  checkAttached();
1134  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_get_flags);
1135 
1136  return apid->apply([&](auto& e) {
1137  return e.api.class_get_flags(e.abi.p2i_RMonoClassPtr(cls));
1138  });
1139 }
1140 
1141 
1142 rmono_int RMonoAPI::classGetRank(RMonoClassPtr cls)
1143 {
1144  checkAttached();
1145  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_get_rank);
1146 
1147  return apid->apply([&](auto& e) {
1148  return e.abi.i2p_rmono_int(e.api.class_get_rank(e.abi.p2i_RMonoClassPtr(cls)));
1149  });
1150 }
1151 
1152 
1153 bool RMonoAPI::classIsValueType(RMonoClassPtr cls)
1154 {
1155  checkAttached();
1156  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_is_valuetype);
1157 
1158  return apid->apply([&](auto& e) {
1159  return e.abi.i2p_rmono_bool(e.api.class_is_valuetype(e.abi.p2i_RMonoClassPtr(cls))) != 0;
1160  });
1161 }
1162 
1163 
1164 uint32_t RMonoAPI::classDataSize(RMonoClassPtr cls)
1165 {
1166  checkAttached();
1167  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_data_size);
1168 
1169  return apid->apply([&](auto& e) {
1170  return e.api.class_data_size(e.abi.p2i_RMonoClassPtr(cls));
1171  });
1172 }
1173 
1174 
1175 uint32_t RMonoAPI::classInstanceSize(RMonoClassPtr cls)
1176 {
1177  checkAttached();
1178  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_instance_size);
1179 
1180  return apid->apply([&](auto& e) {
1181  return e.api.class_instance_size(e.abi.p2i_RMonoClassPtr(cls));
1182  });
1183 }
1184 
1185 
1186 int32_t RMonoAPI::classValueSize(RMonoClassPtr cls, uint32_t* align)
1187 {
1188  checkAttached();
1189  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_value_size);
1190 
1191  return apid->apply([&](auto& e) {
1192  return e.api.class_value_size(e.abi.p2i_RMonoClassPtr(cls), align);
1193  });
1194 }
1195 
1196 
1197 
1198 RMonoReflectionTypePtr RMonoAPI::typeGetObject(RMonoDomainPtr domain, RMonoTypePtr type)
1199 {
1200  checkAttached();
1201  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(type_get_object);
1202 
1203  return apid->apply([&](auto& e) {
1204  return e.abi.i2p_RMonoReflectionTypePtr(e.api.type_get_object(e.abi.p2i_RMonoDomainPtr(domain), e.abi.p2i_RMonoTypePtr(type)));
1205  });
1206 }
1207 
1208 
1209 RMonoReflectionTypePtr RMonoAPI::typeGetObject(RMonoTypePtr type)
1210 {
1211  return typeGetObject(domainGet(), type);
1212 }
1213 
1214 
1215 std::string RMonoAPI::typeGetName(RMonoTypePtr type)
1216 {
1217  checkAttached();
1218  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(type_get_name);
1219 
1220  return apid->apply([&](auto& e) {
1221  return e.api.type_get_name(e.abi.p2i_RMonoTypePtr(type));
1222  });
1223 }
1224 
1225 
1226 RMonoClassPtr RMonoAPI::typeGetClass(RMonoTypePtr type)
1227 {
1228  checkAttached();
1229  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(type_get_class);
1230 
1231  return apid->apply([&](auto& e) {
1232  return e.abi.i2p_RMonoClassPtr(e.api.type_get_class(e.abi.p2i_RMonoTypePtr(type)));
1233  });
1234 }
1235 
1236 
1237 rmono_int RMonoAPI::typeGetType(RMonoTypePtr type)
1238 {
1239  checkAttached();
1240  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(type_get_type);
1241 
1242  return apid->apply([&](auto& e) {
1243  return e.abi.i2p_rmono_int(e.api.type_get_type(e.abi.p2i_RMonoTypePtr(type)));
1244  });
1245 }
1246 
1247 
1248 bool RMonoAPI::typeIsByRef(RMonoTypePtr type)
1249 {
1250  checkAttached();
1251  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(type_is_byref);
1252 
1253  return apid->apply([&](auto& e) {
1254  return e.abi.i2p_rmono_bool(e.api.type_is_byref(e.abi.p2i_RMonoTypePtr(type))) != 0;
1255  });
1256 }
1257 
1258 
1259 bool RMonoAPI::typeIsPointer(RMonoTypePtr type)
1260 {
1261  checkAttached();
1262  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(type_is_pointer);
1263 
1264  return apid->apply([&](auto& e) {
1265  return e.abi.i2p_rmono_bool(e.api.type_is_pointer(e.abi.p2i_RMonoTypePtr(type))) != 0;
1266  });
1267 }
1268 
1269 
1270 bool RMonoAPI::typeIsReference(RMonoTypePtr type)
1271 {
1272  checkAttached();
1273  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(type_is_reference);
1274 
1275  return apid->apply([&](auto& e) {
1276  return e.abi.i2p_rmono_bool(e.api.type_is_reference(e.abi.p2i_RMonoTypePtr(type))) != 0;
1277  });
1278 }
1279 
1280 
1281 bool RMonoAPI::typeIsStruct(RMonoTypePtr type)
1282 {
1283  checkAttached();
1284  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(type_is_struct);
1285 
1286  return apid->apply([&](auto& e) {
1287  return e.abi.i2p_rmono_bool(e.api.type_is_struct(e.abi.p2i_RMonoTypePtr(type))) != 0;
1288  });
1289 }
1290 
1291 
1292 bool RMonoAPI::typeIsVoid(RMonoTypePtr type)
1293 {
1294  checkAttached();
1295  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(type_is_void);
1296 
1297  return apid->apply([&](auto& e) {
1298  return e.abi.i2p_rmono_bool(e.api.type_is_void(e.abi.p2i_RMonoTypePtr(type))) != 0;
1299  });
1300 }
1301 
1302 
1303 rmono_int RMonoAPI::typeSize(RMonoTypePtr type, rmono_int* align)
1304 {
1305  checkAttached();
1306  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(type_size);
1307 
1308  return apid->apply([&](auto& e) {
1309  typedef typename decltype(e.abi)::irmono_int irmono_int;
1310  irmono_int ialign;
1311  rmono_int size = e.abi.i2p_rmono_int(e.api.type_size(e.abi.p2i_RMonoTypePtr(type), &ialign));
1312  if (align) {
1313  *align = e.abi.i2p_rmono_int(ialign);
1314  }
1315  return size;
1316  });
1317 }
1318 
1319 
1320 rmono_int RMonoAPI::typeStackSize(RMonoTypePtr type, rmono_int* align)
1321 {
1322  checkAttached();
1323  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(type_stack_size);
1324 
1325  return apid->apply([&](auto& e) {
1326  typedef typename decltype(e.abi)::irmono_int irmono_int;
1327  irmono_int ialign;
1328  rmono_int size = e.abi.i2p_rmono_int(e.api.type_stack_size(e.abi.p2i_RMonoTypePtr(type), &ialign));
1329  if (align) {
1330  *align = e.abi.i2p_rmono_int(ialign);
1331  }
1332  return size;
1333  });
1334 }
1335 
1336 
1337 
1338 RMonoClassPtr RMonoAPI::fieldGetParent(RMonoClassFieldPtr field)
1339 {
1340  checkAttached();
1341  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(field_get_parent);
1342 
1343  return apid->apply([&](auto& e) {
1344  return e.abi.i2p_RMonoClassPtr(e.api.field_get_parent(e.abi.p2i_RMonoClassFieldPtr(field)));
1345  });
1346 }
1347 
1348 
1349 RMonoTypePtr RMonoAPI::fieldGetType(RMonoClassFieldPtr field)
1350 {
1351  checkAttached();
1352  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(field_get_type);
1353 
1354  return apid->apply([&](auto& e) {
1355  return e.abi.i2p_RMonoTypePtr(e.api.field_get_type(e.abi.p2i_RMonoClassFieldPtr(field)));
1356  });
1357 }
1358 
1359 
1360 std::string RMonoAPI::fieldGetName(RMonoClassFieldPtr field)
1361 {
1362  checkAttached();
1363  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(field_get_name);
1364 
1365  return apid->apply([&](auto& e) {
1366  return e.api.field_get_name(e.abi.p2i_RMonoClassFieldPtr(field));
1367  });
1368 }
1369 
1370 
1371 uint32_t RMonoAPI::fieldGetFlags(RMonoClassFieldPtr field)
1372 {
1373  checkAttached();
1374  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(field_get_flags);
1375 
1376  return apid->apply([&](auto& e) {
1377  return e.api.field_get_flags(e.abi.p2i_RMonoClassFieldPtr(field));
1378  });
1379 }
1380 
1381 
1382 void RMonoAPI::fieldSetValue(RMonoObjectPtr obj, RMonoClassFieldPtr field, const RMonoVariant& val)
1383 {
1384  checkAttached();
1385  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(field_set_value);
1386 
1387  apid->apply([&](auto& e) {
1388  if (obj) {
1389  e.api.field_set_value(e.abi.p2i_RMonoObjectPtr(obj), e.abi.p2i_RMonoClassFieldPtr(field), val);
1390  } else {
1391  RMonoClassPtr cls = fieldGetParent(field);
1392  RMonoVTablePtr vtable = classVTable(domainGet(), cls);
1393  fieldStaticSetValue(vtable, field, val);
1394  }
1395  });
1396 }
1397 
1398 
1399 void RMonoAPI::fieldGetValue(RMonoObjectPtr obj, RMonoClassFieldPtr field, RMonoVariant& val)
1400 {
1401  checkAttached();
1402  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(field_get_value);
1403 
1404  return apid->apply([&](auto& e) {
1405  if (obj) {
1406  e.api.field_get_value(e.abi.p2i_RMonoObjectPtr(obj), e.abi.p2i_RMonoClassFieldPtr(field), val);
1407  } else {
1408  RMonoClassPtr cls = fieldGetParent(field);
1409  RMonoVTablePtr vtable = classVTable(domainGet(), cls);
1410  fieldStaticGetValue(vtable, field, val);
1411  }
1412  });
1413 }
1414 
1415 
1416 void RMonoAPI::fieldGetValue(RMonoObjectPtr obj, RMonoClassFieldPtr field, RMonoVariant&& val)
1417 {
1418  fieldGetValue(obj, field, val);
1419 }
1420 
1421 
1422 template <typename T>
1423 T RMonoAPI::fieldGetValue(RMonoObjectPtr obj, RMonoClassFieldPtr field)
1424 {
1425  T val = T();
1426  if constexpr(std::is_base_of_v<RMonoObjectHandleTag, T>) {
1427  fieldGetValue(obj, field, &val);
1428  } else {
1429  fieldGetValue(obj, field, RMonoVariant(&val));
1430  }
1431  return val;
1432 }
1433 
1434 
1435 RMonoObjectPtr RMonoAPI::fieldGetValueObject(RMonoDomainPtr domain, RMonoClassFieldPtr field, RMonoObjectPtr obj)
1436 {
1437  checkAttached();
1438  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(field_get_value_object);
1439 
1440  return apid->apply([&](auto& e) {
1441  return e.abi.i2p_RMonoObjectPtr(e.api.field_get_value_object (
1442  e.abi.p2i_RMonoDomainPtr(domain),
1443  e.abi.p2i_RMonoClassFieldPtr(field),
1444  e.abi.p2i_RMonoObjectPtr(obj)
1445  ));
1446  });
1447 }
1448 
1449 
1450 RMonoObjectPtr RMonoAPI::fieldGetValueObject(RMonoClassFieldPtr field, RMonoObjectPtr obj)
1451 {
1452  return fieldGetValueObject(domainGet(), field, obj);
1453 }
1454 
1455 
1456 void RMonoAPI::fieldStaticSetValue(RMonoVTablePtr vtable, RMonoClassFieldPtr field, const RMonoVariant& val)
1457 {
1458  checkAttached();
1459  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(field_static_set_value);
1460 
1461  apid->apply([&](auto& e) {
1462  e.api.field_static_set_value(e.abi.p2i_RMonoVTablePtr(vtable), e.abi.p2i_RMonoClassFieldPtr(field), val);
1463  });
1464 }
1465 
1466 
1467 void RMonoAPI::fieldStaticGetValue(RMonoVTablePtr vtable, RMonoClassFieldPtr field, RMonoVariant& val)
1468 {
1469  checkAttached();
1470  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(field_static_get_value);
1471 
1472  apid->apply([&](auto& e) {
1473  e.api.field_static_get_value(e.abi.p2i_RMonoVTablePtr(vtable), e.abi.p2i_RMonoClassFieldPtr(field), val);
1474  });
1475 }
1476 
1477 
1478 void RMonoAPI::fieldStaticGetValue(RMonoVTablePtr vtable, RMonoClassFieldPtr field, RMonoVariant&& val)
1479 {
1480  fieldStaticGetValue(vtable, field, val);
1481 }
1482 
1483 
1484 template <typename T>
1485 T RMonoAPI::fieldStaticGetValue(RMonoVTablePtr vtable, RMonoClassFieldPtr field)
1486 {
1487  T val = T();
1488  if constexpr(std::is_base_of_v<RMonoObjectHandleTag, T>) {
1489  fieldStaticGetValue(vtable, field, &val);
1490  } else {
1491  fieldStaticGetValue(vtable, field, RMonoVariant(&val));
1492  }
1493  return val;
1494 }
1495 
1496 
1497 uint32_t RMonoAPI::fieldGetOffset(RMonoClassFieldPtr field)
1498 {
1499  checkAttached();
1500  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(field_get_offset);
1501 
1502  return apid->apply([&](auto& e) {
1503  return e.api.field_get_offset(e.abi.p2i_RMonoClassFieldPtr(field));
1504  });
1505 }
1506 
1507 
1508 
1509 RMonoClassPtr RMonoAPI::methodGetClass(RMonoMethodPtr method)
1510 {
1511  checkAttached();
1512  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(method_get_class);
1513 
1514  return apid->apply([&](auto& e) {
1515  return e.abi.i2p_RMonoClassPtr(e.api.method_get_class(e.abi.p2i_RMonoMethodPtr(method)));
1516  });
1517 }
1518 
1519 
1520 std::string RMonoAPI::methodGetName(RMonoMethodPtr method)
1521 {
1522  checkAttached();
1523  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(method_get_name);
1524 
1525  return apid->apply([&](auto& e) {
1526  return e.api.method_get_name(e.abi.p2i_RMonoMethodPtr(method));
1527  });
1528 }
1529 
1530 
1531 std::string RMonoAPI::methodFullName(RMonoMethodPtr method, bool signature)
1532 {
1533  checkAttached();
1534  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(method_full_name);
1535 
1536  return apid->apply([&](auto& e) {
1537  return e.api.method_full_name(e.abi.p2i_RMonoMethodPtr(method), e.abi.p2i_rmono_bool(signature ? 1 : 0));
1538  });
1539 }
1540 
1541 
1542 uint32_t RMonoAPI::methodGetFlags(RMonoMethodPtr method, uint32_t* iflags)
1543 {
1544  checkAttached();
1545  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(method_get_flags);
1546 
1547  return apid->apply([&](auto& e) {
1548  return e.api.method_get_flags(e.abi.p2i_RMonoMethodPtr(method), iflags);
1549  });
1550 }
1551 
1552 
1553 RMonoMethodSignaturePtr RMonoAPI::methodSignature(RMonoMethodPtr method)
1554 {
1555  checkAttached();
1556  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(method_signature);
1557 
1558  return apid->apply([&](auto& e) {
1559  return e.abi.i2p_RMonoMethodSignaturePtr(e.api.method_signature(e.abi.p2i_RMonoMethodPtr(method)));
1560  });
1561 }
1562 
1563 
1564 RMonoMethodHeaderPtr RMonoAPI::methodGetHeader(RMonoMethodPtr method)
1565 {
1566  checkAttached();
1567  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(method_get_header);
1568 
1569  return apid->apply([&](auto& e) {
1570  return e.abi.i2p_RMonoMethodHeaderPtr(e.api.method_get_header(e.abi.p2i_RMonoMethodPtr(method)));
1571  });
1572 }
1573 
1574 
1575 rmono_voidp RMonoAPI::methodHeaderGetCode(RMonoMethodHeaderPtr header, uint32_t* codeSize, uint32_t* maxStack)
1576 {
1577  checkAttached();
1578  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(method_header_get_code);
1579 
1580  return apid->apply([&](auto& e) {
1581  return e.abi.i2p_rmono_voidp(e.api.method_header_get_code(e.abi.p2i_RMonoMethodHeaderPtr(header), codeSize, maxStack));
1582  });
1583 }
1584 
1585 
1586 RMonoMethodDescPtr RMonoAPI::methodDescNew(const std::string_view& name, bool includeNamespace)
1587 {
1588  checkAttached();
1589  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(method_desc_new);
1590 
1591  return apid->apply([&](auto& e) {
1592  return e.abi.i2p_RMonoMethodDescPtr(e.api.method_desc_new(name, includeNamespace));
1593  });
1594 }
1595 
1596 
1597 void RMonoAPI::methodDescFree(RMonoMethodDescPtrRaw desc)
1598 {
1599  checkAttached();
1600  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(method_desc_free);
1601 
1602  return apid->apply([&](auto& e) {
1603  e.api.method_desc_free(e.abi.p2i_RMonoMethodDescPtrRaw(desc));
1604  });
1605 }
1606 
1607 
1608 bool RMonoAPI::methodDescMatch(RMonoMethodDescPtr desc, RMonoMethodPtr method)
1609 {
1610  checkAttached();
1611  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(method_desc_match);
1612 
1613  return apid->apply([&](auto& e) {
1614  return e.abi.i2p_rmono_bool(e.api.method_desc_match(e.abi.p2i_RMonoMethodDescPtr(desc), e.abi.p2i_RMonoMethodPtr(method))) != 0;
1615  });
1616 }
1617 
1618 
1619 RMonoMethodPtr RMonoAPI::methodDescSearchInClass(RMonoMethodDescPtr desc, RMonoClassPtr cls)
1620 {
1621  checkAttached();
1622  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(method_desc_search_in_class);
1623 
1624  return apid->apply([&](auto& e) {
1625  return e.abi.i2p_RMonoMethodPtr(e.api.method_desc_search_in_class(e.abi.p2i_RMonoMethodDescPtr(desc), e.abi.p2i_RMonoClassPtr(cls)));
1626  });
1627 }
1628 
1629 
1630 RMonoMethodPtr RMonoAPI::methodDescSearchInClass(const std::string_view& desc, bool includeNamespace, RMonoClassPtr cls)
1631 {
1632  return methodDescSearchInClass(methodDescNew(desc, includeNamespace), cls);
1633 }
1634 
1635 
1636 RMonoMethodPtr RMonoAPI::methodDescSearchInImage(RMonoMethodDescPtr desc, RMonoImagePtr image)
1637 {
1638  checkAttached();
1639  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(method_desc_search_in_image);
1640 
1641  return apid->apply([&](auto& e) {
1642  return e.abi.i2p_RMonoMethodPtr(e.api.method_desc_search_in_image(e.abi.p2i_RMonoMethodDescPtr(desc), e.abi.p2i_RMonoImagePtr(image)));
1643  });
1644 }
1645 
1646 
1647 RMonoMethodPtr RMonoAPI::methodDescSearchInImage(const std::string_view& desc, bool includeNamespace, RMonoImagePtr image)
1648 {
1649  return methodDescSearchInImage(methodDescNew(desc, includeNamespace), image);
1650 }
1651 
1652 
1653 
1654 std::string RMonoAPI::propertyGetName(RMonoPropertyPtr prop)
1655 {
1656  checkAttached();
1657  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(property_get_name);
1658 
1659  return apid->apply([&](auto& e) {
1660  return e.api.property_get_name(e.abi.p2i_RMonoPropertyPtr(prop));
1661  });
1662 }
1663 
1664 
1665 uint32_t RMonoAPI::propertyGetFlags(RMonoPropertyPtr prop)
1666 {
1667  checkAttached();
1668  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(property_get_flags);
1669 
1670  return apid->apply([&](auto& e) {
1671  return e.api.property_get_flags(e.abi.p2i_RMonoPropertyPtr(prop));
1672  });
1673 }
1674 
1675 
1676 RMonoClassPtr RMonoAPI::propertyGetParent(RMonoPropertyPtr prop)
1677 {
1678  checkAttached();
1679  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(property_get_parent);
1680 
1681  return apid->apply([&](auto& e) {
1682  return e.abi.i2p_RMonoClassPtr(e.api.property_get_parent(e.abi.p2i_RMonoPropertyPtr(prop)));
1683  });
1684 }
1685 
1686 
1687 RMonoMethodPtr RMonoAPI::propertyGetSetMethod(RMonoPropertyPtr prop)
1688 {
1689  checkAttached();
1690  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(property_get_set_method);
1691 
1692  return apid->apply([&](auto& e) {
1693  return e.abi.i2p_RMonoMethodPtr(e.api.property_get_set_method(e.abi.p2i_RMonoPropertyPtr(prop)));
1694  });
1695 }
1696 
1697 
1698 RMonoMethodPtr RMonoAPI::propertyGetGetMethod(RMonoPropertyPtr prop)
1699 {
1700  checkAttached();
1701  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(property_get_get_method);
1702 
1703  return apid->apply([&](auto& e) {
1704  return e.abi.i2p_RMonoMethodPtr(e.api.property_get_get_method(e.abi.p2i_RMonoPropertyPtr(prop)));
1705  });
1706 }
1707 
1708 
1709 RMonoObjectPtr RMonoAPI::propertyGetValue(RMonoPropertyPtr prop, const RMonoVariant& obj, RMonoVariantArray& params, bool catchExceptions)
1710 {
1711  checkAttached();
1712  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(property_get_value);
1713 
1714  return apid->apply([&](auto& e) {
1715  return e.abi.i2p_RMonoObjectPtr(e.api.property_get_value(e.abi.p2i_RMonoPropertyPtr(prop), obj, params, catchExceptions));
1716  });
1717 }
1718 
1719 
1720 RMonoObjectPtr RMonoAPI::propertyGetValue(RMonoPropertyPtr prop, const RMonoVariant& obj, RMonoVariantArray&& params, bool catchExceptions)
1721 {
1722  checkAttached();
1723  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(property_get_value);
1724 
1725  return apid->apply([&](auto& e) {
1726  return e.abi.i2p_RMonoObjectPtr(e.api.property_get_value(e.abi.p2i_RMonoPropertyPtr(prop), obj, params, catchExceptions));
1727  });
1728 }
1729 
1730 
1731 void RMonoAPI::propertySetValue(RMonoPropertyPtr prop, const RMonoVariant& obj, RMonoVariantArray& params, bool catchExceptions)
1732 {
1733  checkAttached();
1734  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(property_set_value);
1735 
1736  apid->apply([&](auto& e) {
1737  e.api.property_set_value(e.abi.p2i_RMonoPropertyPtr(prop), obj, params, catchExceptions);
1738  });
1739 }
1740 
1741 
1742 void RMonoAPI::propertySetValue(RMonoPropertyPtr prop, const RMonoVariant& obj, RMonoVariantArray&& params, bool catchExceptions)
1743 {
1744  checkAttached();
1745  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(property_set_value);
1746 
1747  apid->apply([&](auto& e) {
1748  e.api.property_set_value(e.abi.p2i_RMonoPropertyPtr(prop), obj, params, catchExceptions);
1749  });
1750 }
1751 
1752 
1753 
1754 RMonoTypePtr RMonoAPI::signatureGetReturnType(RMonoMethodSignaturePtr sig)
1755 {
1756  checkAttached();
1757  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(signature_get_return_type);
1758 
1759  return apid->apply([&](auto& e) {
1760  return e.abi.i2p_RMonoTypePtr(e.api.signature_get_return_type(e.abi.p2i_RMonoMethodSignaturePtr(sig)));
1761  });
1762 }
1763 
1764 
1765 uint32_t RMonoAPI::signatureGetCallConv(RMonoMethodSignaturePtr sig)
1766 {
1767  checkAttached();
1768  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(signature_get_call_conv);
1769 
1770  return apid->apply([&](auto& e) {
1771  return e.api.signature_get_call_conv(e.abi.p2i_RMonoMethodSignaturePtr(sig));
1772  });
1773 }
1774 
1775 
1776 std::string RMonoAPI::signatureGetDesc(RMonoMethodSignaturePtr sig, bool includeNamespace)
1777 {
1778  checkAttached();
1779  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(signature_get_desc);
1780 
1781  return apid->apply([&](auto& e) {
1782  return e.api.signature_get_desc(e.abi.p2i_RMonoMethodSignaturePtr(sig), e.abi.p2i_rmono_bool(includeNamespace ? 1 : 0));
1783  });
1784 }
1785 
1786 
1787 std::vector<RMonoTypePtr> RMonoAPI::signatureGetParams(RMonoMethodSignaturePtr sig)
1788 {
1789  checkAttached();
1790  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(signature_get_params);
1791 
1792  std::vector<RMonoTypePtr> out;
1793 
1794  apid->apply([&](auto& e) {
1795  typedef decltype(e.abi) ABI;
1796 
1797  blackbone::MemBlock rIter = prepareIterator<ABI>();
1798  typename ABI::irmono_voidpp iptr = (typename ABI::irmono_voidpp) rIter.ptr();
1799 
1800  typename ABI::IRMonoTypePtr param;
1801  typename ABI::IRMonoMethodSignaturePtr isig = e.abi.p2i_RMonoMethodSignaturePtr(sig);
1802 
1803  do {
1804  param = e.api.signature_get_params(isig, iptr);
1805  if (param) {
1806  out.push_back(e.abi.i2p_RMonoTypePtr(param));
1807  }
1808  } while (param);
1809  });
1810 
1811  return out;
1812 }
1813 
1814 
1815 
1816 RMonoClassPtr RMonoAPI::objectGetClass(RMonoObjectPtr obj)
1817 {
1818  checkAttached();
1819  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(object_get_class);
1820 
1821  return apid->apply([&](auto& e) {
1822  return e.abi.i2p_RMonoClassPtr(e.api.object_get_class(e.abi.p2i_RMonoObjectPtr(obj)));
1823  });
1824 }
1825 
1826 
1827 RMonoObjectPtr RMonoAPI::objectNew(RMonoDomainPtr domain, RMonoClassPtr cls)
1828 {
1829  checkAttached();
1830  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(object_new);
1831 
1832  return apid->apply([&](auto& e) {
1833  return e.abi.i2p_RMonoObjectPtr(e.api.object_new(e.abi.p2i_RMonoDomainPtr(domain), e.abi.p2i_RMonoClassPtr(cls)));
1834  });
1835 }
1836 
1837 
1838 RMonoObjectPtr RMonoAPI::objectNew(RMonoClassPtr cls)
1839 {
1840  return objectNew(domainGet(), cls);
1841 }
1842 
1843 
1844 void RMonoAPI::runtimeObjectInit(const RMonoVariant& obj)
1845 {
1846  checkAttached();
1847  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(runtime_object_init);
1848 
1849  apid->apply([&](auto& e) {
1850  e.api.runtime_object_init(obj);
1851  });
1852 }
1853 
1854 
1855 template <typename T>
1856 T RMonoAPI::objectUnbox(RMonoObjectPtr obj)
1857 {
1858  checkAttached();
1859  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(object_unbox);
1860 
1861  T res;
1862  RMonoVariant var(&res);
1863  apid->apply([&](auto& e) {
1864  e.api.object_unbox(var, e.abi.p2i_RMonoObjectPtr(obj));
1865  });
1866  return res;
1867 }
1868 
1869 
1870 RMonoVariant RMonoAPI::objectUnboxRaw(RMonoObjectPtr obj)
1871 {
1872  checkAttached();
1873  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(object_unbox);
1874 
1875  rmono_voidp p;
1876  RMonoVariant var(&p, RMonoVariant::rawPtr);
1877  apid->apply([&](auto& e) {
1878  e.api.object_unbox(var, e.abi.p2i_RMonoObjectPtr(obj));
1879  });
1880  return RMonoVariant(p, RMonoVariant::rawPtr);
1881 }
1882 
1883 
1884 RMonoObjectPtr RMonoAPI::valueBox(RMonoDomainPtr domain, RMonoClassPtr cls, const RMonoVariant& val)
1885 {
1886  checkAttached();
1887  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(value_box);
1888 
1889  return apid->apply([&](auto& e) {
1890  return e.abi.i2p_RMonoObjectPtr(e.api.value_box(e.abi.p2i_RMonoDomainPtr(domain), e.abi.p2i_RMonoClassPtr(cls), val));
1891  });
1892 }
1893 
1894 
1895 RMonoObjectPtr RMonoAPI::valueBox(RMonoClassPtr cls, const RMonoVariant& val)
1896 {
1897  return valueBox(domainGet(), cls, val);
1898 }
1899 
1900 
1901 RMonoStringPtr RMonoAPI::objectToString(const RMonoVariant& obj, bool catchExceptions)
1902 {
1903  checkAttached();
1904 
1905  return apid->apply([&](auto& e) {
1906  if (e.api.object_to_string) {
1907  return e.abi.i2p_RMonoStringPtr(e.api.object_to_string(obj, catchExceptions));
1908  } else {
1909  // TODO: Maybe support value types here?
1910  // UPDATE: Now that we're using objectGetVirtualMethod(), maybe value types will work out of the box?
1911  assert(obj.getType() == RMonoVariant::TypeMonoObjectPtr);
1912 
1913  auto toStr = classGetMethodFromName(getObjectClass(), "ToString", 0);
1914  auto virtualToStr = objectGetVirtualMethod(obj.getMonoObjectPtr(), toStr);
1915  return (RMonoStringPtr) runtimeInvoke(virtualToStr, obj.getMonoObjectPtr(), {}, catchExceptions);
1916  }
1917  });
1918 }
1919 
1920 
1921 RMonoObjectPtr RMonoAPI::objectClone(RMonoObjectPtr obj)
1922 {
1923  checkAttached();
1924  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(object_clone);
1925 
1926  return apid->apply([&](auto& e) {
1927  return e.abi.i2p_RMonoObjectPtr(e.api.object_clone(e.abi.p2i_RMonoObjectPtr(obj)));
1928  });
1929 }
1930 
1931 
1932 RMonoDomainPtr RMonoAPI::objectGetDomain(RMonoObjectPtr obj)
1933 {
1934  checkAttached();
1935  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(object_get_domain);
1936 
1937  return apid->apply([&](auto& e) {
1938  return e.abi.i2p_RMonoDomainPtr(e.api.object_get_domain(e.abi.p2i_RMonoObjectPtr(obj)));
1939  });
1940 }
1941 
1942 
1943 RMonoMethodPtr RMonoAPI::objectGetVirtualMethod(RMonoObjectPtr obj, RMonoMethodPtr method)
1944 {
1945  checkAttached();
1946  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(object_get_virtual_method);
1947 
1948  return apid->apply([&](auto& e) {
1949  return e.abi.i2p_RMonoMethodPtr(e.api.object_get_virtual_method(e.abi.p2i_RMonoObjectPtr(obj), e.abi.p2i_RMonoMethodPtr(method)));
1950  });
1951 }
1952 
1953 
1954 RMonoObjectPtr RMonoAPI::objectIsInst(RMonoObjectPtr obj, RMonoClassPtr cls)
1955 {
1956  checkAttached();
1957  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(object_isinst);
1958 
1959  return apid->apply([&](auto& e) {
1960  return e.abi.i2p_RMonoObjectPtr(e.api.object_isinst(e.abi.p2i_RMonoObjectPtr(obj), e.abi.p2i_RMonoClassPtr(cls)));
1961  });
1962 }
1963 
1964 
1965 rmono_uint RMonoAPI::objectGetSize(RMonoObjectPtr obj)
1966 {
1967  checkAttached();
1968  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(object_get_size);
1969 
1970  return apid->apply([&](auto& e) {
1971  return e.abi.i2p_rmono_uint(e.api.object_get_size(e.abi.p2i_RMonoObjectPtr(obj)));
1972  });
1973 }
1974 
1975 
1976 
1977 RMonoStringPtr RMonoAPI::stringNew(RMonoDomainPtr domain, const std::string_view& str)
1978 {
1979  checkAttached();
1980  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(string_new_len);
1981 
1982  return apid->apply([&](auto& e) {
1983  typedef decltype(e.abi) ABI;
1984  return e.abi.i2p_RMonoStringPtr(e.api.string_new_len(e.abi.p2i_RMonoDomainPtr(domain), str, (typename ABI::irmono_uint) str.size()));
1985  });
1986 }
1987 
1988 
1989 RMonoStringPtr RMonoAPI::stringNew(const std::string_view& str)
1990 {
1991  return stringNew(domainGet(), str);
1992 }
1993 
1994 
1995 RMonoStringPtr RMonoAPI::stringNewUTF16(RMonoDomainPtr domain, const std::u16string_view& str)
1996 {
1997  checkAttached();
1998  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(string_new_utf16);
1999 
2000  return apid->apply([&](auto& e) {
2001  typedef decltype(e.abi) ABI;
2002  return e.abi.i2p_RMonoStringPtr(e.api.string_new_utf16(e.abi.p2i_RMonoDomainPtr(domain), str, (int32_t) str.size()));
2003  });
2004 }
2005 
2006 
2007 RMonoStringPtr RMonoAPI::stringNewUTF16(const std::u16string_view& str)
2008 {
2009  return stringNewUTF16(domainGet(), str);
2010 }
2011 
2012 
2013 RMonoStringPtr RMonoAPI::stringNewUTF32(RMonoDomainPtr domain, const std::u32string_view& str)
2014 {
2015  checkAttached();
2016  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(string_new_utf32);
2017 
2018  return apid->apply([&](auto& e) {
2019  typedef decltype(e.abi) ABI;
2020  return e.abi.i2p_RMonoStringPtr(e.api.string_new_utf32(e.abi.p2i_RMonoDomainPtr(domain), str, (int32_t) str.size()));
2021  });
2022 }
2023 
2024 
2025 RMonoStringPtr RMonoAPI::stringNewUTF32(const std::u32string_view& str)
2026 {
2027  return stringNewUTF32(domainGet(), str);
2028 }
2029 
2030 
2031 std::string RMonoAPI::stringToUTF8(RMonoStringPtr str)
2032 {
2033  checkAttached();
2034  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(string_to_utf8);
2035 
2036  return apid->apply([&](auto& e) {
2037  return e.api.string_to_utf8(e.abi.p2i_RMonoStringPtr(str));
2038  });
2039 }
2040 
2041 
2042 std::u16string RMonoAPI::stringToUTF16(RMonoStringPtr str)
2043 {
2044  checkAttached();
2045  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(string_to_utf16);
2046 
2047  return apid->apply([&](auto& e) {
2048  return e.api.string_to_utf16(e.abi.p2i_RMonoStringPtr(str));
2049  });
2050 }
2051 
2052 
2053 std::u32string RMonoAPI::stringToUTF32(RMonoStringPtr str)
2054 {
2055  checkAttached();
2056  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(string_to_utf32);
2057 
2058  return apid->apply([&](auto& e) {
2059  return e.api.string_to_utf32(e.abi.p2i_RMonoStringPtr(str));
2060  });
2061 }
2062 
2063 
2064 std::u16string RMonoAPI::stringChars(RMonoStringPtr str)
2065 {
2066  checkAttached();
2067  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(string_chars);
2068 
2069  return apid->apply([&](auto& e) {
2070  return e.api.string_chars(e.abi.p2i_RMonoStringPtr(str));
2071  });
2072 }
2073 
2074 
2075 int32_t RMonoAPI::stringLength(RMonoStringPtr str)
2076 {
2077  checkAttached();
2078  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(string_length);
2079 
2080  return apid->apply([&](auto& e) {
2081  return e.api.string_length(e.abi.p2i_RMonoStringPtr(str));
2082  });
2083 }
2084 
2085 
2086 bool RMonoAPI::stringEqual(RMonoStringPtr a, RMonoStringPtr b)
2087 {
2088  checkAttached();
2089  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(string_equal);
2090 
2091  return apid->apply([&](auto& e) {
2092  return e.abi.i2p_rmono_bool(e.api.string_equal(e.abi.p2i_RMonoStringPtr(a), e.abi.p2i_RMonoStringPtr(b))) != 0;
2093  });
2094 }
2095 
2096 
2097 
2098 RMonoArrayPtr RMonoAPI::arrayNew(RMonoDomainPtr domain, RMonoClassPtr cls, rmono_uintptr_t n)
2099 {
2100  checkAttached();
2101  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(array_new);
2102 
2103  return apid->apply([&](auto& e) {
2104  return e.abi.i2p_RMonoArrayPtr(e.api.array_new(e.abi.p2i_RMonoDomainPtr(domain), e.abi.p2i_RMonoClassPtr(cls),
2105  e.abi.p2i_rmono_uintptr_t(n)));
2106  });
2107 }
2108 
2109 
2110 RMonoArrayPtr RMonoAPI::arrayNew(RMonoClassPtr cls, rmono_uintptr_t n)
2111 {
2112  return arrayNew(domainGet(), cls, n);
2113 }
2114 
2115 
2116 RMonoArrayPtr RMonoAPI::arrayNewFull (
2117  RMonoDomainPtr domain,
2118  RMonoClassPtr cls,
2119  const std::vector<rmono_uintptr_t>& lengths,
2120  const std::vector<rmono_intptr_t>& lowerBounds
2121 ) {
2122  checkAttached();
2123  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(array_new_full);
2124 
2125  return apid->apply([&](auto& e) {
2126  typedef decltype(e.abi) ABI;
2127  typedef typename ABI::irmono_voidp irmono_voidp;
2128  typedef typename ABI::irmono_uintptr_t irmono_uintptr_t;
2129  typedef typename ABI::irmono_intptr_t irmono_intptr_t;
2130 
2131  size_t blockSize = lengths.size() * sizeof(irmono_voidp);
2132  if (!lowerBounds.empty()) {
2133  blockSize += lowerBounds.size() * sizeof(irmono_voidp);
2134  }
2135 
2136  char* data = new char[blockSize];
2137  char* dataPtr = data;
2138 
2139  // NOTE: The API for mono_array_new_full() was changed in Mono 2.8. It used to be the following:
2140  //
2141  // MonoArray* mono_array_new_full(MonoDomain *domain, MonoClass *array_class,
2142  // mono_array_size_t *lengths, mono_array_size_t *lower_bounds);
2143  //
2144  // Crucially, the element type of lengths and lower_bounds (mono_array_size_t) used to be typedef'd to either
2145  // guint32 or (if MONO_BIG_ARRAYS was defined) guint64. This means we can't use the new signature when the
2146  // remote uses the old Mono API, and for some miraculous reason, even some recent Unity games STILL use it...
2147  // So we detect the new API by looking for mono_free(), which was also introduced in 2.8, and change types
2148  // accordingly.
2149  // See: https://www.mono-project.com/docs/advanced/embedding/#updates-for-mono-version-28
2150  // TODO: Find a way to support old remotes with MONO_BIG_ARRAYS. How do we detect that?
2151  // TODO: Is looking for mono_free() really a robust way to detect new vs. old API?
2152  bool newApi = (bool) e.api.free;
2153 
2154  if (newApi) {
2155  for (rmono_uintptr_t len : lengths) {
2156  *((irmono_uintptr_t*) dataPtr) = e.abi.p2i_rmono_uintptr_t(len);
2157  dataPtr += sizeof(irmono_uintptr_t);
2158  }
2159  for (rmono_intptr_t bounds : lowerBounds) {
2160  *((irmono_intptr_t*) dataPtr) = e.abi.p2i_rmono_intptr_t(bounds);
2161  dataPtr += sizeof(irmono_intptr_t);
2162  }
2163  } else {
2164  for (rmono_uintptr_t len : lengths) {
2165  *((uint32_t*) dataPtr) = uint32_t(len);
2166  dataPtr += sizeof(uint32_t);
2167  }
2168  for (rmono_intptr_t bounds : lowerBounds) {
2169  *((uint32_t*) dataPtr) = uint32_t(bounds);
2170  dataPtr += sizeof(uint32_t);
2171  }
2172  }
2173 
2174  blackbone::MemBlock block = std::move(process.memory().Allocate(blockSize, PAGE_READWRITE).result());
2175  block.Write(0, blockSize, data);
2176 
2177  delete[] data;
2178 
2179  irmono_voidp lengthsPtr = irmono_voidp(block.ptr());
2180  irmono_voidp lowerBoundsPtr = lowerBounds.empty() ? 0 : irmono_voidp(lengthsPtr + lengths.size()*sizeof(irmono_voidp));
2181 
2182  RMonoArrayPtr arr = e.abi.i2p_RMonoArrayPtr(e.api.array_new_full(e.abi.p2i_RMonoDomainPtr(domain), e.abi.p2i_RMonoClassPtr(cls),
2183  lengthsPtr, lowerBoundsPtr));
2184 
2185  block.Free();
2186 
2187  return arr;
2188  });
2189 }
2190 
2191 
2192 RMonoArrayPtr RMonoAPI::arrayNewFull (
2193  RMonoClassPtr cls,
2194  const std::vector<rmono_uintptr_t>& lengths,
2195  const std::vector<rmono_intptr_t>& lowerBounds
2196 ) {
2197  return arrayNewFull(cls, lengths, lowerBounds);
2198 }
2199 
2200 
2201 RMonoClassPtr RMonoAPI::arrayClassGet(RMonoClassPtr cls, uint32_t rank)
2202 {
2203  checkAttached();
2204  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(array_class_get);
2205 
2206  return apid->apply([&](auto& e) {
2207  return e.abi.i2p_RMonoClassPtr(e.api.array_class_get(e.abi.p2i_RMonoClassPtr(cls), rank));
2208  });
2209 }
2210 
2211 
2212 rmono_voidp RMonoAPI::arrayAddrWithSize(RMonoArrayPtr arr, rmono_int size, rmono_uintptr_t idx)
2213 {
2214  checkAttached();
2215  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(array_addr_with_size);
2216 
2217  rmono_voidp addr;
2218  apid->apply([&](auto& e) {
2219  e.api.array_addr_with_size(RMonoVariant(&addr, RMonoVariant::rawPtr), e.abi.p2i_RMonoArrayPtr(arr),
2220  e.abi.p2i_rmono_int(size), e.abi.p2i_rmono_uintptr_t(idx));
2221  });
2222  return addr;
2223 }
2224 
2225 
2226 rmono_uintptr_t RMonoAPI::arrayLength(RMonoArrayPtr arr)
2227 {
2228  checkAttached();
2229 
2230  return apid->apply([&](auto& e) {
2231  if (e.api.array_length) {
2232  return e.abi.i2p_rmono_uintptr_t(e.api.array_length(e.abi.p2i_RMonoArrayPtr(arr)));
2233  } else {
2234  RMonoClassPtr cls = objectGetClass(arr);
2235  RMonoPropertyPtr lenProp = classGetPropertyFromName(cls, "Length");
2236  RMonoObjectPtr lenObj = propertyGetValue(lenProp, arr);
2237  return (rmono_uintptr_t) objectUnbox<int32_t>(lenObj);
2238  }
2239  });
2240 }
2241 
2242 
2243 int32_t RMonoAPI::arrayElementSize(RMonoClassPtr cls)
2244 {
2245  checkAttached();
2246  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(array_element_size);
2247 
2248  return apid->apply([&](auto& e) {
2249  return e.api.array_element_size(e.abi.p2i_RMonoClassPtr(cls));
2250  });
2251 }
2252 
2253 
2254 int32_t RMonoAPI::classArrayElementSize(RMonoClassPtr cls)
2255 {
2256  checkAttached();
2257  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(class_array_element_size);
2258 
2259  return apid->apply([&](auto& e) {
2260  return e.api.class_array_element_size(e.abi.p2i_RMonoClassPtr(cls));
2261  });
2262 }
2263 
2264 
2265 RMonoArrayPtr RMonoAPI::arrayClone(RMonoArrayPtr arr)
2266 {
2267  checkAttached();
2268  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(array_clone);
2269 
2270  return apid->apply([&](auto& e) {
2271  return e.abi.i2p_RMonoArrayPtr(e.api.array_clone(e.abi.p2i_RMonoArrayPtr(arr)));
2272  });
2273 }
2274 
2275 
2276 template <typename T>
2277 T RMonoAPI::arrayGet(RMonoArrayPtr arr, rmono_uintptr_t idx)
2278 {
2279  checkAttached();
2280  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(array_addr_with_size);
2281 
2282  T val;
2283  apid->apply([&](auto& e) {
2284  typedef decltype(e.abi) ABI;
2285 
2286  // TODO: What about custom value types? Should probably provide a version with RMonoVariant output parameter instead
2287  // of templated return type.
2288 
2289  // NOTE: Mono's original macros for mono_array_get() and mono_array_set*() directly use sizeof() to determine
2290  // the element size, so it seems safe to do the same here, and it's certainly much faster.
2291  if constexpr(std::is_base_of_v<RMonoObjectHandleTag, T>) {
2292  e.api.array_addr_with_size(RMonoVariant(&val), e.abi.p2i_RMonoArrayPtr(arr),
2293  e.abi.p2i_rmono_int((rmono_int) sizeof(typename ABI::IRMonoObjectPtrRaw)), e.abi.p2i_rmono_uintptr_t(idx));
2294  } else {
2295  e.api.array_addr_with_size(RMonoVariant(&val), e.abi.p2i_RMonoArrayPtr(arr),
2296  e.abi.p2i_rmono_int((rmono_int) sizeof(T)), e.abi.p2i_rmono_uintptr_t(idx));
2297  }
2298  });
2299  return val;
2300 }
2301 
2302 
2303 void RMonoAPI::arraySet(RMonoArrayPtr arr, rmono_uintptr_t idx, const RMonoVariant& val)
2304 {
2305  checkAttached();
2306 
2307  apid->apply([&](auto& e) {
2308  // TODO: Maybe some auto-unboxing support? Probably just need to add it to rmono_array_setref().
2309 
2310  if (val.getType() == RMonoVariant::TypeMonoObjectPtr) {
2311  e.api.rmono_array_setref(e.abi.p2i_rmono_gchandle(*arr), e.abi.p2i_rmono_uintptr_t(idx),
2312  e.abi.p2i_rmono_gchandle(*val.getMonoObjectPtr()));
2313  } else if (val.getType() == RMonoVariant::TypeRawPtr) {
2314  RMonoClassPtr arrCls = objectGetClass(arr);
2315  rmono_int size = (rmono_int) arrayElementSize(arrCls);
2316  rmono_voidp p = arrayAddrWithSize(arr, size, idx);
2317  char* data = new char[size];
2318  process.memory().Read((blackbone::ptr_t) val.getRawPtr(), size, data);
2319  process.memory().Write((blackbone::ptr_t) p, size, data);
2320  delete[] data;
2321  } else {
2322  size_t align;
2323  rmono_int size = (rmono_int) val.getRemoteMemorySize(e.abi, align);
2324  rmono_voidp p = arrayAddrWithSize(arr, size, idx);
2325  char* data = new char[size];
2326  val.copyForRemoteMemory(e.abi, data);
2327  process.memory().Write((blackbone::ptr_t) p, size, data);
2328  delete[] data;
2329  }
2330  });
2331 }
2332 
2333 
2334 
2335 rmono_gchandle RMonoAPI::gchandleNew(RMonoObjectPtr obj, bool pinned)
2336 {
2337  checkAttached();
2338  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(gchandle_new);
2339 
2340  return apid->apply([&](auto& e) {
2341  return e.abi.i2p_rmono_gchandle(e.api.gchandle_new(e.abi.p2i_RMonoObjectPtr(obj), e.abi.p2i_rmono_bool(pinned ? 1 : 0)));
2342  });
2343 }
2344 
2345 
2346 rmono_gchandle RMonoAPI::gchandleNewRaw(RMonoObjectPtrRaw obj, bool pinned)
2347 {
2348  checkAttached();
2349  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(gchandle_new);
2350 
2351  return apid->apply([&](auto& e) {
2352  return e.abi.i2p_rmono_gchandle(e.api.gchandle_new.invokeRaw(e.abi.p2i_RMonoObjectPtrRaw(obj), e.abi.p2i_rmono_bool(pinned ? 1 : 0)));
2353  });
2354 }
2355 
2356 
2357 rmono_gchandle RMonoAPI::gchandleNewWeakref(RMonoObjectPtr obj, bool trackResurrection)
2358 {
2359  checkAttached();
2360  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(gchandle_new_weakref);
2361 
2362  return apid->apply([&](auto& e) {
2363  return e.abi.i2p_rmono_gchandle(e.api.gchandle_new_weakref(e.abi.p2i_RMonoObjectPtr(obj),
2364  e.abi.p2i_rmono_bool(trackResurrection ? 1 : 0)));
2365  });
2366 }
2367 
2368 
2369 rmono_gchandle RMonoAPI::gchandleNewWeakrefRaw(RMonoObjectPtrRaw obj, bool trackResurrection)
2370 {
2371  checkAttached();
2372  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(gchandle_new_weakref);
2373 
2374  return apid->apply([&](auto& e) {
2375  return e.abi.i2p_rmono_gchandle(e.api.gchandle_new_weakref.invokeRaw(e.abi.p2i_RMonoObjectPtrRaw(obj),
2376  e.abi.p2i_rmono_bool(trackResurrection ? 1 : 0)));
2377  });
2378 }
2379 
2380 
2381 RMonoObjectPtrRaw RMonoAPI::gchandleGetTarget(rmono_gchandle gchandle)
2382 {
2383  checkAttached();
2384  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(gchandle_get_target);
2385 
2386  return apid->apply([&](auto& e) {
2387  return e.abi.i2p_RMonoObjectPtrRaw(e.api.gchandle_get_target(e.abi.p2i_rmono_gchandle(gchandle)));
2388  });
2389 }
2390 
2391 
2392 void RMonoAPI::gchandleFree(rmono_gchandle gchandle)
2393 {
2394  checkAttached();
2395  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(gchandle_free);
2396 
2397  return apid->apply([&](auto& e) {
2398  e.api.gchandle_free(e.abi.p2i_rmono_gchandle(gchandle));
2399  });
2400 }
2401 
2402 
2403 void RMonoAPI::gcCollect(rmono_int generation)
2404 {
2405  checkAttached();
2406  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(gc_collect);
2407 
2408  apid->apply([&](auto& e) {
2409  e.api.gc_collect(e.abi.p2i_rmono_int(generation));
2410  });
2411 }
2412 
2413 
2414 rmono_int RMonoAPI::gcMaxGeneration()
2415 {
2416  checkAttached();
2417  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(gc_max_generation);
2418 
2419  return apid->apply([&](auto& e) {
2420  return e.abi.i2p_rmono_int(e.api.gc_max_generation());
2421  });
2422 }
2423 
2424 
2425 rmono_int RMonoAPI::gcGetGeneration(RMonoObjectPtr obj)
2426 {
2427  checkAttached();
2428  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(gc_get_generation);
2429 
2430  return apid->apply([&](auto& e) {
2431  return e.abi.i2p_rmono_int(e.api.gc_get_generation(e.abi.p2i_RMonoObjectPtr(obj)));
2432  });
2433 }
2434 
2435 
2436 
2437 RMonoObjectPtr RMonoAPI::runtimeInvoke(RMonoMethodPtr method, const RMonoVariant& obj, RMonoVariantArray& params, bool catchExceptions)
2438 {
2439  checkAttached();
2440  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(runtime_invoke);
2441 
2442  return apid->apply([&](auto& e) {
2443  return e.abi.i2p_RMonoObjectPtr(e.api.runtime_invoke(e.abi.p2i_RMonoMethodPtr(method), obj, params, catchExceptions));
2444  });
2445 }
2446 
2447 
2448 RMonoObjectPtr RMonoAPI::runtimeInvoke(RMonoMethodPtr method, const RMonoVariant& obj, RMonoVariantArray&& params, bool catchExceptions)
2449 {
2450  checkAttached();
2451  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(runtime_invoke);
2452 
2453  return apid->apply([&](auto& e) {
2454  return e.abi.i2p_RMonoObjectPtr(e.api.runtime_invoke(e.abi.p2i_RMonoMethodPtr(method), obj, params, catchExceptions));
2455  });
2456 }
2457 
2458 
2459 
2460 rmono_voidp RMonoAPI::compileMethod(RMonoMethodPtr method)
2461 {
2462  checkAttached();
2463  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(compile_method);
2464 
2465  return apid->apply([&](auto& e) {
2466  return e.abi.i2p_rmono_voidp(e.api.compile_method(e.abi.p2i_RMonoMethodPtr(method)));
2467  });
2468 }
2469 
2470 
2471 
2472 RMonoJitInfoPtr RMonoAPI::jitInfoTableFind(RMonoDomainPtr domain, rmono_voidp addr)
2473 {
2474  checkAttached();
2475  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(jit_info_table_find);
2476 
2477  return apid->apply([&](auto& e) {
2478  return e.abi.i2p_RMonoJitInfoPtr(e.api.jit_info_table_find(e.abi.p2i_RMonoDomainPtr(domain), e.abi.p2i_rmono_voidp(addr)));
2479  });
2480 }
2481 
2482 
2483 RMonoJitInfoPtr RMonoAPI::jitInfoTableFind(rmono_voidp addr)
2484 {
2485  return jitInfoTableFind(domainGet(), addr);
2486 }
2487 
2488 
2489 rmono_voidp RMonoAPI::jitInfoGetCodeStart(RMonoJitInfoPtr jinfo)
2490 {
2491  checkAttached();
2492  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(jit_info_get_code_start);
2493 
2494  return apid->apply([&](auto& e) {
2495  return e.abi.i2p_rmono_voidp(e.api.jit_info_get_code_start(e.abi.p2i_RMonoJitInfoPtr(jinfo)));
2496  });
2497 }
2498 
2499 
2500 int32_t RMonoAPI::jitInfoGetCodeSize(RMonoJitInfoPtr jinfo)
2501 {
2502  checkAttached();
2503  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(jit_info_get_code_size);
2504 
2505  return apid->apply([&](auto& e) {
2506  return e.api.jit_info_get_code_size(e.abi.p2i_RMonoJitInfoPtr(jinfo));
2507  });
2508 }
2509 
2510 
2511 RMonoMethodPtr RMonoAPI::jitInfoGetMethod(RMonoJitInfoPtr jinfo)
2512 {
2513  checkAttached();
2514  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(jit_info_get_method);
2515 
2516  return apid->apply([&](auto& e) {
2517  return e.abi.i2p_RMonoMethodPtr(e.api.jit_info_get_method(e.abi.p2i_RMonoJitInfoPtr(jinfo)));
2518  });
2519 }
2520 
2521 
2522 
2523 std::string RMonoAPI::disasmCode(RMonoDisHelperPtr helper, RMonoMethodPtr method, rmono_voidp ip, rmono_voidp end)
2524 {
2525  checkAttached();
2526  REMOTEMONO_RMONOAPI_CHECK_SUPPORTED(disasm_code);
2527 
2528  return apid->apply([&](auto& e) {
2529  return e.api.disasm_code(e.abi.p2i_RMonoDisHelperPtr(helper), e.abi.p2i_RMonoMethodPtr(method), e.abi.p2i_rmono_voidp(ip),
2530  e.abi.p2i_rmono_voidp(end));
2531  });
2532 }
2533 
2534 
2535 
2536 
2537 
2538 
2539 
2540 
2541 
2542 
2543 
2544 
2545 
2546 // **************************************************************************
2547 // * *
2548 // * UTILITY METHODS *
2549 // * *
2550 // **************************************************************************
2551 
2552 
2553 std::vector<RMonoClassPtr> RMonoAPI::listClasses(RMonoImagePtr image)
2554 {
2555  std::vector<RMonoClassPtr> out;
2556 
2557  RMonoTableInfoPtr tableInfo = imageGetTableInfo(image, MONO_TABLE_TYPEDEF);
2558  rmono_int rows = tableInfoGetRows(tableInfo);
2559 
2560  for (rmono_int i = 0 ; i < rows ; i++) {
2561  uint32_t nameGuid = metadataDecodeRowCol(tableInfo, i, MONO_TYPEDEF_NAME);
2562  uint32_t nameSpaceGuid = metadataDecodeRowCol(tableInfo, i, MONO_TYPEDEF_NAMESPACE);
2563  std::string name = metadataStringHeap(image, nameGuid);
2564  std::string nameSpace = metadataStringHeap(image, nameSpaceGuid);
2565 
2566  RMonoClassPtr cls = classFromName(image, nameSpace, name);
2567 
2568  if (cls) {
2569  out.push_back(cls);
2570  }
2571  }
2572 
2573  return out;
2574 }
2575 
2576 
2577 
2578 std::string RMonoAPI::objectToStringUTF8(RMonoObjectPtr obj, bool catchExceptions)
2579 {
2580  return stringToUTF8(objectToString(obj, catchExceptions));
2581 }
2582 
2583 
2584 template <typename T>
2585 std::vector<T> RMonoAPI::arrayAsVector(RMonoArrayPtr arr)
2586 {
2587  std::vector<T> out;
2588 
2589  rmono_uintptr_t len = arrayLength(arr);
2590  for (rmono_uintptr_t i = 0 ; i < len ; i++) {
2591  out.push_back(arrayGet<T>(arr, i));
2592  }
2593 
2594  return out;
2595 }
2596 
2597 
2598 template <typename T>
2599 RMonoArrayPtr RMonoAPI::arrayFromVector(RMonoDomainPtr domain, RMonoClassPtr cls, const std::vector<T>& vec)
2600 {
2601  RMonoArrayPtr arr = arrayNew(domain, cls, vec.size());
2602 
2603  for (size_t i = 0 ; i < vec.size() ; i++) {
2604  arraySet(arr, (rmono_uintptr_t) i, RMonoVariant(vec[i]));
2605  }
2606 
2607  return arr;
2608 }
2609 
2610 
2611 template <typename T>
2612 RMonoArrayPtr RMonoAPI::arrayFromVector(RMonoClassPtr cls, const std::vector<T>& vec)
2613 {
2614  return arrayFromVector(domainGet(), cls, vec);
2615 }
2616 
2617 
2618 
2619 rmono_gchandle RMonoAPI::gchandlePin(rmono_gchandle gchandle)
2620 {
2621  return apid->apply([&](auto& e) {
2622  return e.abi.i2p_rmono_gchandle(e.api.rmono_gchandle_pin(e.abi.p2i_rmono_gchandle(gchandle)));
2623  });
2624 }
2625 
2626 
2627 
2628 
2629 
2630 }
remotemono::RMonoAPIDispatcher::hasSelectedABI
bool hasSelectedABI() const
Definition: RMonoAPIDispatcher_Def.h:92
remotemono::RMonoAPIBase
Definition: RMonoAPIBase_Def.h:43
remotemono::RMonoObjectHandle< RMonoObjectPtrRaw >
remotemono::RMonoAPI::isAttached
bool isAttached() const
Definition: RMonoAPI_Impl.h:131
remotemono::RMonoAPI::RMonoAPI
RMonoAPI(blackbone::Process &process)
Definition: RMonoAPI_Impl.h:48
remotemono::RMonoAPI::detach
void detach()
Definition: RMonoAPI_Impl.h:93
remotemono::RMonoAPI::isAPIFunctionSupported
bool isAPIFunctionSupported(const std::string &name) const
Definition: RMonoAPI_Impl.h:137
remotemono::RMonoAPI::~RMonoAPI
virtual ~RMonoAPI()
Definition: RMonoAPI_Impl.h:54
remotemono::RMonoAPIDispatcher::selectABI
void selectABI()
Definition: RMonoAPIDispatcher_Def.h:101
remotemono::RMonoHandle::reset
void reset()
Definition: RMonoHandle_Def.h:219
remotemono::RMonoAPI::attach
void attach()
Definition: RMonoAPI_Impl.h:60
remotemono::RMonoHandle::takeOwnership
bool takeOwnership()
Definition: RMonoHandle_Def.h:210
remotemono::RMonoVariant
Definition: RMonoVariant_Def.h:71
remotemono::RMonoHandleBackendBase
Definition: RMonoHandle_Def.h:40
remotemono::RMonoHandle
Definition: RMonoHandle_Def.h:68