How to get a raw memory pointer to a managed class? - c#

How do I find a raw pointer to a managed class in C#, and, hopefully, it's raw size in memory? Obviously, this is not allowed by CLR - more precisely, strictly prohibited, as unmanaged representation of managed classes should never, ever be worked with for both stability and safe reasons - so I'm looking for a hack. I'm not looking for serializing - I do actually need a dump of managed class as it is represented in raw memory.
More precisely, I'm looking for something like function getObjectPtr in the following example:
IntPtr getObjectPtr(Object managedClass) {...}
void main() {
var test=new TestClass();
IntPtr* ptr_to_test=getObjectPtr(test);
Console.WriteLine(ptr_to_test.ToString());
}
Thanks in advance!
EDIT:
I've finally found a solution by myself, and, when came back to post it as an answer, was totally surprised by the amount of so-quickly already posted answers... Thanks to all of you! This was very quick and totally unexpected.
The closest to mine solution was #thehennyy's one, but I'm not posting it since #Chino proposed far better one (sorry I've mistaken it to be wrong at first, I've just forgot to dereference the pointer again). It does not require a code to be unsafe and a bit more tolerates GC:
class Program
{
// Here is the function in case anyone needs it.
// Note, though, it does not preserve the handle while you work with
// pointer, so it is less reliable than the code in Main():
static IntPtr getPointerToObject(Object unmanagedObject)
{
GCHandle gcHandle = GCHandle.Alloc(unmanagedObject, GCHandleType.WeakTrackResurrection);
IntPtr thePointer = Marshal.ReadIntPtr(GCHandle.ToIntPtr(gcHandle));
gcHandle.Free();
return thePointer;
}
class TestClass
{
uint a = 0xDEADBEEF;
}
static void Main(string[] args)
{
byte[] cls = new byte[16];
var test = new TestClass();
GCHandle gcHandle = GCHandle.Alloc(test, GCHandleType.WeakTrackResurrection);
IntPtr thePointer = Marshal.ReadIntPtr(GCHandle.ToIntPtr(gcHandle));
Marshal.Copy(thePointer, cls, 0, 16); //Dump first 16 bytes...
Console.WriteLine(BitConverter.ToString(BitConverter.GetBytes(thePointer.ToInt32())));
Console.WriteLine(BitConverter.ToString(cls));
Console.ReadLine();
gcHandle.Free();
}
}
/* Example output (yours should be different):
40-23-CA-02
4C-38-04-01-EF-BE-AD-DE-00-00-00-80-B4-21-50-73
That field's value is "EF-BE-AD-DE", 0xDEADBEEF as it is stored in memory. Yay, we found it!
*/
Hovewer, now I'm a bit clueless. According to the this article, first 2 addresses in the class should be pointers to SyncBlock and RTTI structure, and therefore the first field's address must be offset by 2 words [8 bytes in 32-bit systems, 16 bytes in 64-bit systems] from the beginning. Mine is 64-bit; however, as you can see in the output, it is obvious that first field's raw offset from the object's address is only 4 bytes, which doesn't make any sense.
I've asked this as a separate question.
Maybe I should ask this as a separate question, but it is possible that there is an error in my solution.

Hey is this what you want?:
GCHandle gcHandle = GCHandle.Alloc(yourObject,GCHandleType.WeakTrackResurrection);
IntPtr thePointer = GCHandle.ToIntPtr(gcHandle);

You can write a small IL function that leaks an objects address.
var o = new object();
var d = new DynamicMethod("GetPtr", typeof(IntPtr), new Type[] {typeof(object)}, Assembly.GetExecutingAssembly().ManifestModule);
var il = d.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ret);
var address = (IntPtr)d.Invoke(null, new object[] {o});
Console.WriteLine(address);
The source is: IllidanS4 / SharpUtils
/ UnsafeTools.cs

Related

Porting binary file reading C++ code to C#

