I am working on LOTUS Notes API, during the process i came to a point where the fucntio in like this ,
bytesRead = fread (Buffer, 1, (WORD) Length, hCDFile);
Now i found some C# equivalent method like , which runs inside a while loop .At the first iteration the method seems working fine ( the result are same when i debug c version of code and C# version). But in second iteration say suppose the values of dwLengthHost =35,
before this method i called another method
NSFDUMPReadFromFile(hCDFile, ref RecordTypeCanonicalPtr, sizeof (ushort)) which calls the fread function and give value RecordTypeCanonicalPtr=149 . But after that when same method is called later the RecordTypeCanonicalPtr and dwLengthHost values changes automatically .
[DllImport("msvcrt.dll")]
public static extern UInt32 fread(ref IntPtr Buffer, uint Size, uint Count, IntPtr Stream);
private bool NSFDUMPReadFromFile(IntPtr hCDFile,
ref IntPtr Buffer,
UInt32 Length)
{
UInt32 bytesRead = NotesApi.fread(ref Buffer, 1, (uint)Length, hCDFile);
/* Read bytes from the file */
if (bytesRead == Length)
return true;
else
return false;
}
Look like you need to use FileStream
You can create it by using File.Open
Exactly same behavior as:
bytesRead = fread (Buffer, 1, (WORD) Length, hCDFile);
should provide following C# code
bytesRead = file.Read(Buffer, 0, Length)
full example might be following
using(file = File.Open("test.bin", FileMode.Open))
{
var length = 256;
var buffer = new byte[length];
var bytesRead = file.Read(buffer, 0, length);
}
Related
I'm struggling a bit on this part...
I want to do this in CE!(that is read the value 20 in my c# app)
However my code is not working...
[DllImport("kernel32.dll")]
public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int dwSize, ref IntPtr lpNumberOfBytesRead);
public int ReadInt32(IntPtr address, int[] pointers)
{
/* FOR REFERENCE ONLY! PSEUDO-CODE
ReadProcessMemory(..., ModuleBaseAddress + 0x010F418, Temporary, ..., ...); // -> 0x02A917F8
ReadProcessMemory(..., 0x02A917F8+0x48, Temporary, .....,.); // -> 0x02A9A488
[02A9A488] = 20
*/
IntPtr bytesRead = IntPtr.Zero;
byte[] _buff = new byte[sizeof(int)];
int offIndex = 0;
IntPtr finalval = address;
Console.WriteLine("[BASE] {0:x}", (int)address);
foreach(int PointerOffs in pointers)
{
ReadProcessMemory(hProcess, address, _buff, _buff.Length, ref bytesRead);
finalval += pointers[offIndex];
Console.WriteLine("[Curr ADDRESS] {0:x}", finalval);
offIndex++;
}
return BitConverter.ToInt32(_buff, 0);
}
And this is how I access the method:
int currAmmo = (int) pReader.ReadInt32((IntPtr)LocalPlayer.BaseAddress, LocalPlayer.oMGAmmo);
Console.Write("[AMMO] {0}\n", currAmmo);
Your function has enough problems to warrant a replacement, I tried to fix it but it was easier just to start fresh. By utilizing a pre increment instead of a post increment you will de-reference the first pointer before adding an offset which is ideal.
public static int ReadInt32(IntPtr hProc, IntPtr ptr, int[] offsets)
{
IntPtr addr = ptr;
var buffer = new byte[4];
for (int i = 0; i < offsets.Length; ++i)
{
ReadProcessMemory(hProc, addr, buffer, buffer.Length, out var read1);
addr = IntPtr.Add(new IntPtr(BitConverter.ToInt32(buffer, 0)), offsets[i]);
}
ReadProcessMemory(hProc, addr, buffer, 4, out var read);
return BitConverter.ToInt32(buffer, 0);
}
I learned C# today just to answer this question :)
In C# I have an data type byte[], which I want to fill in using a C++ function which returns char*
The C++ function (in ImageData.dll)
char* pMemoryBuffer = NULL;
char* LoadData(const char *fileName)
{
// processing pMemoryBuffer ...
return pMemoryBuffer;
}
Import native dll into C#:
[DllImport(".\\Modules_Native\\ImageData.dll", EntryPoint = "LoadData")]
private extern static byte[] LoadData(string fileName);
The byte[] data in C#
byte[] buffer = new byte[256*256];
buffer = LoadData("D:\\myPic.tif");
Apparently it is not working yet, but it presents the idea of what I want to do. So I am wondering how to make this work, and what is the right way to do it. Thanks very much for your education.
try this
// c++
void LoadData(unsigned char* *pMemoryBuffer, const char *fileName)
{
// processing pMemoryBuffer ...
*pMemoryBuffer = resutss;
}
Import native dll into C#:
[DllImport(".\\Modules_Native\\ImageData.dll", EntryPoint = "LoadData")]
private extern static void LoadData(out IntPtr data, string fileName);
When the function returns data will point to the array and you can read the contents using the Marshal class. I guess you would copy it to a new byte array.
byte[] buffer = new byte[256*256];
buffer = Marshal.Copy(LoadData(buffer ,"D:\\myPic.tif"), buffer , 0, buffer.Length);
This should do it:
[DllImport(#".\Modules_Native\ImageData.dll")]
private extern static IntPtr LoadData(string fileName);
byte[] buffer = new byte[256*256];
buffer = Marshal.Copy(LoadData("D:\\myPic.tif"), buffer, 0, buffer.Length);
However, it won't free the memory. Hopefully the C(++) library frees it automatically during the next call, or else provides a deallocation function.
A better approach is to use a caller-allocated buffer, then you would just do:
byte[] buffer = new byte[256*256];
LoadData("D:\\myPic.tif", buffer);
For this, the C(++) code would need to be changed to
int LoadData(const char *fileName, char* pMemoryBuffer)
{
// processing pMemoryBuffer ...
return 1; // if success
}
and the p/invoke declaration to
[DllImport(#".\Modules_Native\ImageData.dll")]
private extern static int LoadData(string fileName, byte[] buffer);
I'm not sure, but my gut says that you can't assign a char* to a byte array, just as you can't in C++ itself. You can either use an IntPtr in C# (probably not super useful), OR, you can pass C++ a byte[] buffer and a number of bytes to write. In other words, I think the following would work:
char* pMemoryBuffer = NULL;
int size = 0;
int seek = 0;
bool LoadData(const char* filename)
{
// load filename
// set seek = 0
// set size to data size
}
int ReadData(char* buffer, int nBytesToRead)
{
// nCopyBytes = min(nBytesToRead, size - seek)
// copy nCopyBytes from pMemoryBuffer+seek to buffer
// seek += nCopyBytes
// return nCopyBytes
}
From C#, you'd use it like this:
byte[] buffer = new byte[256*256];
LoadData("foo.tif");
int bytesRead = ReadData(buffer, 256*256);
Sorry if you specifically want to avoid doing something like this.
I have an application that shows a WebBrowser component, which contains a flash application that create a XMLSocket with a server.
I'm now trying to hook recv ( luckly a LocalHook) for log purpuse, but when I try to read the socket content I get only strange chars, but if i set the hook with SpyStudio I get readable strings.
Here is the code I use :
I set the hook with
CreateRecvHook = LocalHook.Create(
LocalHook.GetProcAddress("ws2_32.dll", "recv"),
new Drecv(recv_Hooked),
this);
CreateRecvHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });
I set up everything I need with
[DllImport("ws2_32.dll")]
static extern int recv(
IntPtr socketHandle,
IntPtr buf,
int count,
int socketFlags
);
[UnmanagedFunctionPointer(CallingConvention.StdCall,
CharSet = CharSet.Unicode,
SetLastError = true)]
delegate int Drecv(
IntPtr socketHandle,
IntPtr buf,
int count,
int socketFlags
);
static int recv_Hooked(
IntPtr socketHandle,
IntPtr buf,
int count,
int socketFlags)
{
byte[] test = new byte[count];
Marshal.Copy(buf, test, 0, count);
IntPtr ptr = IntPtr.Zero;
ptr = Marshal.AllocHGlobal(count);
Marshal.Copy(test, 0, ptr, count);
string s = System.Text.UnicodeEncoding.Unicode.GetString(test);
Debug.WriteLine(s);
System.IO.StreamWriter file = new System.IO.StreamWriter("log.txt");
file.WriteLine(s);
file.Close();
return recv(socketHandle, buf, count, socketFlags);;
}
I've already tried using different Encoding without success. As a side note, the WebBrowser doesn't seems to have any problem.
You're saving the content of the uninitialized buffer, no wonder it's garbage.
There is nothing in that buffer until after recv (the real one) fills it in. You also can't know how many bytes are actually valid except by inspecting the return code from the real recv.
This is my c++ code
HANDLE hPipe = ::CreateNamedPipe(_T("\\\\.\\pipe\\FirstPipe"),
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
PIPE_UNLIMITED_INSTANCES,
4096,
4096,
0,
NULL);
ConnectNamedPipe(hPipe, NULL);
DWORD bytesWritten = 0;
WriteFile(hPipe, lpBuffers, sizeof(LPWSABUF), &bytesWritten, NULL);//LPWSABUF is structure and lpBuffers is a variable of this structure
This is my C# code
uint dataLen = (uint)(br.ReadInt32());
string len = (dataLen).ToString();
listBox1.Items.Add(len);
IntPtr dataAdd = IntPtr.Zero;
string data = "";
if (IntPtr.Size == 4) dataAdd = (IntPtr)br.ReadInt32(); //ERROR
else dataAdd = (IntPtr)br.ReadInt64();
byte[] b = new byte[(int)dataLen];
Marshal.Copy(b, 0, dataAdd, (int)dataLen);
data = Encoding.Unicode.GetString(b);
listBox2.Items.Add(data);
In sixth line of C# code giving error.
That End of the stream. I dont have any idea why it is giving error.
Here is the structure
typedef struct _WSABUF {
ULONG len; /* the length of the buffer */
__field_bcount(len) CHAR FAR *buf; /* the pointer to the buffer */
} WSABUF, FAR * LPWSABUF;
LPWSABUF is pointer, its size is 32 or 64 bit. Possibly you mean this:
WriteFile(hPipe, lpBuffers, sizeof(WSABUF), &bytesWritten, NULL);
simply you have reached end of stream so end of stream exception is thrown.
If it's the first read command from file then your file is empty
I have this method that I need to call and use in my application, but I don't know really know how to do it exactly.
This is the function that I need to call.
[DllImport(dll_Path)]
public static extern int DTS_GetDataToBuffer(int Position, int Length, char* Buffer, int* DataRead);
In my code, I have this function and I'm missing its implementation.
internal static void GetDataToBuffer(int position, int length, out byte[] data, out int dataRead)
{
unsafe
{
// the code I need
}
}
I think most of this is very selfexplanatory. I need to implement the latter function so I can be able to read the data into the buffer and the amount of data read (which should actually be the same as data.Length, but the manufacturer has this as separate option, so I need it).
Can anyone help? Is this clear enough?
Thank you
Edit: Here is the unmanaged declaration from the .h file. Hope it helps.
extern NAG_DLL_EXPIMP int DTS_GetDataToBuffer(int Position,
int Length,
unsigned char *Buffer,
int *DataRead );
Edit #2:
Positon - the position from which to star reading the data.
Length - The amount of data to read (this would be the buffer size).
DataRead - the actual data size that was read.
I don't think you really need to use unsafe pointers here.
Declare function as
[DllImport(dll_Path)]
public static extern int DTS_GetDataToBuffer(
int position,
int length,
byte[] buffer,
ref int dataRead);
Reasonable C# wrapper for this function:
internal static byte[] GetDataToBuffer()
{
// set BufferSize to your most common data length
const int BufferSize = 1024 * 8;
// list of data blocks
var chunks = new List<byte[]>();
int dataRead = 1;
int position = 0;
int totalBytes = 0;
while(true)
{
var chunk = new byte[BufferSize];
// get new block of data
DTS_GetDataToBuffer(position, BufferSize, chunk, ref dataRead);
position += BufferSize;
if(dataRead != 0)
{
totalBytes += dataRead;
// append data block
chunks.Add(chunk);
if(dataRead < BufferSize)
{
break;
}
}
else
{
break;
}
}
switch(chunks.Count)
{
case 0: // no data blocks read - return empty array
return new byte[0];
case 1: // single data block
if(totalBytes < BufferSize)
{
// truncate data block to actual data size
var data = new byte[totalBytes];
Array.Copy(chunks[0], data, totalBytes);
return data;
}
else // single data block with size of Exactly BufferSize
{
return chunks[0];
}
default: // multiple data blocks
{
// construct new array and copy all data blocks to it
var data = new byte[totalBytes];
position = 0;
for(int i = 0; i < chunks.Count; ++i)
{
// copy data block
Array.Copy(chunks[i], 0, data, position, Math.Min(totalBytes, BufferSize));
position += BufferSize;
// we need to handle last data block correctly,
// it might be shorted than BufferSize
totalBytes -= BufferSize;
}
return data;
}
}
}
I can't test this but I think you should let the Marshaler do you conversion(s):
[DllImport(dll_Path)]
public static extern int DTS_GetDataToBuffer(out byte[] data, out int dataRead);
i agree you don't need to use unsafe block. you are using pinvoke, i hope below links might be useful :
http://msdn.microsoft.com/en-us/magazine/cc164123.aspx
http://www.pinvoke.net/
and there are post on stackoverflow too