2013-06-04 110 views
4

我想打電話給LsaOpenPolicy,它需要一個LSA_OBJECT_ATTRIBUTES結構。我正在使用the struct definition from pinvoke.net。該結構具有字段public LSA_UNICODE_STRING ObjectName;如何爲一個pinvoke調用分配一個空值給一個結構體?

LSA_OBJECT_ATTRIBUTES MSDN文章說:

當你調用LsaOpenPolicy,這種結構的成員初始化爲NULL 爲零,因爲該功能不使用這些信息。

而具體:

對象名

       應該NULL

雖然我可以分配LSA_OBJECT_ATTRIBUTES結構的其他領域IntPtr.Zero(或只是簡單的0的值類型),我看不到的方式來爲ObjectName這樣做。具體來說,

無法隱式轉換類型 'System.IntPtr' 到 'LSA_UNICODE_STRING'

我應該在這種情況下怎麼辦?我是否應該初始化一個長度爲零(長度爲0,最大長度爲0,空/空緩衝區)的LSA_UNICODE_STRING?我是否應該更改LSA_OBJECT_ATTRIBUTES定義,以便字段爲IntPtr?我應該將它設爲空,並將null分配給該字段?

我對內存管理的經驗很少,所以我對任何可能導致內存泄漏的問題都非常謹慎。

+0

它可能不是最漂亮的溶劑,但是在你通過參數之前投射到一個物體上會發生什麼? – Jordy

+0

@Jordy(LSA_UNICODE_STRING)(object)IntPtr.Zero'編譯,但在運行時拋出'InvalidCastException'。就我所能說的,我在問題結尾處提出的兩種方法都有效,但我不知道我是否會遇到任何問題。 – Bob

+0

Pinvoke是一件棘手的事情......如果它像你期望的那樣工作,那麼你可能會算上自己的幸運。基本經驗與Pinvoke:如果它的工作,不要觸摸它。 – Jordy

回答

3

聲明LSA_UNICODE_STRINGclass而不是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; 
} 

您可以採用相同的策略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 
); 

注意,在pinvoke.net申報錯誤地使用上LsaOpenPolicySetLastError=true。這是錯誤的,因爲錯誤代碼返回到返回值中。我也將PreserveSig的設置刪除爲true,因爲這是默認設置。他們的LSA_OBJECT_ATTRIBUTES聲明也出現錯誤,因爲ObjectName參數的類型爲LSA_UNICODE_STRING,這是結構而不是指向它的指針。

我會建議你對待你發現的問題。網絡極端懷疑。該網站上的大部分聲明完全不正確。

你問使用可空類型的可能性。根據@ JaredPar的answer here,這不是一個選項。

+0

好吧,我重新回答了我的問題,以便與我想問的問題相匹配。對不起,第一次的誤會。 –

+0

我實際上有一個字段('LSA_UNICODE_STRING [] UserRights')在其他地方('LsaAddAccountRights'),它不適用於類(我猜我需要做一些編組)。聲明一個結構體和一個類(給這個類命名爲「PLSA ...」,無論如何都適合),這是有效的。謝謝!另外,感謝您挖掘可空類型的信息 - 我忘記了它們在內存中有不同的佈局。出於好奇,你認爲將ObjectName聲明爲IntPtr類型怎麼樣?這會破壞什麼? – Bob

+0

這也會很好。如果你真的想傳遞一個非空值,那麼你需要做更多的工作。你需要將struct編組爲指針,這涉及非託管內存的分配。多一點樣板。如果你總是傳遞'null',那麼'IntPtr'很好。 –

相關問題