Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

P/invoke function taking pointer to struct [duplicate]

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

like image 992
Tim Lovell-Smith Avatar asked Jul 06 '10 04:07

Tim Lovell-Smith


1 Answers

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.

like image 82
Tim Lovell-Smith Avatar answered Sep 28 '22 17:09

Tim Lovell-Smith