I am trying to port some code from our C++ application to ensure that the licence files are compatible with both applications.
I've tried marking the functions as external, however that opened a whole other can of worms that I wouldn't like to delve into considering this is my last week at my current employer.
The C++ code I'd like to port is as follows:
std::fstream licenceFile(filePath, std::ios::in | std::ios::binary);
licenceFile.read((char *) &this->m_FileData, sizeof(this->m_FileData));
m_FileData is a struct and is as follows:
struct LicManKeyFileData
{
BYTE m_EncryptedKey[255];
WCHAR m_MacAddress[33];
WCHAR m_PreviousMacLicense[33];
WCHAR m_SoftwareName[16];
WCHAR m_ClientName[65];
BYTE m_Version;
BYTE m_EncryptionLength;
time_t m_LicenseTime;
};
I have tried several methods of replicating this in C#, firstly reading the file member by member, for example:
BinaryReader reader = new BinaryReader(licenceFileStream, Encoding.BigEndianUnicode);
licenceFileData.EncryptedKey = reader.ReadBytes(licenceFileData.EncryptedKey.Length);
byte[] mac = new byte[sizeof(char) * licenceFileData.MacAddress.Length];
mac = reader.ReadBytes(mac.Length);
Something strange I noticed about this method is that a lot of the values were being set as 204 seemingly arbitrarily, when they are read correctly in the C++ application, so I've had to add this:
if (mac[0] == 204)
mac[0] = 0;
Which makes no sense to me, it's not an alignment issue, reading from a byte before or after that gives totally garbage values (chinese characters) and this check and assigning 0 to the first index allows me to get the proper value.
Another method I've tried was found on here on StackOverflow, and is as follows:
public static T ReadStruct<T>(this BinaryReader reader) where T : struct
{
Byte[] buffer = new Byte[Marshal.SizeOf(typeof(T))];
reader.Read(buffer, 0, buffer.Length);
GCHandle handle = default(GCHandle);
try
{
handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
return (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally
{
if (handle.IsAllocated)
handle.Free();
}
}
Oddly, this method also returns some values as 204 where the C++ application reads them as the correct value.
The struct I'm using in C# looks like this:
unsafe struct LicenceFileDataS
{
internal fixed byte m_EncryptedKey[255];
internal fixed char m_MacAddress[33];
internal fixed char m_PreviousMacLicense[33];
internal fixed char m_SoftwareName[16];
internal fixed char m_ClientName[65];
internal byte m_Version;
internal byte m_EncryptionLength;
internal long m_LicenseTime;
}
Does anyone know a better method for porting this code or how I can fix the values that are being read as 204? It works perfectly in C++. My apologies for the wall of text.

Convert code c++ to c# , read to a class [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have a class
class DataqFmt
{
public:
unsigned short SR_number;
unsigned short SR_numerator;
unsigned char offset;
unsigned char nbytes;
short hdr_bytes;
unsigned long dat_bytes;
char dummy[1144];
};
code c++ :
afl = fopen(path, "rb");
DataqFmt dataqstr;
fread ((char*) &dataqstr, sizeof (dataqstr), 1, afl);
How can i convert this code c++ to c# . Please help me
I'm going to assume that the C++ application that wrote this file was compiled for Win32 x86 and run on Win32 x86. This allows me to make assumptions about that way that DataqFmt was arranged. If these assumptions are wrong, you can adjust them by using the various options of StructLayout and related attributes, like MarshalAs and FieldOffset.
First, we're going to use a C# structure with the same layout as DataqFmt:
[StructLayout(LayoutKind.Sequential)]
struct DataqFmtCs
{
public ushort SR_number; // assuming the C++ type unsigned short is 2 bytes
public ushort SR_numerator;
public byte offset; // assuming the C++ type unsigned char was an unsigned and 1 byte
public byte nbytes;
public short hdr_bytes; // assuming the C++ type short was 2 bytes
public uint dat_bytes; // assuming the C++ type unsigned long was 4 bytes
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1144)]
public sbyte[] dummy; // assuming the C++ type char was signed and 1 byte
}
With that structure, we now need to do file I/O to get the raw bytes.
int dataqfmtSize = Marshal.SizeOf(typeof(DataqFmtCs));
var buffer = new byte[dataqfmtSize];
using (var fs = File.OpenRead("path\\to\\the\\file")) {
int bytesRead = fs.Read(buffer, 0, buffer.Length);
if (bytesRead != buffer.Length) {
// handle this
}
DataqFmtCs someThing = GetDataqFmtFromBuffer(buffer);
}
Finally, we have the conversion routine GetDataqFmtFromBuffer.
private static DataqFmtCs GetDataqFmtFromBuffer(byte[] buffer) {
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try {
return (DataFmtCs)Marshal.PtrToStructure(
handle.AddrOfPinnedObject(),
typeof(DataFmtCs));
} finally {
handle.Free();
}
}
Marshal.PtrToStrucutre is doing the vast majority of the conversion work. The rest of the code is just defining the struct and doing basic .NET file I/O.
Another option--and this is often a good solution if you are working with a well-documented protocol that is platform agnostic, as you'll often need to perform endian conversions--is to write a deserialization routine that operates on a Stream using a BinaryReader. I'll leave this as an exercise for you.
If you are using visual studio you could also import the C++ code and compile it into a CLR library to be referenced by any other .net assembly. This is especially a good idea if you need the C++ code to run fast.
If you're willing to acknowledge that the C++ fread() is inherently fragile and non-portable, it might be better to write an abstraction layer to read (and write) the code data types, for example a format like this is useful:
// returns true on success, false on EOF
public static bool Read(Stream stm, out int val)
{ /* ... */ }
public static bool Read(Stream stm, out short val)
{ /* ... */ }
then you can write you code to be something like:
if (!Read(stm, out _someMember))
throw SomeException(); // or return a fail code
if (!Read(stm, out _someOtherMember))
throw SomeException();
or in the case of some of my code, I wrote a method that given an object, a stream, and the name of either a field or a property, reads the appropriate sized value and sets the member (or throws an exception if it can't find it), and then a similar method that works on an object and a collection of names (or really a variable number of string arguments, so initialization can look like this:
public static TTHorizontalHeader FromStream(Stream stm)
{
TTHorizontalHeader header = new TTHorizontalHeader();
if (!Reader.ReadType(stm, header,
"TableVersion", "Ascender", "Descender", "LineGap", "AdvanceWidthMax", "MinLeftSideBearing",
"MinRightSideBearing", "XMaxExtent", "CaretSlopeRise", "CaretSlopeRun", "CaretOffset", "Reserved0",
"Reserved1", "Reserved2", "Reserved3", "MetricDataFormat", "NumberOfHMetrics"))
return null;
return header;
}
but you say, "won't the C++ run faster since it just does one fread()?" And I reply, "Endianess, data type size, structure padding, and changes in object layout are reason enough to not keep propagating the same fragile code under the guise of performance. Any decent buffered stream is going to do only one actual read anyway and the reading work is done by an impartial robot. Besides the cost of I/O, buffered or not, will dwarf the cost of reflection and string iteration.

passing pointers referencing memory allocated in managed code to unmanaged

I have a large char[] buffer allocated in c# and want to pass a pointer to this data to an umnanaged c function in a DLL.
Now i think for this to work the char buffer must be FIXED so that GC cant shift it around while the function is working.
If so, would i declare the buffer FIXED and call the DLL within and UNSAFE block ??
fixed ( int* p = &bigbuffer )
{
processbigbuffer(bigbuffer);
}
I have searched but not many references highlight the issue that the memory belongs to c# and how this would work in a DLL.
Thanks
You don't have to use fixed. The runtime will do that for you automatically. So if you have the C function:
void ProcessBigBuffer(char* buffer);
Then your managed prototype would look like:
[DllImport("foo.dll", CallingConvention=CallingConvention.Cdecl)]
static extern void ProcessBigBuffer([MarshalAs(UnmanagedType.LPArray)] char[] buffer);
And your call site would be:
char[] buffer = new char[bufferSize];
// initialize the buffer
// and then process it
ProcessBigBuffer(buffer);
See also:
UnmanagedType enumeration
Interoperating with Unmanaged Code
Yes, indeed. You can do this without unsafe code and without copying the data.
var chars = new char[LARGE_AMOUNT];
var handle = GCHandle.Alloc(chars);
try
{
processBigBuffer(/* this is an IntPtr -> */ handle.AddrOfPinnedObject, ... );
}
finally
{
handle.Free();
}
My OpenCL bindings use this all over the place (and are very performant).

How do I call this c function in c# (unmarshalling return struct)?

I want to use c# interop to call a function from a dll written in c. I have the header files.
Take a look at this:
enum CTMBeginTransactionError {
CTM_BEGIN_TRX_SUCCESS = 0,
CTM_BEGIN_TRX_ERROR_ALREADY_IN_PROGRESS,
CTM_BEGIN_TRX_ERROR_NOT_CONNECTED
};
#pragma pack(push)
#pragma pack(1)
struct CTMBeginTransactionResult {
char * szTransactionID;
enum CTMBeginTransactionError error;
};
struct CTMBeginTransactionResult ctm_begin_customer_transaction(const char * szTransactionID);
How do I call ctm_begin_customer_transaction from c#. The const char * mapps well to string, but despite various attempts (looking at stackoverflow and other sites), I fail to marshal the return structure. If I define the function to return IntPtr it works ok...
Edit
I changed the return type to IntPtr and use:
CTMBeginTransactionResult structure = (CTMBeginTransactionResult)Marshal.PtrToStructure(ptr, typeof(CTMBeginTransactionResult));
but it throws AccessViolationException
I also tried:
IntPtr ptr = Transactions.ctm_begin_customer_transaction("");
int size = 50;
byte[] byteArray = new byte[size];
Marshal.Copy(ptr, byteArray, 0, size);
string stringData = Encoding.ASCII.GetString(byteArray);
stringData == "70e3589b-2de0-4d1e-978d-55e22225be95\0\"\0\0\a\0\0\b\b?" at this point. The "70e3589b-2de0-4d1e-978d-55e22225be95" is the szTransactionID from the struct. Where is the Enum? Is it the next byte?
There's a memory management problem hidden in this struct. Who owns the C string pointer? The pinvoke marshaller will always assume that the caller owns it so it will try to release the string. And passes the pointer to CoTaskMemFree(), same function as the one called by Marshal.FreeCoTaskMem(). These functions use the COM memory allocator, the universal interop memory manager in Windows.
This rarely comes to a good end, C code does not typically use that allocator unless the programmer designed his code with interop in mind. In which case he'd never have used a struct as a return value, interop always works much less trouble-free when the caller supplies buffers.
So you cannot afford to let the marshaller do its normal duty. You must declare the return value type as IntPtr so it doesn't try to release the string. And you must marshal it yourself with Marshal.PtrToStructure().
That however still leaves the question unanswered, who owns the string? There is nothing you can do to release the string buffer, you don't have access to the allocator used in the C code. The only hope you have is that the string wasn't actually allocated on the heap. That's possible, the C program might be using string literals. You need to verify that guess. Call the function a billion times in a test program. If that doesn't explode the program then you're good. If not then only C++/CLI can solve your problem. Given the nature of the string, a "transaction ID" ought to change a lot, I'd say you do have a problem.
I hate to answer my own question, but I found the solution to marshal the resulting struct. The struct is 8 bytes long (4 bytes for the char * and 4 bytes for enum). Marshalling the string does not work automatically, but the following works:
// Native (unmanaged)
public enum CTMBeginTransactionError
{
CTM_BEGIN_TRX_SUCCESS = 0,
CTM_BEGIN_TRX_ERROR_ALREADY_IN_PROGRESS,
CTM_BEGIN_TRX_ERROR_NOT_CONNECTED
};
// Native (unmanaged)
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
internal struct CTMBeginTransactionResult
{
public IntPtr szTransactionID;
public CTMBeginTransactionError error;
};
// Managed wrapper around native struct
public class BeginTransactionResult
{
public string TransactionID;
public CTMBeginTransactionError Error;
internal BeginTransactionResult(CTMBeginTransactionResult nativeStruct)
{
// Manually marshal the string
if (nativeStruct.szTransactionID == IntPtr.Zero) this.TransactionID = "";
else this.TransactionID = Marshal.PtrToStringAnsi(nativeStruct.szTransactionID);
this.Error = nativeStruct.error;
}
}
[DllImport("libctmclient-0.dll")]
internal static extern CTMBeginTransactionResult ctm_begin_customer_transaction(string ptr);
public static BeginTransactionResult BeginCustomerTransaction(string transactionId)
{
CTMBeginTransactionResult nativeResult = Transactions.ctm_begin_customer_transaction(transactionId);
return new BeginTransactionResult(nativeResult);
}
The code works, but I still need to investigate, if calling the unmanaged code results in memory leaks.

Convert array of structs to IntPtr

I am trying to convert an array of the RECT structure (given below) into an IntPtr, so I can send the pointer using PostMessage to another application.
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
// lots of functions snipped here
}
// so we have something to send, in reality I have real data here
// also, the length of the array is not constant
RECT[] foo = new RECT[4];
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(foo[0]) * 4);
Marshal.StructureToPtr(foo, ptr, true); // -- FAILS
This gives an ArgumentException on the last line ("The specified structure must be blittable or have layout information."). I need to somehow get this array of RECTs over to another application using PostMessage, so I really need a pointer to this data.
What are my options here?
UPDATE: This seems to work:
IntPtr result = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Win32.RECT)) * foo.Length);
IntPtr c = new IntPtr(result.ToInt32());
for (i = 0; i < foo.Length; i++)
{
Marshal.StructureToPtr(foo[i], c, true);
c = new IntPtr(c.ToInt32() + Marshal.SizeOf(typeof(Win32.RECT)));
}
UPDATED AGAIN to fix what arbiter commented on.
StructureToPtr expects struct object, and foo is not structure it is array, that is why exception occurs.
I can suggest you to write structures in cycle (sadly, StructureToPtr does not have overload with Index):
long LongPtr = ptr.ToInt64(); // Must work both on x86 and x64
for (int I = 0; I < foo.Length; I++)
{
IntPtr RectPtr = new IntPtr(LongPtr);
Marshal.StructureToPtr(foo[I], RectPtr, false); // You do not need to erase struct in this case
LongPtr += Marshal.SizeOf(typeof(Rect));
}
Another option is to write structure as four integers, using Marshal.WriteInt32:
for (int I = 0; I < foo.Length; I++)
{
int Base = I * sizeof(int) * 4;
Marshal.WriteInt32(ptr, Base + 0, foo[I].Left);
Marshal.WriteInt32(ptr, Base + sizeof(int), foo[I].Top);
Marshal.WriteInt32(ptr, Base + sizeof(int) * 2, foo[I].Right);
Marshal.WriteInt32(ptr, Base + sizeof(int) * 3, foo[I].Bottom);
}
And the last, you can use unsafe keyword, and work with pointers directly.
Arbiter has given you one good answer for how to marshal arrays of structs. For blittable structs like these I, personally, would use unsafe code rather than manually marshaling each element to unmanaged memory. Something like this:
RECT[] foo = new RECT[4];
unsafe
{
fixed (RECT* pBuffer = foo)
{
//Do work with pointer
}
}
or you could pin the array using a GCHandle.
Unfortunately, you say you need to send this information to another process. If the message you are posting is not one of the ones for which Windows provides automatic marshaling then you have another problem. Since the pointer is relative to the local process it means nothing in the remote process and posting a message with this pointer will cause unexpected behavior, including likely program crash. So what you need to do is write the RECT array to the other process' memory not your own. To do this you need to use OpenProcess to get a handle to the process, VitualAllocEx to allocate the memory in the other process and then WriteProcessMemory to write the array into the other process' virtual memory.
Unfortunately again, if you are going from a 32bit process to a 32bit process or from a 64bit process to a 64bit process things are quite straightforward but from a 32bit process to a 64bit process things can get a little hairy. VirtualAllocEx and WriteProcessMemory are not really supported from 32 to 64. You may have success by trying to force VirtualAllocEx to allocate its memory in the bottom 4GB of the 64bit memory space so that the resultant pointer is valid for the 32bit process API calls and then write with that pointer. In addition, you may have struct size and packing differences between the two process types. With RECT there is no problem but some other structs with packing or alignment issues might need to be manually written field by field to the 64bit process in order to match the 64bit struct layout.
You could try the following:
RECT[] rects = new RECT[ 4 ];
IntPtr[] pointers = new IntPtr[4];
IntPtr result = Marshal.AllocHGlobal(IntPtr.Size * rects.Length);
for (int i = 0; i < rects.Length; i++)
{
pointers[i] = Marshal.AllocHGlobal (IntPtr.Size);
Marshal.StructureToPtr(rects[i], pointers[i], true);
Marshal.WriteIntPtr(result, i * IntPtr.Size, pointers[i]);
}
// the array that you need is stored in result
And don't forget to free everything after you are finished.
I was unable to get this solution to work. So, I did some searching and the solution given here worked for me.
http://social.msdn.microsoft.com/Forums/en-US/clr/thread/dcfd6310-b03b-4552-b4c7-6c11c115eb45

Categories

Resources