convert C++ code to C#: SendMessageTimeout() - c#

First of all docu for SendMessageTimeout:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644952%28v=vs.85%29.aspx
i have this C++ code and i want to convert it to C#:
LRESULT success = SendMessageTimeout(
HWND_BROADCAST,
WM_SETTINGCHANGE,
0,
(LPARAM) "Environment",
SMTO_ABORTIFHUNG,
5000,
NULL
);
What i did in C#:
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
IntPtr hWnd,
uint Msg,
UIntPtr wParam,
IntPtr lParam,
uint fuFlags,
uint uTimeout,
out UIntPtr lpdwResult
);
SendMessageTimeout(
(IntPtr)0xFFFFFFFF, //HWND_BROADCAST
0x001A, //WM_SETTINGCHANGE
(UIntPtr)0,
(IntPtr)"Environment", // ERROR_1: can't convert string to IntPtr
0x0002, // SMTO_ABORTIFHUNG
5000,
out UIntPtr.Zero // ERROR_2: a static readonly field can not be passed ref or out
);

For your issues.
HWND_BROADCAST is 0xFFFF not 0xFFFFFFFF
You will have to allocate memory for the LPARAM value manually using Marshal.StringToHGlobalUni and then free it after the call using Marshal.FreeHGlobal. You must free this memory or it will leak. Marshal'd memory is not garbage collected.
For lpdwResult just create an IntPtr variable and pass that in. You can just ignore its value.
The code should be something like this:
IntPtr result = IntPtr.Zero;
IntPtr setting = Marshal.StringToHGlobalUni("Environment");
SendMessageTimeout(
(IntPtr)0xFFFF, //HWND_BROADCAST
0x001A, //WM_SETTINGCHANGE
(UIntPtr)0,
(IntPtr)setting,
0x0002, // SMTO_ABORTIFHUNG
5000,
out result
);
Marshal.FreeHGlobal(setting);
In general you need to be careful when freeing memory that you pass to a SendMessage call since you don't know what the receving window will do with the pointer that you pass to it. Howerver since WM_SETTINGCHANGE is a built in Windows message, Windows will handle this pointer for you.

SendMessage is a bit painful due to the non-descript argument types it uses. Necessary because it needs to do many jobs. Necessary in the C language, but not in C#. What you want to do here is take advantage of the C# language supporting overloads. The IntPtr arguments can just be reference type references, the pinvoke marshaller will properly convert them to a pointer and take care of the memory management hassle. So just craft another one that's compatible with the way you want to use it:
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
IntPtr hWnd,
int Msg,
IntPtr wParam,
string lParam,
int fuFlags,
int uTimeout,
IntPtr lpdwResult
);
Now you can use:
SendMessageTimeout((IntPtr)0xffff, 0x001A, IntPtr.Zero, "Environment",
2, 5000, IntPtr.Zero);

Related

What is the hex value of PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON?

