如何为pinvoke调用的结构分配空值?

Bob*_*Bob 5 c# pinvoke struct marshalling

我想打电话给LsaOpenPolicy,它需要一个LSA_OBJECT_ATTRIBUTES结构。我正在使用来自pinvoke.net的结构定义。该结构具有领域public LSA_UNICODE_STRING ObjectName;

LSA_OBJECT_ATTRIBUTESMSDN文章说:

当您调用时LsaOpenPolicy,将此函数的成员初始化为NULL或零,因为该函数不使用该信息。

特别是:

对象名

    应该为NULL

虽然我可以将LSA_OBJECT_ATTRIBUTESstruct 的其他字段分配给IntPtr.Zero(或仅将其分配给0值类型),但看不到的方法ObjectName。特别,

无法将类型'System.IntPtr'隐式转换为'LSA_UNICODE_STRING'

在这种情况下我该怎么办?我应该初始化LSA_UNICODE_STRING长度为零(长度0,最大长度0,空/空缓冲区)的a吗?我应该更改LSA_OBJECT_ATTRIBUTES定义以便该字段为IntPtr吗?我应该使它为可空值并分配null给该字段吗?

我对内存管理的经验很少,因此对于可能导致内存泄漏的任何事情我都非常警惕。

Dav*_*nan 5

声明LSA_UNICODE_STRING为 aclass而不是 a struct。通过这样做,你使它成为一个引用类型。这与LSA_OBJECT_ATTRIBUTES因为ObjectName具有PLSA_UNICODE_STRING指向结构的指针的类型的声明相匹配。您确实需要指定LayoutKind.Sequential何时执行此操作,因为这不是类的默认设置。进行此更改后,您可以将变量设置为null.

[StructLayout(LayoutKind.Sequential)]
class PLSA_UNICODE_STRING 
{
    public UInt16 Length;
    public UInt16 MaximumLength;
    public IntPtr Buffer;
}
Run Code Online (Sandbox Code Playgroud)

您可以采用相同的策略LSA_OBJECT_ATTRIBUTES来允许将其作为null.

[StructLayout(LayoutKind.Sequential)]
class PLSA_OBJECT_ATTRIBUTES
{
   public uint Length;
   public IntPtr RootDirectory;
   public PLSA_UNICODE_STRING ObjectName;
   public uint Attributes;
   public IntPtr SecurityDescriptor;
   public IntPtr SecurityQualityOfService;
}

[DllImport("advapi32.dll")]
static extern uint LsaOpenPolicy(
    PLSA_UNICODE_STRING SystemName,
    PLSA_OBJECT_ATTRIBUTES ObjectAttributes,
    uint DesiredAccess,
    out IntPtr PolicyHandle
);
Run Code Online (Sandbox Code Playgroud)

请注意,pinvoke.netSetLastError=true上的声明错误地使用了on LsaOpenPolicy。这是错误的,因为错误代码在返回值中返回。我还删除了PreserveSigto的设置,true因为这是默认设置。他们的声明LSA_OBJECT_ATTRIBUTES也似乎是错误的,因为ObjectName参数的类型LSA_UNICODE_STRING是结构而不是指向它的指针。

我建议您以极度怀疑的态度对待您在 pinvoke.net 上找到的内容。该网站上的大部分声明都是错误的。

您询问使用可为空类型的可能性。根据@JaredPar 的回答,这不是一个选项。