remotemono
RMonoHandle_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 <BlackBone/Process/Process.h>
25 #include "RMonoHandle_Def.h"
26 #include "RMonoAPIBase_Def.h"
27 
28 
29 
30 
31 namespace remotemono
32 {
33 
34 
35 template <typename PtrT>
36 void RMonoHandleAssemblyNamePtrDelete(PtrT p, RMonoAPIBase* mono)
37 {
38  RMonoAPIDispatcher* apid = mono->getAPIDispatcher();
39  apid->apply([&](auto& e) {
40  // TODO: Some remotes (e.g. RedRunner) don't have mono_assembly_name_free(), but they do have
41  // mono_assembly_name_parse(). How are we supposed to free then? I guess we'll just leak for now...
42  if (e.api.assembly_name_free) {
43  e.api.assembly_name_free(e.abi.p2i_RMonoAssemblyNamePtrRaw(p));
44  }
45 
46  if (e.api.assembly_name_new) {
47  if (e.api.free) {
48  e.api.free(e.abi.p2i_rmono_voidp((rmono_voidp) p));
49  } else if (e.api.g_free) {
50  e.api.g_free(e.abi.p2i_rmono_voidp((rmono_voidp) p));
51  } else {
52  assert(false);
53  }
54  } else {
55  blackbone::MemBlock block(&mono->getProcess().memory(), (blackbone::ptr_t) p, true);
56  block.Free();
57  }
58  });
59 }
60 
61 
62 template <typename PtrT>
63 void RMonoHandleMethodDescPtrDelete(PtrT p, RMonoAPIBase* mono)
64 {
65  RMonoAPIDispatcher* apid = mono->getAPIDispatcher();
66  apid->apply([&](auto& e) {
67  e.api.method_desc_free(e.abi.p2i_RMonoMethodDescPtrRaw(p));
68  });
69 }
70 
71 
72 void RMonoObjectHandleDelete(rmono_gchandle gchandle, RMonoAPIBase* mono)
73 {
74  RMonoAPIDispatcher* apid = mono->getAPIDispatcher();
75  apid->apply([&](auto& e) {
76  e.api.gchandle_free(e.abi.p2i_rmono_gchandle(gchandle));
77  });
78 }
79 
80 
81 
82 
83 
84 template<typename HandleT, void (*deleter)(HandleT, RMonoAPIBase*), HandleT invalidHandle>
85 void RMonoHandle<HandleT, deleter, invalidHandle>::Data::registerBackend()
86 {
87  regIt = mono->registerMonoHandleBackend(this);
88 }
89 
90 
91 template<typename HandleT, void (*deleter)(HandleT, RMonoAPIBase*), HandleT invalidHandle>
92 void RMonoHandle<HandleT, deleter, invalidHandle>::Data::unregisterBackend()
93 {
94  mono->unregisterMonoHandleBackend(regIt);
95 }
96 
97 
98 
99 
100 
101 template <typename RawPtrT>
103 {
104  if (this == &other || **this == *other) {
105  return true;
106  }
107  // TODO: Maybe implement a custom remote function to do this more efficiently?
108  auto pinnedThis = pin();
109  return pinnedThis.raw() == other.raw();
110 }
111 
112 
113 template <typename RawPtrT>
115 {
116  if (!isValid()) {
117  return *this;
118  }
119  RMonoAPIDispatcher* apid = d->mono->getAPIDispatcher();
120  rmono_gchandle pinned = REMOTEMONO_GCHANDLE_INVALID;
121  apid->apply([&](auto& e) {
122  pinned = e.abi.i2p_rmono_gchandle(e.api.rmono_gchandle_pin(e.abi.p2i_rmono_gchandle(d->handle)));
123  });
124  return Self(pinned, d->mono);
125 }
126 
127 
128 template <typename RawPtrT>
130 {
131  if (!isValid()) {
132  return *this;
133  }
134  RMonoAPIDispatcher* apid = d->mono->getAPIDispatcher();
135  rmono_gchandle cloned = REMOTEMONO_GCHANDLE_INVALID;
136  apid->apply([&](auto& e) {
137  cloned = e.abi.i2p_rmono_gchandle(e.api.gchandle_new(*this, false));
138  });
139  return Self(cloned, d->mono);
140 }
141 
142 
143 template <typename RawPtrT>
144 typename RMonoObjectHandle<RawPtrT>::RawPtr RMonoObjectHandle<RawPtrT>::raw() const
145 {
146  if (!isValid()) {
147  return (RawPtr) 0;
148  }
149  RMonoAPIDispatcher* apid = d->mono->getAPIDispatcher();
150  RawPtr p = (RawPtr) 0;
151  apid->apply([&](auto& e) {
152  p = e.abi.i2p_rmono_voidp(e.api.gchandle_get_target(e.abi.p2i_rmono_gchandle(d->handle)));
153  });
154  return p;
155 }
156 
157 
158 }
remotemono::RMonoObjectHandle
Definition: RMonoHandle_Def.h:277
remotemono::RMonoAPIDispatcher
Definition: RMonoAPIDispatcher_Def.h:78
remotemono::RMonoObjectHandle::raw
RawPtr raw() const
Definition: RMonoHandle_Impl.h:144