I'm trying to read a process's memory, but the address I would like to start reading from exceeds the IntPtr and UIntPtr limit.
[DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")]
private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, [Out] int lpNumberOfBytesRead);
ReadProcessMemory(ProcessHandle, (IntPtr)0x14EC7B38A, buffer, buffer.Length, bytesused);
Doing this produces a OverflowException exception even if I use a UIntPtr. I have tried using a ulong, but this produces an AccessViolationException exception. What other data type should I use?
Windows is a 64-bit OS. UInt is 64bits wide. I assume the problem is that your application is either built for 32bit or is built to "Prefer 32bit" (the Visual Studio defaults).
This answer has the details of the setting you want to change.
Related
I'm using a Silicon Labs VCP (CP2105) under Windows (7/8/10) and I am trying to obtain some info from it using the Silicon Labs runtime DLL - which is unmanaged.
This is my implementation:
[DllImport("CP210xRuntime.dll")]
private static extern Int32 CP210xRT_GetDeviceProductString(IntPtr handle, IntPtr bfPtr, ref uint len, bool convert);
public static Int32 GetProduct(IntPtr handle)
{
var buff = new char[100];
GCHandle hnd = GCHandle.Alloc(buff);
IntPtr bfPtr = (IntPtr)hnd;
uint bytesRead = 0;
var r = CP210xRT_GetDeviceProductString(handle, bfPtr, ref bytesRead, true);
hnd.Free();
return r;
}
I am getting the device handle for the ports using:
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateFile(
string FileName,
uint DesiredAccess,
uint ShareMode,
IntPtr SecurityAttributes,
uint CreationDisposition,
uint FlagsAndAttributes,
IntPtr hTemplateFile
);
When I run this it works - of sorts, that is to say the return value is 0 which, according to the Silicon Labs docs, indicates all is well, and I have confirmed this by using a handle to another device and I got 3 back, which confirms invalid handle.
The bytesRead ref value is also ammended as expected to 36 which is what the length of the product name should be. But the buff array never fills with any data (just to be sure I have written values to each element as well but they dont change). If I leave the program running the whole thing throws an exception:
Managed Debugging Assistant 'FatalExecutionEngineError' has detected a problem in********
Additional information: The runtime has encountered a fatal error. The address of the error was at 0x70338780, on thread 0x1f5c. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.
This is also the program does, if I comment out the line where I call the function from the dll - the program does not fail.
I'm not massively familar with invoke unmanged code using C# so if someone could help me out with where I am going wrong / point me in the right direction I would be most grateful!
This is from the Silicon Labs Docs:
CP210x_STATUS CP210xRT_GetDeviceProductString(HANDLE cyHandle,
LPVOID lpProduct, LPBYTE lpbLength, BOOL bConvertToASCII = TRUE)
I was using the SendMessage native method in my sample. Please find the native method declaration below,
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
But when declare the above native method in my sample, it shows the warning(CA1901 - P/Invoke declarations should be portable). It shows the warning like "the parameter lParam in method will be 4 bytes wide on 64-bit platforms. This is not correct, as the actual native declaration of this API indicates it should be 8 bytes wide on 64-bit platforms.
So how we can solve this above FxCop warning, and also please suggest how we can know the actual size of the parameter based on the 32 bit and 64 bit platforms?
You should use the following declaration:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
I am trying to use this function, but I don't have shcore.dll and I can't figure out where to get it. Is shcore.dll just a Windows 10 DLL?
[DllImport("Shcore.dll")]
internal static extern IntPtr GetDpiForMonitor(
[In] IntPtr hmonitor,
[In] MonitorDpiType dpiType,
[Out] out uint dpiX,
[Out] out uint dpiY);
It is not available on Windows 7.
Windows 8.1 or newer is required based on Microsoft's documentation.
This question already has answers here:
Target 32 Bit or 64 Bit native DLL depending on environment
(3 answers)
DllImport - An attempt was made to load a program with an incorrect format [duplicate]
(1 answer)
Closed 8 years ago.
The community reviewed whether to reopen this question 8 months ago and left it closed:
Original close reason(s) were not resolved
I want my C# application to conditionally run a native method, conditionally choosing to run either the x86 or the x64 version of the dll. Whenever I try to load the 32 bit dll I get the below error:
Unhandled Exception: System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
at <exeName>.MiniDumpMethods.MiniDumpWriteDumpX86(IntPtr hProcess, UInt32 processId, SafeHandle hFile, MINIDUMP_TYPE dumpType, IntPtr expParam, IntPtr userStreamParam, IntPtr callbackParam)
Background context: I want my binary to take a memory dump of a given process. Based on whether or not the process it's taking a memory dump of is 32 or 64 bit it'll choose to run the MiniDumpwriteDump method from the x86 or x64 version of dbghelp.dll.
I'm currently doing the following:
[SuppressUnmanagedCodeSecurity]
internal static class MiniDumpMethods
{
[DllImport("dbghelp.dll",
EntryPoint = "MiniDumpWriteDump",
CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Unicode,
ExactSpelling = true,
SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool MiniDumpWriteDump(
IntPtr hProcess,
uint processId,
SafeHandle hFile,
MINIDUMP_TYPE dumpType,
IntPtr expParam,
IntPtr userStreamParam,
IntPtr callbackParam);
[DllImport("dbghelpx86.dll",
EntryPoint = "MiniDumpWriteDump",
CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Unicode,
ExactSpelling = true,
SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool MiniDumpWriteDumpX86(
IntPtr hProcess,
uint processId,
SafeHandle hFile,
MINIDUMP_TYPE dumpType,
IntPtr expParam,
IntPtr userStreamParam,
IntPtr callbackParam);
}
Any idea how I can conditionally load either the x86 or the x64 version of the dll?
(Note: dbghelpx86.dll is the x86 version of dbghelp.dll that I renamed)
Thanks
You cannot load a 32 bit DLL into a 64 bit process. To support this you will have to have two different EXE's, one compiled as 64 bit and one compiled as 32 bit.
If you run the 64 bit process and encounter a 32 bit dump, you'll have to launch the 32 bit version of the EXE to process the dump file. Once it is processed you can use some sort of IPC (Interprocess Communication) mechanism to send the results back to the 64 bit process.
I have a 32-bit app that makes use of Java Accessibility (WindowsAccessBridge-32.dll, via the Java Access Bridge), and works perfectly on a 32-bit machine, but fails on an x64 machine.
I believe I have tracked it down to one of the first calls after Windows_run:
getAccessibleContextFromHWND(hwnd, out vmId, out context)
defined as follows:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("WindowsAccessBridge-32.dll", CallingConvention = CallingConvention.Cdecl)]
public extern static bool getAccessibleContextFromHWND(IntPtr hwnd, out Int32 vmID, out IntPtr acParent);
This call works fine on the 32-bit system, returning True, populating both vmId (with some 5-digit value, which), and context - whereas on the 64-bit system, it returns True, populates 'context', but returns '0' for vmId.
If I assume that 0 is valid (even though it's a random 5-digit number resembling a pointer on the 32-bit system), the next call still fails:
AccessibleContextInfo aci = new API.AccessibleContextInfo();
if (!getAccessibleContextInfo(vmId, context, ref aci))
throw new Exception();
where:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("WindowsAccessBridge-32.dll", CallingConvention = CallingConvention.Cdecl)]
public extern static bool getAccessibleContextInfo(Int32 vmID, IntPtr ac, ref AccessibleContextInfo info);
(I'm omitting the AccessibleContextInfo struct for brevity, but I can provide it if necessary).
I know that the libraries are working, because both JavaMonkey and JavaFerret work correctly. Furthermore, call to isJavaWindow works, returning 'true', or 'false' as appropriate, and I am linking to the correct DLL (WindowsAccessBridge-32).
Can anyone suggest what may be wrong here?
It appears that the problem is in the type of AccessibilityContext:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("WindowsAccessBridge-32.dll", CallingConvention = CallingConvention.Cdecl)]
public extern static bool getAccessibleContextFromHWND(IntPtr hwnd, out Int32 vmID, out IntPtr acParent);
AccessibilityContext (acParent above), which I had incorrectly mapped as an IntPtr, is actually an Int32 when using the "legacy" WindowsAccessBridge.dll library (used under x86), and an Int64 when using the WOW64 WindowsAccessBridge-32.dll library.
So the upshot is, the code has to differ between x86 and WOW x64, and must be compiled separately for each. I do this by #define'ing WOW64 during x64 builds, always referencing the Int64 methods, and using "shim" methods on x86:
#if WOW64 // using x64
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("WindowsAccessBridge-32.dll", CallingConvention = CallingConvention.Cdecl)]
public extern static bool getAccessibleContextFromHWND(IntPtr hwnd, out Int32 vmID, out Int64 acParent);
#else // using x86
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("WindowsAccessBridge.dll", EntryPoint = "getAccessibleContextFromHWND", CallingConvention = CallingConvention.Cdecl)]
private extern static bool _getAccessibleContextFromHWND(IntPtr hwnd, out Int32 vmID, out Int32 acParent);
public static bool getAccessibleContextFromHWND(IntPtr hwnd, out Int32 vmID, out Int64 acParent)
{
Int32 _acParent;
bool retVal = _getAccessibleContextFromHWND(hwnd, out vmID, out _acParent);
acParent = _acParent;
return retVal;
}
#endif
If your using a 64 bit JVM with a 32 bit version of the Java Access bridge it won't work correctly. You need a 64 bit version of the access bridge which has recently been released. see
http://blogs.oracle.com/korn/entry/java_access_bridge_v2_0
For instructions on installing a 32 bit copy of the access bridge for use with 32 bit JRE's under 64 bit windows see
http://www.travisroth.com/2009/07/03/java-access-bridge-and-64-bit-windows/
The call to 'initializeAccessBridge' REQUIRES you to have an active windows message pump.
Inside 'initializeAccessBridge', it (eventually) creates a hidden dialog window (using CreateDialog). Once the dialog is created, it performs a PostMessage with a registered message. The JavaVM side of the access bridge responds to this message, and posts back another message to the dialog that was created (it appears to be a 'hello' type handshake between your app and the java VM). As such, if your application doesn't have an active message pump, the return message from the JavaVM never gets received by your app.