// // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // /* * Copyright (c) 2002 Sergey Chaban */ using System; using System.IO; using System.Text; using System.Reflection; using System.Runtime.InteropServices; namespace Mono.PEToolkit { public sealed class PEUtils { private PEUtils() { } unsafe internal static string GetString (sbyte* data, int start, int len, Encoding encoding) { byte[] data_array = new byte[len-start]; for (int i=start; i /// Reads structure from the input stream preserving its endianess. /// /// /// /// unsafe internal static void ReadStruct(BinaryReader reader, void* pStruct, int len) { byte* p = (byte*) pStruct; if (System.BitConverter.IsLittleEndian) { // On a little-endian machine read data in 64-bit chunks, // this won't work on big-endian machine because // BinaryReader APIs are little-endian while // memory writes are platform-native. // This seems faster than ReadBytes/Copy method // in the "else" clause, especially if used often // (no extra memory allocation for byte[]?). int whole = len >> 3; int rem = len & 7; for (int i = whole; --i >= 0;) { long qw = reader.ReadInt64(); Marshal.WriteInt64((IntPtr) p, qw); p += sizeof (long); } for (int i = rem; --i >= 0;) { *p++ = (byte) reader.ReadByte(); } } else { byte [] buff = reader.ReadBytes(len); Marshal.Copy(buff, 0, (IntPtr) p, len); } } /// /// Reads structure from the input stream /// changing its endianess if required /// (if running on big-endian hardware). /// /// /// /// /// unsafe internal static void ReadStruct(BinaryReader reader, void* pStruct, int len, Type type) { ReadStruct(reader, pStruct, len); if (!System.BitConverter.IsLittleEndian) { ChangeStructEndianess(pStruct, type); } } unsafe private static int SwapByTypeCode(byte* p, TypeCode tcode) { int inc = 0; switch (tcode) { case TypeCode.Int16 : short* sp = (short*) p; short sx = *sp; sx = LEBitConverter.SwapInt16(sx); *sp = sx; inc = sizeof (short); break; case TypeCode.UInt16 : ushort* usp = (ushort*) p; ushort usx = *usp; usx = LEBitConverter.SwapUInt16(usx); *usp = usx; inc = sizeof (ushort); break; case TypeCode.Int32 : int* ip = (int*) p; int ix = *ip; ix = LEBitConverter.SwapInt32(ix); *ip = ix; inc = sizeof (int); break; case TypeCode.UInt32 : uint* uip = (uint*) p; uint uix = *uip; uix = LEBitConverter.SwapUInt32(uix); *uip = uix; inc = sizeof (uint); break; case TypeCode.Int64 : long* lp = (long*) p; long lx = *lp; lx = LEBitConverter.SwapInt64(lx); *lp = lx; inc = sizeof (long); break; case TypeCode.UInt64 : ulong* ulp = (ulong*) p; ulong ulx = *ulp; ulx = LEBitConverter.SwapUInt64(ulx); *ulp = ulx; inc = sizeof (ulong); break; case TypeCode.Byte : case TypeCode.SByte : inc = sizeof (byte); break; default : break; } return inc; } unsafe internal static int ChangeStructEndianess(void* pStruct, Type type) { if (type == null || !type.IsValueType) return 0; if (!type.IsLayoutSequential && !type.IsExplicitLayout) { throw new Exception("Internal error: struct must have explicit or sequential layout."); } bool seq = type.IsLayoutSequential; byte* p = (byte*) pStruct; int offs = 0; int inc; FieldInfo [] fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); foreach (FieldInfo fi in fields) { if (!seq) offs = Marshal.OffsetOf(type, fi.Name).ToInt32 (); Type ft = fi.FieldType; TypeCode tcode = Type.GetTypeCode(ft); if (tcode == TypeCode.Object) { // not a primitive type, process recursively. inc = ChangeStructEndianess(p + offs, ft); } else { inc = SwapByTypeCode(p + offs, tcode); } if (seq) offs += inc; } return offs; } } }