308 lines
8.9 KiB
C#
308 lines
8.9 KiB
C#
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
|
|
namespace Bartok.MSIL
|
|
{
|
|
|
|
using System;
|
|
|
|
public abstract class MarshalSpec {
|
|
|
|
// Constructor Methods
|
|
|
|
internal static MarshalSpec Create(byte[] buffer) {
|
|
int offset = 0;
|
|
NativeTypes kind = (NativeTypes)
|
|
SignatureBuffer.uncompressInt(buffer, ref offset);
|
|
switch (kind) {
|
|
case NativeTypes.BOOLEAN:
|
|
case NativeTypes.I1:
|
|
case NativeTypes.U1:
|
|
case NativeTypes.I2:
|
|
case NativeTypes.U2:
|
|
case NativeTypes.I4:
|
|
case NativeTypes.U4:
|
|
case NativeTypes.I8:
|
|
case NativeTypes.U8:
|
|
case NativeTypes.R4:
|
|
case NativeTypes.R8:
|
|
case NativeTypes.CURRENCY:
|
|
case NativeTypes.BSTR:
|
|
case NativeTypes.LPSTR:
|
|
case NativeTypes.LPWSTR:
|
|
case NativeTypes.LPTSTR:
|
|
case NativeTypes.IUNKNOWN:
|
|
case NativeTypes.IDISPATCH:
|
|
case NativeTypes.STRUCT:
|
|
case NativeTypes.INTF:
|
|
case NativeTypes.INT:
|
|
case NativeTypes.UINT:
|
|
case NativeTypes.BYVALSTR:
|
|
case NativeTypes.ANSIBSTR:
|
|
case NativeTypes.TBSTR:
|
|
case NativeTypes.VARIANTBOOL:
|
|
case NativeTypes.FUNC:
|
|
case NativeTypes.ASANY:
|
|
case NativeTypes.LPSTRUCT:
|
|
case NativeTypes.ERROR:
|
|
case NativeTypes.MAX: {
|
|
if (offset != buffer.Length) {
|
|
Console.WriteLine("WARNING: extra bytes in "+new MetaDataBlob(buffer));
|
|
}
|
|
return new MarshalSpecNative(kind);
|
|
}
|
|
case NativeTypes.SAFEARRAY: {
|
|
VariantTypes elemType;
|
|
if (offset < buffer.Length) {
|
|
elemType = (VariantTypes)
|
|
SignatureBuffer.uncompressInt(buffer, ref offset);
|
|
}
|
|
else {
|
|
elemType = VariantTypes.VT_EMPTY;
|
|
}
|
|
if (offset != buffer.Length) {
|
|
Console.WriteLine("WARNING: extra bytes in "+new MetaDataBlob(buffer));
|
|
}
|
|
return new MarshalSpecSafeArray(elemType);
|
|
}
|
|
case NativeTypes.FIXEDSYSSTRING: {
|
|
uint elemCount =
|
|
SignatureBuffer.uncompressInt(buffer, ref offset);
|
|
if (offset != buffer.Length) {
|
|
Console.WriteLine("WARNING: extra bytes in "+new MetaDataBlob(buffer));
|
|
}
|
|
return new MarshalSpecFixedString(elemCount);
|
|
}
|
|
case NativeTypes.FIXEDARRAY: {
|
|
uint elemCount =
|
|
SignatureBuffer.uncompressInt(buffer, ref offset);
|
|
if (offset != buffer.Length) {
|
|
Console.WriteLine("WARNING: extra bytes in "+new MetaDataBlob(buffer));
|
|
}
|
|
return new MarshalSpecFixedArray(elemCount);
|
|
}
|
|
case NativeTypes.CUSTOMMARSHALER: {
|
|
String guid = uncompressString(buffer, ref offset);
|
|
String unmanagedType = uncompressString(buffer, ref offset);
|
|
String managedType = uncompressString(buffer, ref offset);
|
|
String cookie = uncompressString(buffer, ref offset);
|
|
if (offset != buffer.Length) {
|
|
Console.WriteLine("WARNING: extra bytes in "+new MetaDataBlob(buffer));
|
|
}
|
|
return new MarshalSpecCustom(guid, unmanagedType,
|
|
managedType, cookie);
|
|
}
|
|
case NativeTypes.ARRAY: {
|
|
NativeTypes elemType = (NativeTypes)
|
|
SignatureBuffer.uncompressInt(buffer, ref offset);
|
|
uint paramNumber =
|
|
((offset < buffer.Length) ?
|
|
SignatureBuffer.uncompressInt(buffer, ref offset) :
|
|
0);
|
|
uint extras =
|
|
((offset < buffer.Length) ?
|
|
SignatureBuffer.uncompressInt(buffer, ref offset) :
|
|
0);
|
|
if (offset != buffer.Length) {
|
|
Console.WriteLine("WARNING: extra bytes in "+new MetaDataBlob(buffer));
|
|
}
|
|
return new MarshalSpecArray(elemType, paramNumber, extras);
|
|
}
|
|
default: {
|
|
throw new Exception("Unknown marshal spec kind "+kind);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static String uncompressString(byte[] buffer, ref int offset) {
|
|
uint length = SignatureBuffer.uncompressInt(buffer, ref offset);
|
|
int oldOffset = offset;
|
|
offset += (int) length;
|
|
return MetaDataLoader.stringEncoding.GetString(buffer, oldOffset,
|
|
(int) length);
|
|
}
|
|
|
|
public override abstract String ToString();
|
|
|
|
}
|
|
|
|
public class MarshalSpecNative: MarshalSpec {
|
|
|
|
// Constructor Methods
|
|
|
|
public MarshalSpecNative(NativeTypes kind) {
|
|
this.kind = kind;
|
|
}
|
|
|
|
// Accessors
|
|
|
|
public NativeTypes Kind {
|
|
get { return this.kind; }
|
|
}
|
|
|
|
public override String ToString() {
|
|
return "MarshalSpecNative("+kind+")";
|
|
}
|
|
|
|
// Private State
|
|
|
|
private readonly NativeTypes kind;
|
|
|
|
}
|
|
|
|
public class MarshalSpecSafeArray: MarshalSpec {
|
|
|
|
// Constructor Methods
|
|
|
|
public MarshalSpecSafeArray(VariantTypes elemType) {
|
|
this.elemType = elemType;
|
|
}
|
|
|
|
// Accessors
|
|
|
|
public VariantTypes ElementType {
|
|
get { return this.elemType; }
|
|
}
|
|
|
|
public override String ToString() {
|
|
return "MarshalSpecSafeArray("+elemType+")";
|
|
}
|
|
|
|
// Private State
|
|
|
|
private readonly VariantTypes elemType;
|
|
|
|
}
|
|
|
|
public class MarshalSpecFixedString: MarshalSpec {
|
|
|
|
// Constructor Methods
|
|
|
|
public MarshalSpecFixedString(uint elemCount) {
|
|
this.elemCount = elemCount;
|
|
}
|
|
|
|
// Accessors
|
|
|
|
public uint ElementCount {
|
|
get { return this.elemCount; }
|
|
}
|
|
|
|
public override String ToString() {
|
|
return "MarshalSpecFixedString("+elemCount+")";
|
|
}
|
|
|
|
// Private State
|
|
|
|
private readonly uint elemCount;
|
|
|
|
}
|
|
|
|
public class MarshalSpecFixedArray: MarshalSpec {
|
|
|
|
// Constructor Methods
|
|
|
|
public MarshalSpecFixedArray(uint elemCount) {
|
|
this.elemCount = elemCount;
|
|
}
|
|
|
|
// Accessors
|
|
|
|
public uint ElementCount {
|
|
get { return this.elemCount; }
|
|
}
|
|
|
|
public override String ToString() {
|
|
return "MarshalSpecFixedArray("+elemCount+")";
|
|
}
|
|
|
|
// Private State
|
|
|
|
private readonly uint elemCount;
|
|
|
|
}
|
|
|
|
public class MarshalSpecCustom: MarshalSpec {
|
|
|
|
// Constructor Methods
|
|
|
|
public MarshalSpecCustom(String guid, String unmanagedType,
|
|
String managedType, String cookie) {
|
|
this.guid = guid;
|
|
this.unmanagedType = unmanagedType;
|
|
this.managedType = managedType;
|
|
this.cookie = cookie;
|
|
}
|
|
|
|
// Accessors
|
|
|
|
public String Guid {
|
|
get { return this.guid; }
|
|
}
|
|
|
|
public String UnmanagedType {
|
|
get { return this.unmanagedType; }
|
|
}
|
|
|
|
public String ManagedType {
|
|
get { return this.managedType; }
|
|
}
|
|
|
|
public String Cookie {
|
|
get { return this.cookie; }
|
|
}
|
|
|
|
public override String ToString() {
|
|
return ("MarshalSpecCustom("+guid+","+
|
|
managedType+"->"+unmanagedType+","+cookie+")");
|
|
}
|
|
|
|
// Private State
|
|
|
|
private readonly String guid;
|
|
private readonly String unmanagedType;
|
|
private readonly String managedType;
|
|
private readonly String cookie;
|
|
|
|
}
|
|
|
|
public class MarshalSpecArray: MarshalSpec {
|
|
|
|
// Constructor Methods
|
|
|
|
public MarshalSpecArray(NativeTypes elemType, uint paramNumber,
|
|
uint extras) {
|
|
this.elemType = elemType;
|
|
this.paramNumber = paramNumber;
|
|
this.extras = extras;
|
|
}
|
|
|
|
// Accessors
|
|
|
|
public NativeTypes ElementType {
|
|
get { return this.elemType; }
|
|
}
|
|
|
|
public uint ParameterNumber {
|
|
get { return this.paramNumber; }
|
|
}
|
|
|
|
public uint ExtraCount {
|
|
get { return this.extras; }
|
|
}
|
|
|
|
public override String ToString() {
|
|
return "MarshalSpecArray("+elemType+","+paramNumber+","+extras+")";
|
|
}
|
|
|
|
// Private State
|
|
|
|
private readonly NativeTypes elemType;
|
|
private readonly uint paramNumber;
|
|
private readonly uint extras;
|
|
|
|
}
|
|
|
|
}
|