Well, there are at least two bugs in this method:
1.) This one I fixed some time ago in my personal version. If you call a method on the mobile device, which doesn't return any data, Invoke() will crash, because it always tries to copy data from the receiving buffer to a byte array. A fix would be, to check the receiving data size, whether it's zero.
2.) This is the really major one. It just cost me about 2 days to try to fix an VB.Net application, that uses RAPI.Invoke() and has thrown around some strange MemoryAccessViolation Exceptions when accessing a simple property. The problem is, that somebody used Marshal.WriteInt16 to move data from a Byte-Array to a unmanaged allocated memory with the size of the Byte-Array. This caused some serious chaos in memory and it looks like the code (or its author) wanted to remind us how awful unmanaged programming can be. ^^ The fix on the other hand is an easy one, by just exchanging WriteInt16 with WriteByte.
I also made some other changes to this method, mainly to give it some form of exception handling, if for example the called exe/dll/method is missing.
public int Invoke(string DLLPath, string FunctionName, byte[] InputData, out byte[] OutputData)
{
// RAPI memory management is non-intuitive
// you must allocate the input variable with LocalAlloc and then RAPI will release them
// you must also call LocalFree on the output buffer though you never call LocalAlloc
CheckConnection();
uint recvSize = 0;
IntPtr recvData = IntPtr.Zero;
// create a pointer to hold incoming data - RAPI will free this internally
IntPtr sendData = Marshal.AllocHGlobal(InputData.Length);
// copy outgoing data to the pointer - too bad we don't have a memcpy fcn
for (int i = 0; i < InputData.Length; i++)
{
Marshal.WriteByte(sendData, i, InputData[i]);
}
// call the RAPI function
int hresult = CeRapiInvoke(DLLPath, FunctionName, (uint)InputData.Length, sendData, out recvSize, out recvData, IntPtr.Zero, 0);
try
{
System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hresult);
}
catch
{
throw;
}
if (recvSize != 0)
{
// allocate our managed array
OutputData = new byte[recvSize];
// copy the returned data from unmanaged to managed memory
Marshal.Copy(recvData, OutputData, 0, (int)recvSize);
}
else
{
OutputData = null;
}
// RAPI called LocalAlloc on this internally so we must free it
Marshal.FreeHGlobal(recvData);
return hresult;
}