I would like to use the UpdateProcThreadAttribute() API call in a C# program, but I can't find the hex value of PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON. I was only able to find (0x00000001ui64 << 44) on Microsoft's website, but I don't know how I can implement this into my code and use it as an IntPtr, according to PInvoke.net.
In C/C++, 0x00000001ui64 is an unsigned 64bit integer with a value of 1, and << 44 is left-shifting that value by 44 bits. A left-shift is equivalent to multiplying by 2, so the result of multiplying 1 by 2 44 times is 17592186044416, which in hex is 0x100000000000UL, or 0x1000_0000_0000UL for readibility.
FYI, C# has the same bit-shift operators that C/C++ has.
LPPROC_THREAD_ATTRIBUTE_LIST is a pointer to a PROC_THREAD_ATTRIBUTE_LIST structure. Call InitializeProcThreadAttributeList() 1 time to determine how large that list needs to be, then allocate memory of that size, and call InitializeProcThreadAttributeList() again to initialize the list.
For example (also see .NET : How to PInvoke UpdateProcThreadAttribute):
const int PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY = 0x20007;
const long PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON = 0x100000000000L;
[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool InitializeProcThreadAttributeList(
IntPtr lpAttributeList,
int dwAttributeCount,
int dwFlags,
ref IntPtr lpSize);
[DllImport("kernel32.dll", SetLastError=true)]
public static extern bool DeleteProcThreadAttributeList(IntPtr lpAttributeList);
[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UpdateProcThreadAttribute(
IntPtr lpAttributeList,
uint dwFlags,
IntPtr Attribute,
IntPtr lpValue,
IntPtr cbSize,
IntPtr lpPreviousValue,
IntPtr lpReturnSize);
...
IntPtr attrListSize = 0;
InitializeProcThreadAttributeList(
IntPtr.Zero,
1,
0,
ref attrListSize);
IntPtr attrList = Marshal.AllocHGlobal(attrListSize);
InitializeProcThreadAttributeList(
attrList,
1,
0,
ref attrListSize);
IntPtr lpValue = Marshal.AllocHGlobal(sizeof(long));
Marshal.WriteInt64(lpValue, PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON);
UpdateProcThreadAttribute(
attrList,
0,
(IntPtr)PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY,
lpValue,
sizeof(long),
IntPtr.Zero,
IntPtr.Zero
);
// use attrList as needed, ie in STARTUPINFOEX.lpAttributeList ...
DeleteProcThreadAttributeList(attrList);
Marshal.FreeHGlobal(lpValue);
Marshal.FreeHGlobal(attrList);

C# WriteProcessMemory strange stackoverflow exception

I'm using WinAPI function WriteProcessMemory from kernel32.dll to write to another process' memory.
It worked good for a few times, but then it just stopped working correctly.
I'm importing this function with this code:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out int lpNumberOfBytesWritten);
And here's code that I'm using to write:
int bytesWritten;
WriteProcessMemory(hProcess, (IntPtr)dwAdress, data, (uint)size, out bytesWritten);
It just throws this exception:
System.OverflowException
Debug info:
debug info
Can anyone help me with this problem?
Your p/invoke is declared incorrectly. The final two parameters are SIZE_T, which is pointer sized. Your code should be:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
byte[] lpBuffer,
UIntPtr nSize,
out UIntPtr lpNumberOfBytesWritten
);
Note that SIZE_T is an unsigned type, hence the use of UIntPtr. If using an unsigned type is not convenient you could switch the above to use IntPtr instead since you are never going to write more then 263 bytes.
The code that you presented does not test the return value of WriteProcessMemory. Please always checked return values for errors. For instance:
if (!WriteProcessMemory(...))
throw new Win32Exception();

Does .NET interop cache the generated unmanaged thunks to managed method?

For example, I use unmanaged Win32 timer:
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void TimerProc(IntPtr hWnd, uint uMsg, IntPtr nIDEvent, uint dwTime);
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr SetTimer(IntPtr hWnd, IntPtr nIDEvent,
uint uElapse, TimerProc lpTimerFunc);
// ...
TimerProc timerProc = delegate { this.Beep(); };
// ...
var timerId = NativeMethods.SetTimer(IntPtr.Zero, IntPtr.Zero, 500, timerProc);
I wonder if the unmanaged pointer for lpTimerFunc which is passed to the actual SetTimer API remains the same for as longs as the managed timerProc remians the same, no matter how many times I call NativeMethods.SetTimer? Or does a new unmanaged thunk get generated for timerProc each time I call NativeMethods.SetTimer?
Each delegate will have its own thunk, so it depends on how you create your delegate. If you create a new delegate each time you call SetTimer, you'll have lots of them. If create it once for your class, you'll only have one.

Memory access violation while passing void* param to DLL function

I'm adding new disk device to system from my C# code, so I want to call
[System.Runtime.InteropServices.DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public extern static void SHChangeNotify(long wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2);
like below
MyWin32Functions.SHChangeNotify(0x00000100/*ADDRIVE*/, 0x0005/*PATHW*/, driveLetter, IntPtr.Zero);
dwItem1 is void* and we should pass a wchar_t* (pointing to null terminated string) containing drive root in this case; so driveLetter above is
string letter = "Z:\\";
byte[] data = Encoding.Default.GetBytes(letter);
byte[] zdata = new byte[data.Length + 1];
data.CopyTo(zdata, 0);
IntPtr p = System.Runtime.InteropServices.Marshal.AllocHGlobal(zdata.Length);
System.Runtime.InteropServices.Marshal.Copy(zdata, 0, p, zdata.Length);
(my code almost same as code in similiar case: How to call SHChangeNotify from C# without error 14007
but I get System.AccessViolationException)
Any suggestions what am I doing wrong?
The first parameter in your interop signature should be an int, not a long. Though the Win32 function is declared as LONG, a LONG in Win32 is 32-bit.
[System.Runtime.InteropServices.DllImport("Shell32.dll")]
public extern static void SHChangeNotify(int wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2);
This MSDN article shows the common mapping between Win32 types an .NET types for Platform Invoke.

Writing a memory scanner in C#

I'm trying to make a memory scanner in C#. I heard that I need the API functions WriteProcessMemory and ReadProcessMemory.
I called them :
[DllImport("kernel32.dll")]
public static extern bool ReadProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
byte[] lpBuffer,
UInt32 nSize,
ref UInt32 lpNumberOfBytesRead
);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
byte[] lpBuffer,
uint nSize,
out UIntPtr lpNumberOfBytesWritten);
All the examples for memory scanners I found on Google were very hard to understand. I've read a lot of articles saying that to find value addr you need to search at any memory byte. Now I need to get the program to open the process for reading and writing from memory.
Can I do that with GetProcessByName?
Yes, like so:
Process[] process = Process.GetProcessesByName("cmd");
byte[] memory = new byte[255];
uint bytesRead =0;
bool succes = ReadProcessMemory(
process[0].Handle,
process[0].MainModule.BaseAddress ,
memory ,
(uint) memory.Length ,
ref bytesRead);
You have to check if success is true. If not you have read nothing.

Categories