Functions such as CreateProcess have signatures taking pointers to structs. In C I would just pass NULL as a pointer for the optional parameters, instead of creating a dummy struct object on the stack and passing a pointer to the dummy.
In C#, I have declared it as (p/invoke)
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern bool CreateProcess(
            string lpApplicationName,
            string lpCommandLine,
            ref SECURITY_ATTRIBUTES lpProcessAttributes,
            ref SECURITY_ATTRIBUTES lpThreadAttributes,
            bool bInheritHandles,
            CreateProcessFlags dwProcessCreationFlags,
            IntPtr lpEnvironment,
            string lpCurrentDirectory,
            ref STARTUPINFO lpStartupInfo,
            ref PROCESS_INFORMATION lpProcessInformation);
But if I try to pass null for the lpProcessAttributes argument or lpThreadAttributes argument, I get a compiler error:
Error 2 Argument 3: cannot convert from '<null>' to 'ref Debugging.Wrappers.SECURITY_ATTRIBUTES'
How can I modify the above function signature so that I can just pass null for the SECURITY_ATTRIBUTES arguments, without this compiler error? (And also be able to pass a real struct if I want to?)
OK, I finally(!) found an even better way of doing this:
Declare SECURITY_ATTRIBUTES as class instead of struct and don't pass it by ref. :-)
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool CreateProcess(
        string lpApplicationName,
        StringBuilder lpCommandLine,
        SECURITY_ATTRIBUTES lpProcessAttributes,
        SECURITY_ATTRIBUTES lpThreadAttributes,
        bool bInheritHandles,
        CreateProcessFlags dwCreationFlags,
        IntPtr lpEnvironment,
        string lpCurrentDirectory,
        STARTUPINFO lpStartupInfo, /// Required
        PROCESS_INFORMATION lpProcessInformation //Returns information about the created process
        );
/// <summary>
/// See http://msdn.microsoft.com/en-us/library/aa379560(v=VS.85).aspx
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public class SECURITY_ATTRIBUTES
{
    public uint nLength;
    public IntPtr lpSecurityDescriptor;
    [MarshalAs(UnmanagedType.Bool)] public bool bInheritHandle;
}
Bonus: this also lets you declare a decent constructor on SECURITY_ATTRIBUTES which initializes nLength.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With