IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
FieldMarshal.cs
Go to the documentation of this file.
1/*
2 Copyright (C) 2008-2012 Jeroen Frijters
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19
20 Jeroen Frijters
21 jeroen@frijters.net
22
23*/
24
25using System.Reflection.Metadata;
26using System.Reflection.Metadata.Ecma335;
27using System.Runtime.InteropServices;
28using System.Text;
29
34
35namespace IKVM.Reflection
36{
37
38 internal struct FieldMarshal
39 {
40
41 const UnmanagedType UnmanagedType_CustomMarshaler = (UnmanagedType)0x2c;
42 const UnmanagedType NATIVE_TYPE_MAX = (UnmanagedType)0x50;
43
44 public UnmanagedType UnmanagedType;
45 public UnmanagedType? ArraySubType;
46 public short? SizeParamIndex;
47 public int? SizeConst;
48 public VarEnum? SafeArraySubType;
49 public Type SafeArrayUserDefinedSubType;
50 public int? IidParameterIndex;
51 public string MarshalType;
52 public string MarshalCookie;
53 public Type MarshalTypeRef;
54
55 internal static bool ReadFieldMarshal(Module module, int token, out FieldMarshal fm)
56 {
57 fm = new FieldMarshal();
58
59 foreach (var i in module.FieldMarshalTable.Filter(token))
60 {
61 var blob = module.GetBlobReader(module.FieldMarshalTable.records[i].NativeType);
62
63 fm.UnmanagedType = (UnmanagedType)blob.ReadCompressedUInt();
64 switch (fm.UnmanagedType)
65 {
66 case UnmanagedType.LPArray:
67 fm.ArraySubType = (UnmanagedType)blob.ReadCompressedUInt();
68 if (fm.ArraySubType == NATIVE_TYPE_MAX)
69 fm.ArraySubType = null;
70
71 if (blob.Length != 0)
72 {
73 fm.SizeParamIndex = (short)blob.ReadCompressedUInt();
74 if (blob.Length != 0)
75 {
76 fm.SizeConst = blob.ReadCompressedUInt();
77 if (blob.Length != 0 && blob.ReadCompressedUInt() == 0)
78 fm.SizeParamIndex = null;
79 }
80 }
81 break;
82 case UnmanagedType.SafeArray:
83 if (blob.Length != 0)
84 {
85 fm.SafeArraySubType = (VarEnum)blob.ReadCompressedUInt();
86 if (blob.Length != 0)
87 fm.SafeArrayUserDefinedSubType = ReadType(module, blob);
88 }
89 break;
90 case UnmanagedType.ByValArray:
91 fm.SizeConst = blob.ReadCompressedUInt();
92 if (blob.Length != 0)
93 fm.ArraySubType = (UnmanagedType)blob.ReadCompressedUInt();
94 break;
95 case UnmanagedType.ByValTStr:
96 fm.SizeConst = blob.ReadCompressedUInt();
97 break;
98 case UnmanagedType.Interface:
99 case UnmanagedType.IDispatch:
100 case UnmanagedType.IUnknown:
101 if (blob.Length != 0)
102 fm.IidParameterIndex = blob.ReadCompressedUInt();
103 break;
104 case UnmanagedType_CustomMarshaler:
105 {
106 blob.ReadCompressedUInt();
107 blob.ReadCompressedUInt();
108 fm.MarshalType = ReadString(blob);
109 fm.MarshalCookie = ReadString(blob);
110
111 var parser = TypeNameParser.Parse(fm.MarshalType, false);
112 if (!parser.Error)
113 fm.MarshalTypeRef = parser.GetType(module.Universe, module, false, fm.MarshalType, false, false);
114 break;
115 }
116 }
117
118 return true;
119 }
120
121 return false;
122 }
123
124 internal static void SetMarshalAsAttribute(ModuleBuilder module, int token, CustomAttributeBuilder attribute)
125 {
126 attribute = attribute.DecodeBlob(module.Assembly);
127 var rec = new FieldMarshalTable.Record();
128 rec.Parent = token;
129 rec.NativeType = WriteMarshallingDescriptor(module, attribute);
130 module.FieldMarshalTable.AddRecord(rec);
131 }
132
133 static BlobHandle WriteMarshallingDescriptor(ModuleBuilder module, CustomAttributeBuilder attribute)
134 {
135 var val = attribute.GetConstructorArgument(0);
136 var unmanagedType = val switch
137 {
138 short s => (UnmanagedType)s,
139 int i => (UnmanagedType)i,
140 _ => (UnmanagedType)val,
141 };
142
143 var bb = new ByteBuffer(5);
144 bb.WriteCompressedUInt((int)unmanagedType);
145
146 switch (unmanagedType)
147 {
148 case UnmanagedType.LPArray:
149 {
150 var arraySubType = attribute.GetFieldValue<UnmanagedType>("ArraySubType") ?? NATIVE_TYPE_MAX;
151 bb.WriteCompressedUInt((int)arraySubType);
152
153 var sizeParamIndex = attribute.GetFieldValue<short>("SizeParamIndex");
154 var sizeConst = attribute.GetFieldValue<int>("SizeConst");
155 if (sizeParamIndex != null)
156 {
157 bb.WriteCompressedUInt(sizeParamIndex.Value);
158 if (sizeConst != null)
159 {
160 bb.WriteCompressedUInt(sizeConst.Value);
161 bb.WriteCompressedUInt(1); // flag that says that SizeParamIndex was specified
162 }
163 }
164 else if (sizeConst != null)
165 {
166 bb.WriteCompressedUInt(0); // SizeParamIndex
167 bb.WriteCompressedUInt(sizeConst.Value);
168 bb.WriteCompressedUInt(0); // flag that says that SizeParamIndex was not specified
169 }
170
171 break;
172 }
173 case UnmanagedType.SafeArray:
174 {
175 var safeArraySubType = attribute.GetFieldValue<VarEnum>("SafeArraySubType");
176 if (safeArraySubType != null)
177 {
178 bb.WriteCompressedUInt((int)safeArraySubType);
179 var safeArrayUserDefinedSubType = (Type)attribute.GetFieldValue("SafeArrayUserDefinedSubType");
180 if (safeArrayUserDefinedSubType != null)
181 WriteType(module, bb, safeArrayUserDefinedSubType);
182 }
183
184 break;
185 }
186 case UnmanagedType.ByValArray:
187 {
188 bb.WriteCompressedUInt(attribute.GetFieldValue<int>("SizeConst") ?? 1);
189 var arraySubType = attribute.GetFieldValue<UnmanagedType>("ArraySubType");
190 if (arraySubType != null)
191 bb.WriteCompressedUInt((int)arraySubType);
192
193 break;
194 }
195 case UnmanagedType.ByValTStr:
196 bb.WriteCompressedUInt(attribute.GetFieldValue<int>("SizeConst").Value);
197 break;
198 case UnmanagedType.Interface:
199 case UnmanagedType.IDispatch:
200 case UnmanagedType.IUnknown:
201 {
202 var iidParameterIndex = attribute.GetFieldValue<int>("IidParameterIndex");
203 if (iidParameterIndex != null)
204 bb.WriteCompressedUInt(iidParameterIndex.Value);
205
206 break;
207 }
208 case UnmanagedType_CustomMarshaler:
209 {
210 bb.WriteCompressedUInt(0);
211 bb.WriteCompressedUInt(0);
212 var marshalType = (string)attribute.GetFieldValue("MarshalType");
213 if (marshalType != null)
214 WriteString(bb, marshalType);
215 else
216 WriteType(module, bb, (Type)attribute.GetFieldValue("MarshalTypeRef"));
217
218 WriteString(bb, (string)attribute.GetFieldValue("MarshalCookie") ?? "");
219 break;
220 }
221 }
222
223 return module.GetOrAddBlob(bb.ToArray());
224 }
225
226 static Type ReadType(Module module, ByteReader br)
227 {
228 var str = ReadString(br);
229 if (str == "")
230 return null;
231
232 return module.Assembly.GetType(str) ?? module.Universe.GetType(str, true);
233 }
234
235 static void WriteType(Module module, ByteBuffer bb, Type type)
236 {
237 WriteString(bb, type.Assembly == module.Assembly ? type.FullName : type.AssemblyQualifiedName);
238 }
239
240 static string ReadString(ByteReader br)
241 {
242 return Encoding.UTF8.GetString(br.ReadBytes(br.ReadCompressedUInt()));
243 }
244
245 static void WriteString(ByteBuffer bb, string str)
246 {
247 var buf = Encoding.UTF8.GetBytes(str);
248 bb.WriteCompressedUInt(buf.Length);
249 bb.Write(buf);
250 }
251
252 }
253
254}
IKVM.Reflection.Module Module
IKVM.Reflection.Type Type