Call Win32 CalculatePopupWindowPosition from C# - c#

I'm trying to call the WinAPI function CalculatePopupWindowPosition in C# using P/Invoke. From
http://msdn.microsoft.com/en-us/library/windows/desktop/dd565861(v=vs.85).aspx
I see that it's syntax is:
BOOL WINAPI CalculatePopupWindowPosition(
_In_ const POINT *anchorPoint,
_In_ const SIZE *windowSize,
_In_ UINT flags,
_In_opt_ RECT *excludeRect,
_Out_ RECT *popupWindowPosition
);
I then tried to import it using the following code in C#
[DllImport("User32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool CalculatePopupWindowPosition
(
[In] ref POINT anchorPoint,
[In] ref SIZE windowSize,
[In] ref UInt32 flags,
[In,Optional] ref RECT excludeRect,
[Out] out SIZE popupWindowPosition
);
I also implemented the RECT, POINT and SIZE structures and initialized them. Finally I called the function like so.
CalculatePopupWindowPosition(ref nIconPos, ref windowSize, ref flags, ref nIconRect, out windowSize);
This doesn't seem to work though, windowSize contains nothing but zeros, which it shouldn't. Any ideas what I'm doing wrong here?

The flags parameter needs to be passed by value rather than by reference:
[DllImport("User32.dll", SetLastError = true)]
public static extern bool CalculatePopupWindowPosition
(
ref POINT anchorPoint,
ref SIZE windowSize,
uint flags,
ref RECT excludeRect,
out RECT popupWindowPosition
);
Some general advice. When an API call fails, check the return value. In this case if the function returns false then call Marshal.GetLastWin32Error to find out the error status code.

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();

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.

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

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);

DLLImport -> how to handle a HANDLE in C#

in my C# code I want to import a C++ DLL. I use the dllimport and it works fine with a some of the functions. But in one function I get a HANDLE which I need later to call another function.
[DllImport("SiUSBXp.dll")]
public static extern int SI_Open(UInt32 deviceNum,ref IntPtr devHandle ); // this function gets the HANDLE
[DllImport("SiUSBXp.dll")]
public static extern int SI_Write([In]IntPtr devHandle, [In, Out] byte[] inputByte, UInt32 size,ref UInt32 bytesWritten); // this function needs the HANDLE
In my code these functions are called like this:
IntPtr devHandle = new IntPtr();
UInt32 bytesWritten = new UInt32();
byte[] byteArr = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
SI_Open(0, ref devHandle);
SI_Write(devHandle, byteArr, 10, ref bytesWritten);
If I do it like this I get an "System.AccessViolationException". I searched here and in the internet but didnt find a specific answer. How do I use the IntPtr correctly, so it works?
Best Regards
Toby
Your SI_Write function looks quite like Windows Kernel32's WriteFile.
So, I would do this:
[DllImport("SiUSBXp.dll", SetLastError = true)]
static extern int SI_Open(uint dwDevice, ref IntPtr cyHandle);
[DllImport("SiUSBXp.dll", SetLastError = true)]
static extern int SI_Write(IntPtr cyHandle, byte[] lpBuffer,
uint dwBytesToWrite, out uint lpdwBytesWritten);
EDIT: I found this documentation USBXPRESS® PROGRAMMER’S GUIDE on the web, and it states that the SI_Write prototype looks actually much closer to WriteFile than I thought. The doc states this:
SI_STATUS SI_Write (HANDLE Handle, LPVOID Buffer, DWORD NumBytesToWrite,
DWORD *NumBytesWritten, OVERLAPPED* o = NULL)
It means the .NET prototype should be this instead:
[DllImport("SiUSBXp.dll")]
static extern int SI_Write(IntPtr Handle, byte[] Buffer,
uint NumBytesToWrite, out uint NumBytesWritten, IntPtr o);
o is optional so you can pass IntPtr.Zero.
You are making a classic C programmer mistake, you don't check the return value of the functions. Which tells you whether or not the function failed. A likely scenario is that SI_Open() returned a failure code. You ignore it and use the uninitialized handle value anyway. A kaboom is not unusual.
The next possible mistake is that you don't use the CallingConvention property in the [DllImport] statement. It is fairly likely to be needed, Cdecl is the default unless the native function is declared with __stdcall. Also an excellent way to invoke a kaboom. If you still have trouble then you are going to have to debug the native code.
Btw, you get rid of the awkward syntax by using out instead of ref. In both functions.
[DllImport("SiUSBXp.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int SI_Open(UInt32 deviceNum, out IntPtr devHandle );
try this:
[DllImport("SiUSBXp.dll")]
public static extern int SI_Open(UInt32 deviceNum, ref IntPtr devHandle); // this function gets the HANDLE
[DllImport("SiUSBXp.dll")]
public static extern int SI_Write(IntPtr devHandle, ref byte[] inputByte, UInt32 size, ref UInt32 bytesWritten); // this function needs the HANDLE
EDIT:
#Hans Passant is right. This is the correct way to pass a byte[] into a LPVOID parameter. ref used to coerce an object into LPVOID, but isn't needed for an array. What happens when you try this?
[DllImport("SiUSBXp.dll")]
public static extern int SI_Write(IntPtr devHandle, byte[] inputByte, UInt32 size, ref UInt32 bytesWritten); // this function needs the HANDLE
Did you try the answer #Simon Mourier gave? He was first to provide this declaration and his answer deserves to be accepted.
bad: static extern void DoStuff(**byte[] inputByte**);
good: static extern void DoStuff(**[In, MarshalAs(UnmanagedType.LPArray)] byte[] inputByte**);

Categories