1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//
5
6//
7////////////////////////////////////////////////////////////////////////////////
8// This module defines a Utility Class used by reflection
9//
10//
11
12////////////////////////////////////////////////////////////////////////////////
13
14
15#ifndef __INVOKEUTIL_H__
16#define __INVOKEUTIL_H__
17
18// The following class represents the value class
19#include <pshpack1.h>
20
21struct InterfaceMapData
22{
23 REFLECTCLASSBASEREF m_targetType;
24 REFLECTCLASSBASEREF m_interfaceType;
25 PTRARRAYREF m_targetMethods;
26 PTRARRAYREF m_interfaceMethods;
27};
28
29// Calling Conventions
30// NOTE: These are defined in CallingConventions.cs They must match up.
31#define Standard_CC 0x0001
32#define VarArgs_CC 0x0002
33#define Any_CC (Standard_CC | VarArgs_CC)
34
35#define PRIMITIVE_TABLE_SIZE ELEMENT_TYPE_STRING
36#define PT_Primitive 0x01000000
37
38// Define the copy back constants.
39#define COPYBACK_PRIMITIVE 1
40#define COPYBACK_OBJECTREF 2
41#define COPYBACK_VALUECLASS 3
42
43#include <poppack.h>
44
45class ReflectMethodList;
46class ArgDestination;
47
48// Structure used to track security access checks efficiently when applied
49// across a range of methods, fields etc.
50//
51class RefSecContext : public AccessCheckContext
52{
53public:
54 RefSecContext(AccessCheckOptions::AccessCheckType accessCheckType)
55 : m_fCheckedCaller(false),
56 m_fCheckedPerm(false),
57 m_fCallerHasPerm(false),
58 m_pCaller(NULL),
59 m_pCallerDomain(NULL),
60 m_accessCheckType(accessCheckType)
61 {
62 LIMITED_METHOD_CONTRACT;
63 }
64
65 virtual MethodTable* GetCallerMT();
66 virtual MethodDesc* GetCallerMethod();
67 virtual Assembly* GetCallerAssembly();
68 virtual bool IsCalledFromInterop();
69
70 AccessCheckOptions::AccessCheckType GetAccessCheckType() const
71 {
72 LIMITED_METHOD_CONTRACT;
73 return m_accessCheckType;
74 }
75
76 AppDomain* GetCallerDomain();
77
78private:
79 bool m_fCheckedCaller;
80 bool m_fCheckedPerm;
81 bool m_fCallerHasPerm;
82
83
84 // @review GENERICS:
85 // These method descriptors may be shared between compatible instantiations
86 // Check that this does not open any security holes
87 MethodDesc* m_pCaller;
88 AppDomain* m_pCallerDomain;
89
90 AccessCheckOptions::AccessCheckType m_accessCheckType;
91
92 void FindCaller();
93};
94
95// This class abstracts the functionality which creats the
96// parameters on the call stack and deals with the return type
97// inside reflection.
98//
99class InvokeUtil
100{
101
102public:
103 static void CopyArg(TypeHandle th, OBJECTREF *obj, ArgDestination *argDest);
104
105 // Given a type, this routine will convert an return value representing that
106 // type into an ObjectReference. If the type is a primitive, the
107 // value is wrapped in one of the Value classes.
108 static OBJECTREF CreateObjectAfterInvoke(TypeHandle th, void * pValue);
109
110 // This is a special purpose Exception creation function. It
111 // creates the TargetInvocationExeption placing the passed
112 // exception into it.
113 static OBJECTREF CreateTargetExcept(OBJECTREF* except);
114
115 // This is a special purpose Exception creation function. It
116 // creates the ReflectionClassLoadException placing the passed
117 // classes array and exception array into it.
118 static OBJECTREF CreateClassLoadExcept(OBJECTREF* classes,OBJECTREF* except);
119
120 // Validate that the field can be widened for Set
121 static void ValidField(TypeHandle th, OBJECTREF* value);
122
123 // ChangeType
124 // This method will invoke the Binder change type method on the object
125 // binder -- The Binder object
126 // srcObj -- The source object to be changed
127 // th -- The TypeHandel of the target type
128 // locale -- The locale passed to the class.
129 static OBJECTREF ChangeType(OBJECTREF binder,OBJECTREF srcObj,TypeHandle th,OBJECTREF locale);
130
131 // CreatePrimitiveValue
132 // This routine will validate the object and then place the value into
133 // the destination
134 // dstType -- The type of the destination
135 // srcType -- The type of the source
136 // srcObj -- The Object containing the primitive value.
137 // pDst -- poiner to the destination
138 static void CreatePrimitiveValue(CorElementType dstType, CorElementType srcType, OBJECTREF srcObj, ARG_SLOT* pDst);
139
140 // CreatePrimitiveValue
141 // This routine will validate the object and then place the value into
142 // the destination
143 // dstType -- The type of the destination
144 // srcType -- The type of the source
145 // pSrc -- pointer to source data.
146 // pSrcMT - MethodTable of source type
147 // pDst -- poiner to the destination
148 static void CreatePrimitiveValue(CorElementType dstType,CorElementType srcType,
149 void *pSrc, MethodTable *pSrcMT, ARG_SLOT* pDst);
150
151 // IsPrimitiveType
152 // This method will verify the passed in type is a primitive or not
153 // type -- the CorElementType to check for
154 inline static DWORD IsPrimitiveType(const CorElementType type)
155 {
156 LIMITED_METHOD_CONTRACT;
157
158 if (type >= PRIMITIVE_TABLE_SIZE)
159 {
160 if (ELEMENT_TYPE_I==type || ELEMENT_TYPE_U==type)
161 {
162 return TRUE;
163 }
164 return 0;
165 }
166
167 return (PT_Primitive & PrimitiveAttributes[type]);
168 }
169
170 static BOOL IsVoidPtr(TypeHandle th);
171
172 // CanPrimitiveWiden
173 // This method determines if the srcType and be widdened without loss to the destType
174 // destType -- The target type
175 // srcType -- The source type.
176 inline static DWORD CanPrimitiveWiden(const CorElementType destType, const CorElementType srcType)
177 {
178 LIMITED_METHOD_CONTRACT;
179
180 if (destType >= PRIMITIVE_TABLE_SIZE || srcType >= PRIMITIVE_TABLE_SIZE)
181 {
182 if ((ELEMENT_TYPE_I==destType && ELEMENT_TYPE_I==srcType) ||
183 (ELEMENT_TYPE_U==destType && ELEMENT_TYPE_U==srcType))
184 {
185 return TRUE;
186 }
187 return 0;
188 }
189 return ((1 << destType) & PrimitiveAttributes[srcType]);
190 }
191
192 // Field Stuff. The following stuff deals with fields making it possible
193 // to set/get field values on objects
194
195 // SetValidField
196 // Given an target object, a value object and a field this method will set the field
197 // on the target object. The field must be validate before calling this.
198 static void SetValidField(CorElementType fldType, TypeHandle fldTH, FieldDesc* pField, OBJECTREF* target, OBJECTREF* value, TypeHandle declaringType, CLR_BOOL *pDomainInitialized);
199
200 static OBJECTREF GetFieldValue(FieldDesc* pField, TypeHandle fieldType, OBJECTREF* target, TypeHandle declaringType, CLR_BOOL *pDomainInitialized);
201
202 // ValidateObjectTarget
203 // This method will validate the Object/Target relationship
204 // is correct. It throws an exception if this is not the case.
205 static void ValidateObjectTarget(FieldDesc* pField,TypeHandle fldType,OBJECTREF *target);
206
207 // Create reflection pointer wrapper
208 static OBJECTREF CreatePointer(TypeHandle th, void * p);
209
210 static TypeHandle GetPointerType(OBJECTREF pObj);
211 static void* GetPointerValue(OBJECTREF pObj);
212 static void* GetIntPtrValue(OBJECTREF pObj);
213
214 // Check accessability of a type or nested type.
215 static void CanAccessClass(RefSecContext* pCtx,
216 MethodTable* pClass,
217 BOOL checkAccessForImplicitValueTypeCtor = FALSE);
218
219 static void CanAccessMethod(MethodDesc* pMeth,
220 MethodTable* pParentMT,
221 MethodTable* pInstanceMT,
222 RefSecContext* pSCtx,
223 BOOL fCriticalToFullDemand = TRUE,
224 BOOL checkSkipVer = FALSE);
225
226 // Check accessability of a field
227 static void CanAccessField(RefSecContext* pCtx,
228 MethodTable* pTargetMT,
229 MethodTable* pInstanceMT,
230 FieldDesc* pTargetField);
231
232 //
233 // Check to see if the target of a reflection operation is on a remote object
234 //
235 // Arguments:
236 // pDesc - item being accessed (MethodDesc, FieldDesc, etc)
237 // pTargetMT - object being reflected on
238
239 template <typename T>
240 static bool IsTargetRemoted(T *pDesc, MethodTable *pTargetMT)
241 {
242 CONTRACTL
243 {
244 THROWS;
245 GC_TRIGGERS;
246 MODE_ANY;
247 PRECONDITION(CheckPointer(pDesc));
248 }
249 CONTRACTL_END;
250
251 if (pDesc->IsStatic())
252 return FALSE;
253
254 if (pTargetMT == NULL)
255 return FALSE;
256
257 return FALSE;
258 }
259
260 static AccessCheckOptions::AccessCheckType GetInvocationAccessCheckType(BOOL targetRemoted = FALSE);
261
262private:
263 // Check accessability of a type or nested type.
264 static void CheckAccessClass(RefSecContext *pCtx,
265 MethodTable *pClass,
266 BOOL checkAccessForImplicitValueTypeCtor = FALSE);
267
268public:
269 // Check accessability of a method
270 static void CheckAccessMethod(RefSecContext *pCtx,
271 MethodTable *pTargetMT,
272 MethodTable *pInstanceMT,
273 MethodDesc *pTargetMethod);
274
275private:
276 // Check accessability of a field
277 static void CheckAccessField(RefSecContext *pCtx,
278 MethodTable *pTargetMT,
279 MethodTable *pInstanceMT,
280 FieldDesc *pTargetField);
281
282 // Check accessability of a field or method.
283 // pTargetMD should be NULL for a field, and may be NULL for a method.
284 // If checking a generic method with a method instantiation,
285 // the method should be in as pOptionalTargetMethod so
286 // that the accessibilty of its type arguments is checked too.
287 static void CheckAccess(RefSecContext *pCtx,
288 MethodTable *pTargetMT,
289 MethodTable *pInstanceMT,
290 MethodDesc *pTargetMD,
291 FieldDesc *pTargetField,
292 const AccessCheckOptions &accessCheckOptions);
293
294 static void* CreateByRef(TypeHandle dstTh,CorElementType srcType, TypeHandle srcTH,OBJECTREF srcObj, OBJECTREF *pIncomingObj);
295
296 // GetBoxedObject
297 // Given an address of a primitve type, this will box that data...
298 static OBJECTREF GetBoxedObject(TypeHandle th,void* pData);
299
300private:
301 // The Attributes Table
302 // This constructs a table of legal widening operations
303 // for the primitive types.
304 static DWORD const PrimitiveAttributes[PRIMITIVE_TABLE_SIZE];
305};
306
307
308#endif // __INVOKEUTIL_H__
309