I know about the StackTrace class but for what I am doing this is too slow due to all the symbol lookups.
I heard about the RtlCaptureStackBackTrace function in Kernel32.dll but I seem to be unable to get it to function correctly. I am unfamiliar with pinvoke as I rarely have to do anything with it and the stuff I do is well covered on the net, this is not however :(.
This is the definition I have:
[DllImport("kernel32.dll")]
public static extern ushort RtlCaptureStackBackTrace(uint FramesToSkip, uint FramesToCapture, out IntPtr BackTrace, out uint BackTraceHash);
And this is how I am using it:
IntPtr trace = IntPtr.Zero;
uint traceHash = 0;
int framesCaptured = 0;
framesCaptured = RtlCaptureStackBackTrace(0, 4, out trace, out traceHash);
int[] frames = new int[framesCaptured];
Marshal.Copy(trace, frames, 0, framesCaptured);
What I see is that framesCaptured is 1, which should be at least 4 user calls plus system calls for my test app.
EDIT: I should probably be explicit in that my question is what am I doing wrong with RtlCaptureStackBackTrace that I am not receiving the correct stack address information or am I using it right and just don't know how to disseminate the data?
Related
I am trying to call a C++ method from C#. Unfortunately, the documentation for the C++ library is pretty skimpy, but I have access to a header file that defines the methods, so.
The C++ declaration is:
DWORD FAR PASCAL EXPORT Init(int numOfChannels,int startLead,int smpRate,double* pMV_in_1_NUM,int mode = 0);
The documentation unfortunately only gives a C++ example for using this method, which is:
Init (8, 1, 500, &pMV_in_1_NUM, 1);
But I'm trying to call it from C#, so my code is:
[DllImport("NVECGUSB.dll", EntryPoint = "Init")]
[return: MarshalAs(UnmanagedType.U4)]
private static extern UInt32 Init(
int numOfChannels,
int startLead,
int smpRate,
[param: MarshalAs(UnmanagedType.R8)]
ref double pMV_in_1_NUM,
int mode
);
and then...
double pmvIn1Num = 0;
resultCode = Init(8, 1, 500, ref pmvIn1Num, 1);
Console.WriteLine("Init returned {0}", resultCode.ToString("x"));
It doesn't crash or anything, but the resultCode is indicating that the parameters are incorrect, even though they values are correct according to the documentation, so I'm guessing there's something wrong with how I'm passing that double * parameter. (I'm willing to accept that I'm wrong there but right now I can't think of another reason for the error)
Note that I've also tried
[DllImport("NVECGUSB.dll", EntryPoint = "Init")]
[return: MarshalAs(UnmanagedType.U4)]
private static extern UInt32 Init(
int numOfChannels,
int startLead,
int smpRate,
double[] pMV_in_1_NUM,
int mode
);
and
double[] pmvIn1Num = new double[] { 0 };
resultCode = Init(6, 1, 250, pmvIn1Num, 1);
because Google searches throw up results about arrays of double, but I'm not sure this is applicable in my scenario.
So my question is, am I doing it correctly?
(Note that this relates to the Norav 1200M ECG device so if someone has worked wiht that and can tell me what I'm doing wrong, that would be great too)
Basically I have a DLL and a header file (C++) for a data acquisition device that I use for my research. The device has 8 sensors and each sensor has x,y,z,etc data points. I'd like to create a UI program in WPF for this device. So far I've successfully been able to communicate with the device in .NET via an unsafe code implementation and read data into an array of structs (where each struct corresponds to one of the sensors). However I'd like to see if I can get it working with a strictly safe code implementation, but I've just been hitting brick walls for a while now. This is my first time working with unmanaged vs. managed code so please bear with me. I've searched countless threads online and the rabbit hole just keeps getting deeper so I'd like some advice from someone with experience. Basically the API header file has a function with the following definition:
int GetSynchronousRecord(USHORT sensorID, void *pRecord, int recordSize);
Essentially we pass the function a buffer by reference, and it fills it up. I have the option of getting either a single sensor's data, or all sensors at once depending on the sensorID argument I pass. What HAS worked for me so far (in the managed world) is if I do the following:
[StructLayout(LayoutKind.Sequential)]
public struct DOUBLE_POSITION_ANGLES_TIME_Q_RECORD
{
public double x;
public double y;
public double z;
public double a;
public double e;
public double r;
public double time;
public ushort quality;
};
...
[DllImport("ATC3DG64.DLL", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetSynchronousRecord(ushort sensorID, ref DOUBLE_POSITION_ANGLES_TIME_Q_RECORD record, int recordSize);
...
DOUBLE_POSITION_ANGLES_TIME_Q_RECORD record = new DOUBLE_POSITION_ANGLES_TIME_Q_RECORD();
// Get the data from SENSOR_1 only
errorCode = GetSynchronousRecord(1, ref record, Marshal.SizeOf(record));
So this implementation works fine, I can get all the coordinate data and at a really good speed. However, I'd like to get ALL the sensors at once. In the C++ API code samples, they pass the GetSynchronousRecord function an ARRAY of STRUCTS, one struct for each sensor. I tried to do the same in C# as follows:
[DllImport("ATC3DG64.DLL", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetSynchronousRecord(ushort sensorID, ref DOUBLE_POSITION_ANGLES_TIME_Q_RECORD[] record, int recordSize);
// Define Array of Struct for each sensor
DOUBLE_POSITION_ANGLES_TIME_Q_RECORD[] record = new DOUBLE_POSITION_ANGLES_TIME_Q_RECORD[8];
while(recording) {
...
// Get data from ALL sensors (0xffff)
errorCode = GetSynchronousRecord(0xffff, ref record, Marshal.SizeOf(record)*8);
...
}
But this straight up crashes my program with an System.ExecutionEngineException error. I've read that since my function is expecting a void* pointer, that I should use an IntPtr argument, but this approach seemed quite confusing to be honest. Another thing I tried is to actually loop over each sensor and call the function for the sensor, but this dropped the speed INSANELY almost to 1 record/second (instead of 100 records/second). Many other similar threads on stackexchange say to use out parameter, or to use [In, Out] attribute on the function definition, but none of these suggestions worked.
TL;DR: If I understand my situation correctly, I have a MANAGED array of structs that I need to correctly pass to a C++ function as an argument (pass by reference), and then the function will fill my structs with data from a data acquisition device.
I apologize for the wall of text/code, any information for me from someone with experience would be much appreciated.
EDIT: Just to clarify, the GetSynchronousRecord function is INSIDE a while loop where on each iteration I'm getting new data points for each struct.
Your second p/invoke declaration is wrong. You had
[DllImport("ATC3DG64.DLL", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetSynchronousRecord(
ushort sensorID,
ref DOUBLE_POSITION_ANGLES_TIME_Q_RECORD[] record,
int recordSize
);
The problem is the array parameter. Because you pass that array by ref that actually makes it a double pointer. Instead you want to simply remove the ref and declare the import like so:
[DllImport("ATC3DG64.DLL", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetSynchronousRecord(
ushort sensorID,
[Out] DOUBLE_POSITION_ANGLES_TIME_Q_RECORD[] record,
int recordSize
);
The [Out] attribute tells the marshaler that the data is flowing out of the function. Without it the default assumption is that the data flows in.
When you call the function do so like this:
errorCode = GetSynchronousRecord(0xffff, record, Marshal.SizeOf(record)*record.Length);
The best way is probably using IntPtr rather than ref DOUBLE_POSITION_ANGLES_TIME_Q_RECORD.
I'd change the P/Invoke signature to:
[DllImport("ATC3DG64.DLL", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetSynchronousRecord(ushort sensorID, IntPtr record, int recordSize);
Create an IntPtr that points to the needed memory space:
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf<DOUBLE_POSITION_ANGLES_TIME_Q_RECORD>() * 8);
Call the P/Invoke function (which should fill the memory with the structs):
errorCode = GetSynchronousRecord(0xffff, ptr, Marshal.SizeOf<DOUBLE_POSITION_ANGLES_TIME_Q_RECORD>() * 8);
Get the structures from the memory block:
DOUBLE_POSITION_ANGLES_TIME_Q_RECORD[] records = new DOUBLE_POSITION_ANGLES_TIME_Q_RECORD[8];
for (i = 0; i < 8; i++) {
records[i] = Marshal.PtrToStructure<DOUBLE_POSITION_ANGLES_TIME_Q_RECORD>(IntPtr.Add(ptr, i * Marshal.SizeOf<DOUBLE_POSITION_ANGLES_TIME_Q_RECORD>()));
}
Marshal.FreeHGlobal(ptr);
I am trying to use some pinvokes to set up a wgl context for some unit tests, but (so far) one of my methods unbalances the stack.
What I have done is to first create a window and get its DC. This all works as I am talking to the kernel32, user32, gdi32 libraries. I am wanting to draw to a pbuffer with OpenGL, and in order to create the PB, I need to use the extensions. Which requires that I have a context... This is all sadly normal and working so far.
The problem comes when I am trying to create the pbuffer. When I try get the configurations using wglChoosePixelFormatARB, this appears to unbalance the stack. I have just executed another ARB method (wglGetExtensionsStringARB) earlier to check the extensions - and that works fine using the same parent DC.
So, on to code... My delegate looks like this:
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
public delegate bool wglChoosePixelFormatARBDelegate(
IntPtr dc,
[In] int[] attribIList,
[In] float[] attribFList,
uint maxFormats,
[Out] int[] pixelFormats,
out uint numFormats);
I find it like this:
[DllImport(opengl32)]
public static extern IntPtr wglGetProcAddress(string lpszProc);
// ...
var ptr = wglGetProcAddress("wglCreatePbufferARB");
wglCreatePbufferARB = Marshal.GetDelegateForFunctionPointer(ptr, typeof(wglChoosePixelFormatARBDelegate));
And I am invoking it like this:
var iAttrs = new int[]
{
Wgl.WGL_ACCELERATION_ARB, Wgl.WGL_FULL_ACCELERATION_ARB,
Wgl.WGL_DRAW_TO_WINDOW_ARB, Wgl.TRUE,
Wgl.WGL_SUPPORT_OPENGL_ARB, Wgl.TRUE,
Wgl.NONE, Wgl.NONE
};
var fAttrs = new float[2];
var piFormats = new int[1];
uint nFormats;
wglChoosePixelFormatARB(
parentDC,
iAttrs,
fAttrs,
(uint)piFormats.Length,
piFormats,
out nFormats);
if (nFormats == 0)
{
return IntPtr.Zero;
}
var pbuf = extensions.wglCreatePbufferARB(parentDC, piFormats[0], 1, 1, null);
The native side of this is (which is not exported):
BOOL WINAPI wglChoosePixelFormatARB (
HDC hdc,
const int *piAttribIList,
const FLOAT *pfAttribFList,
UINT nMaxFormats,
int *piFormats,
UINT *nNumFormats);
And the function def is this:
typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (
HDC hdc,
const int *piAttribIList,
const FLOAT *pfAttribFList,
UINT nMaxFormats,
int *piFormats,
UINT *nNumFormats);
The code looks OK to me, but there must be something wrong :) I hope someone can point out my error.
In case more code is required, I have it all here in a single file that is just a plain console app:
https://gist.github.com/mattleibow/755eba3c8ff5eafb9549842a0abb0426
(the code has large chunks of comments, this is just because I am busy porting from C++ to C#. And a third of the code is just the dllimports/structs/enums)
The function declaration looks reasonable but it seems that you are simply importing the wrong function.
You want wglChoosePixelFormatARB but actually import wglCreatePbufferARB. This smells like a class copy/paste SNAFU.
Fix this by correcting the name that you pass to GetProcAddress.
I'm working on application SFX / Protector in C# and i want the protected assembly to be executed from a byte array instead of writing it to hard disk, in order to be much harder for reverse engineering.
I have a program within a byte array ( which have a valid entry point ) and i want to execute it.
I found a similar question on this website on how can i do that, i know this can be done using the code snippet below but can someone please guide me on how can i run a program from a byte array using this ?
technically he below code let me do this :
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace DynamicX86
{
class Program
{
const uint PAGE_EXECUTE_READWRITE = 0x40;
const uint MEM_COMMIT = 0x1000;
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
private delegate int IntReturner();
static void Main(string[] args)
{
List<byte> bodyBuilder = new List<byte>();
bodyBuilder.Add(0xb8);
bodyBuilder.AddRange(BitConverter.GetBytes(42));
bodyBuilder.Add(0xc3);
byte[] body = bodyBuilder.ToArray();
IntPtr buf = VirtualAlloc(IntPtr.Zero, (uint)body.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
Marshal.Copy(body, 0, buf, body.Length);
IntReturner ptr = (IntReturner)Marshal.GetDelegateForFunctionPointer(buf, typeof(IntReturner));
Console.WriteLine(ptr());
}
}
}
How can i implement this answer to run a program from array of bytes. I can't understand exactly what i can do with this code. Please help
This is a link where i found this answer :
Is it possible to execute an x86 assembly sequence from within C#?
Anyhelp would be highly appreciated.
What is the valid entry point and what is it's signature? How do you get these bytes from? Do you generate IL? If you do, perhaps it might be easier to simply do this.
What the code above is trying to do is allocate unmanaged memory, fill it with x86 instructions and then have .NET create a delegate from this "function pointer" and execute it - which is different from what you want.
I want to invoke one/many functions of a native library but I am unsure on the type mappings. The function in particular I am currently trying is as follows, here is the small console app which I am spiking in:
extern char *tgetstr (const char *name, char **area);
And here is my attempt at mapping this to use in a .NET console. I get an error saying, trying to read or write protected memory.
class Program
{
[DllImport("termcap.dll")]
public static extern IntPtr tgetstr(IntPtr name, IntPtr area);
static void Main(string[] args)
{
IntPtr ptr1 = new IntPtr();
IntPtr a = tgetstr(Marshal.StringToCoTaskMemAnsi("cl"), ptr1);
Console.WriteLine(Marshal.PtrToStringBSTR(a));
}
}
TIA
Andrew
You need to pass your IntPtr by ref, so the function can overwrite it. Then you also need to free the string after you've copied it, hopefully the DLL provides a matching deallocation function. StringToCoTaskMemAnsi isn't helping you any either, it's just leaking memory.
The correct p/invoke declaration is probably
[DllImport("termcap.dll", CharSet = CharSet.Ansi)]
public static extern IntPtr tgetstr(string name, ref IntPtr area);
I haven't worked with unmanaged code since 3 years but I think you can do it by marking the method parameters with MarshalAs attribute. Check this article,
MSDN
You have to pin your ptr1.
GCHandle handle = GCHandle.Alloc(ptr1, GCHandleType.Pinned);