Return IntPtr with array to c++ - c#

I have c# method ReadBytesInTask, which is called from c++ code, using function pointer acquired with Marshal.GetFunctionPointerForDelegate method.
ReadBytesInTask gets ptr to unmanaged short[] array populates it and sends back to unmanaged code. Array is unmarshalled to unmanaged memory correctly inside method, but c++ gets only zero populated array.
What should I do?
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Auto)]
private delegate int BytesReader([In,Out] IntPtr buffer, int samplesCount, string taskId);
private static readonly BytesReader _readBytesInTask = ReadBytesInTask;
private static int ReadBytesInTask(IntPtr buffer, int samplesCount)
{
var bufferSize = samplesCount;
var samplesToRead = bufferSize <= task.Buffer.Length - task.Offset ? bufferSize : task.Buffer.Length - task.Offset;
buffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(short))*samplesToRead);
Marshal.Copy(task.Buffer, task.Offset, buffer, samplesToRead);
task.Offset += samplesToRead;
if (samplesToRead < bufferSize) task.Offset = 0;
return samplesToRead;
}

You are changing the pointer and not what it points to. So you will need a pointer to pointer. So it would be something like this:
private static int ReadBytesInTask(IntPtr* buffer, int samplesCount)

Related

Create C++ dll with functions whose arguments can be called as out parameter in c#

