singrdk/base/Windows/mkmsil/msil/MarshalSpec.cs

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;
}
}