I want to create a function in c++ that takes two parameter(char[], int) and modifies the parameters(Similar to out parameter in c#) and then create a dll that can be used in c#.
C++ Sample Code:
static void funct(char * name, int size)
{
char[] testName="John";
name=&testName;
size=5;
}
C# Sample Code:
const string dllLocation = "D:\\Test.dll";
[DllImport(dllLocation, CallingConvention = CallingConvention.Cdecl)]
private static extern void funct(StringBuilder name, int size);
This is not correct code. It is just to give an idea of what I want. I want to use c# to access the c++ function through dll and obtain the name and size(no of characters).
Use pointers in the C++ side and marshal these by ref on the C# side.
static void funct(char** name, int* size)
{
char[] testName="John";
*name=&testName;
*size=5;
}
const string dllLocation = "D:\\Test.dll";
[DllImport(dllLocation, CallingConvention = CallingConvention.Cdecl)]
private static extern void funct(ref StringBuilder name, ref int size);
Beware with the char array, it may create memory leaks or worse crashes, it would be better to first test the size of the buffer and the size of the data you want to pass to C#, if there is enough room copy it, else inform to C# that it needs more size so it's allocated by C#.
Something like this:
static int funct(char** name, int* size, int bufferSize)
{
if(bufferSize < 4)
return 4;
char[] testName="John";
memcpy(name*, &char[0], 4);
*size=5;
return -1;
}
const string dllLocation = "D:\\Test.dll";
[DllImport(dllLocation, CallingConvention = CallingConvention.Cdecl)]
private static extern void funct(ref StringBuilder name, ref int size, int bufferSize);
StringBuilder sb = null;
int size = 0;
//Request size
int neededSize = funct(ref sb, ref size, 0);
//Create buffer with appropiate size
sb = new StringBuilder(neededSize);
//Call with the correct size, test result.
if(funct(ref sb, ref size, neededSize) != -1)
throw new Exception();

Marshalling a pointer to an array of pointer to structure Exception "cannot Read or Write protected memory"

I am translating a native C++ library to C#. The original function allocates some memory of the struct, doing some memory manipulation of the current process and return the manipulated bytes to a byte buffer inside the struct.
The struct is defined as follow:
typedef struct tdMEM_SCATTER_HEADER {
DWORD magic;
WORD version;
WORD Future1;
ULONG64 qwA;
DWORD cbMax;
DWORD cb;
PBYTE pb;
PVOID pvReserved1;
PVOID pvReserved2;
PVOID Future2[8];
} MEM_SCATTER_HEADER, *PMEM_SCATTER_HEADER, **PPMEM_SCATTER_HEADER;
The original function is defined as follow:
DWORD Scatter(_Inout_ PPMEM_SCATTER_HEADER ppMEMs, _In_ DWORD count);
and the allocating sequence is
pbBuffer = LocalAlloc(0, count * (sizeof(PMEM_SCATTER_HEADER) + sizeof(MEM_SCATTER_HEADER) + 0x1000));
ZeroMemory(pbBuffer, count * (sizeof(PMEM_SCATTER_HEADER) + sizeof(MEM_SCATTER_HEADER)));
for(i = 0; i < cMEMs; i++) {
pMEM->pb = pbData + ((QWORD)i << 12); // Allocating return bytes buffer.
}
Here is what I tried:
Struct marshalling:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct MEM_SCATTER_HEADER
{
public uint magic;
public ushort version;
public ushort Future1;
public ulong qwA;
public uint cbMax;
public uint cb;
[MarshalAs(UnmanagedType.ByValArray)]
public byte[] pb;
public IntPtr pvReserved1;
public IntPtr pvReserved2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public IntPtr[] Future2;
}
Memory allocating:
MEM_SCATTER_HEADER[] header = new MEM_SCATTER_HEADER[count];
for (int i = 0; i < count; i++)
{
header[i].pb = new byte[0x1000];
Array.Clear(header[i].pb, 0, header[i].pb.Length); // Fill array with 0
}
DLLImport:
[DllImport("testC.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern uint Scatter(ref MEM_SCATTER_HEADER ppMems, uint count);
And finally function call:
uint count = Scatter(ref header, count);
I have a had time debugging wether I marshal data wrongly or wether I have to do some manual marshalling to get rid of the exception: "Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'" at function call.
The initial allocation is not zeroing all the memory it's allocating, and it doesn't look right. It's as if the code were doing:
int bigchunk = sizeof(PMEM_SCATTER_HEADER) + sizeof(MEM_SCATTER_HEADER) + 0x1000;
int smallchunk = sizeof(PMEM_SCATTER_HEADER) + sizeof(MEM_SCATTER_HEADER);
pBuffer = LocalAlloc(0, count * bigchunk);
ZeroMemory(pBuffer, count * smallchunk);
Might this matter?

Calling C++ function with LPStr return value from C#

I have a C++ dll in 64-Bit, which contains a function that returns an LPStr. I would like to call this function in C#. The function declaration looks like this:
__declspec(dllexport) LPSTR __stdcall function(int16_t error_code);
In my C# code I have tried the following:
[DllImport(#"<PathToInterface.dll>", EntryPoint = "function")]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string function(Int16 error_code);
And then in the program:
string ErrorMessage = "";
ErrorMessage = function(-10210);
I know that the function itself is good, as I can call it from another program (written in LabVIEW FWIW). But when I execute the C# Program, it just exits with error code 0x80000003, I can't even try, catch the exeption.
How do I call this function properly?
As a side node: I do have other functions in this dll, that use LPStr as parameters, which I can call without a problem. It is only two functions that return LPStr that make problems
How do I call this function properly?
As interop? you can't ... it is also error prone in plain C++
you should rather do it like
extern "C" __declspec(dllexport) int __stdcall function(int16_t error_code,
LPSTR buffer, size_t size)
{
LPCSTR format = "error: %i";
size_t req = _scprintf(format, error_code); // check for require size
if (req > size) //buffer size is too small
{
return req; //return required size
}
sprintf_s(buffer, size, format, error_code); //fill buffer
return 0;
}
And usage
class Program
{
static void Main(string[] args)
{
short error_code = -10210;
var ret = function(error_code, null, 0); // check for required size of the buffer
var sb = new StringBuilder(ret); // create large enough buffer
ret = function(error_code, sb, (uint)sb.Capacity + 1); //call again
var error_desc = sb.ToString(); //get results
Console.WriteLine(error_desc);
Console.ReadKey();
}
[DllImport("TestDll.dll", EntryPoint = "function", CharSet = CharSet.Ansi)]
public static extern int function(short error_code, StringBuilder sb, int size);
}
usage in C++
typedef int (__stdcall *function)(int16_t error_code, LPSTR buffer, size_t size);
int main()
{
auto handle = LoadLibrary(L"TestDll.dll");
auto proc = (function)GetProcAddress(handle, "_function#12");
// of course it can be done via linking
int16_t error_code = 333;
const int ret = proc(error_code, NULL, 0); // check for size
CHAR* buffer = new CHAR[ret + 1];
//CHAR buffer[200]; //eventually allocate on stack
//but size have to be constant value and may be too small
proc(error_code, buffer, ret+1); // call again
MessageBoxA(0, buffer, "Return", 0); //show result
delete[] buffer; //free buffer!
FreeLibrary(handle);
return 0;
}

Reading block of memory into array?

I am using the method below to read bytes in memory. I want to read values in memory addresses which are very near each other. Previously I have been making individual calls for each byte in memory and adding the result to an array using a for loop. This became really inefficient, so instead I want to adapt the below code to read a large block of memory and then try to do an itteration through the array to pull out the bytes I want. I have spent a bit of time trying to work it out, but really struggling. FYI, this method reads a pointer, and then if that value is a pointer, it reads that pointer, and so forth until it gets to the static address then reads the byte value at that address.
[DllImport("kernel32", EntryPoint = "ReadProcessMemory")]
private static extern byte ReadProcessMemoryByte(int Handle, int Address, ref byte Value, int Size, ref int BytesRead);
public static byte ReadPointerByte(string EXENAME, int Pointer, int[] Offset)
{
byte Value = 0;
checked
{
try
{
Process[] Proc = Process.GetProcessesByName(EXENAME);
if (Proc.Length != 0)
{
int Bytes = 0;
int Handle = OpenProcess(PROCESS_ALL_ACCESS, 0, Proc[0].Id);
if (Handle != 0)
{
foreach (int i in Offset)
{
ReadProcessMemoryInteger((int)Handle, Pointer, ref Pointer, 4, ref Bytes);
Pointer += i;
}
ReadProcessMemoryByte((int)Handle, Pointer, ref Value, 2, ref Bytes);
CloseHandle(Handle);
}
}
}
catch
{ }
}
return Value;
}
What I have so far:
private void label1_Click(object sender, EventArgs e)
{
int[] valuesSeperated[200];
List<byte> PreArray = new List<byte>();
Process[] test = Process.GetProcessesByName("MyProcess"); //Get process handle
int baseAddress = test[0].MainModule.BaseAddress.ToInt32(); //Get base address
byte ReadX = MyClass.ReadPointerByte("MyProcess", BaseAddress, new int[] { 0xc, 0x0, 0x2 }); //call memory reading function (including memory offsets)
PreArray.Add(ReadX);
byte[] PreArrayToInt = PreArray.ToArray();
int[] MYConvertedBytes = PreArray ToInt.Select(x => (int)x).ToArray();
foreach (int i in MYConvertedBytes)
{
valuesSeperated // (don't really know what to do here, if the read was successful I would have a long number at [0], so now need to seperate these as if I had read each one in memory one at a time.
}
string TestString = MYConvertedBytes[0].ToString();
label1.Text = TestString;
}
So to summarize: I don't know how to read a larger block of memory (say 200 addresses at once) using the above method. I don't know how best to extract the values from the resulting array to form a new array that has the bytes now separated. Please ask if anything is unclear, I am quite new and really want to learn so any hints/help would be really appreciated.
Your interop signature looks completely wrong to me.
The c signature is:
BOOL WINAPI ReadProcessMemory(
__in HANDLE hProcess,
__in LPCVOID lpBaseAddress,
__out LPVOID lpBuffer,
__in SIZE_T nSize,
__out SIZE_T *lpNumberOfBytesRead
);
It should be something like:
[DllImport("kernel32", EntryPoint = "ReadProcessMemory",SetLastError=true)]
private static extern unsafe bool NativeReadProcessMemory(IntPtr processHandle, IntPtr baseAddress, byte* buffer, IntPtr size, out IntPtr bytesRead);
static unsafe void ReadProcessMemory(IntPtr processHandle, IntPtr baseAddress, byte[] buffer,int start, int size)
{
fixed(byte* pBuffer=buffer)
{
IntPtr bytesRead;
if(!NativeReadProcessMemory(processHandle, baseAddress, pBuffer+start,(IntPtr)size, out bytesRead))
throw new Win32Exception(Marshal.GetLastWin32Error());
if((int)bytesRead!=size)
throw new Exception("Incomplete read");//User better exception type here
}
}

How do I read the names from a PE module's export table?

I've successfully read a PE header from an unmanaged module loaded into memory by another process. What I'd like to do now is read the names of this module's exports. Basically, this is what I have so far (I've left out a majority of the PE parsing code, because I already know it works):
Extensions
public static IntPtr Increment(this IntPtr ptr, int amount)
{
return new IntPtr(ptr.ToInt64() + amount);
}
public static T ToStruct<T>(this byte[] data)
{
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
T result = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
handle.Free();
return result;
}
public static byte[] ReadBytes(this Process process, IntPtr baseAddress, int size)
{
int bytesRead;
byte[] bytes = new byte[size];
Native.ReadProcessMemory(process.Handle, baseAddress, bytes, size, out bytesRead);
return bytes;
}
public static T ReadStruct<T>(this Process process, IntPtr baseAddress)
{
byte[] bytes = ReadBytes(process, baseAddress, Marshal.SizeOf(typeof(T)));
return bytes.ToStruct<T>();
}
public static string ReadString(this Process process, IntPtr baseAddress, int size)
{
byte[] bytes = ReadBytes(process, baseAddress, size);
return Encoding.ASCII.GetString(bytes);
}
GetExports()
Native.IMAGE_DATA_DIRECTORY dataDirectory =
NtHeaders.OptionalHeader.DataDirectory[Native.IMAGE_DIRECTORY_ENTRY_EXPORT];
if (dataDirectory.VirtualAddress > 0 && dataDirectory.Size > 0)
{
Native.IMAGE_EXPORT_DIRECTORY exportDirectory =
_process.ReadStruct<Native.IMAGE_EXPORT_DIRECTORY>(
_baseAddress.Increment((int)dataDirectory.VirtualAddress));
IntPtr namesAddress = _baseAddress.Increment((int)exportDirectory.AddressOfNames);
IntPtr nameOrdinalsAddress = _baseAddress.Increment((int)exportDirectory.AddressOfNameOrdinals);
IntPtr functionsAddress = _baseAddress.Increment((int)exportDirectory.AddressOfFunctions);
for (int i = 0; i < exportDirectory.NumberOfFunctions; i++)
{
Console.WriteLine(_process.ReadString(namesAddress.Increment(i * 4), 64));
}
}
When I run this, all I get is a pattern of double question marks, then completely random characters. I know the header is being read correctly, because the signatures are correct. The problem has to lie in the way that I'm iterating over the function list.
The code at this link seems to suggest that the names and ordinals form a matched pair of arrays, counted up to NumberOfNames, and that the functions are separate. So your loop may be iterating the wrong number of times, but that doesn't explain why you're seeing bad strings from the very beginning.
For just printing names, I'm having success with a loop like the one shown below. I think the call to ImageRvaToVa may be what you need to get the correct strings? However I don't know whether that function will work unless you've actually loaded the image by calling MapAndLoad -- that's what the documentation requests, and the mapping did not seem to work in some quick experiments I did using LoadLibrary instead.
Here's the pInvoke declaration:
[DllImport("DbgHelp.dll", CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurity]
public static extern IntPtr ImageRvaToVa(
IntPtr NtHeaders,
IntPtr Base,
uint Rva,
IntPtr LastRvaSection);
and here's my main loop:
LOADED_IMAGE loadedImage = ...; // populated with MapAndLoad
IMAGE_EXPORT_DIRECTORY* pIID = ...; // populated with ImageDirectoryEntryToData
uint* pFuncNames = (uint*)
ImageRvaToVa(
loadedImage.FileHeader,
loadedImage.MappedAddress,
pIID->AddressOfNames,
IntPtr.Zero);
for (uint i = 0; i < pIID->NumberOfNames; i++ )
{
uint funcNameRVA = pFuncNames[i];
if (funcNameRVA != 0)
{
char* funcName =
(char*) (ImageRvaToVa(loadedImage.FileHeader,
loadedImage.MappedAddress,
funcNameRVA,
IntPtr.Zero));
var name = Marshal.PtrToStringAnsi((IntPtr) funcName);
Console.WriteLine(" funcName: {0}", name);
}
}

Categories