Below is a code in C# where I am trying to add SSL binding of an existing certificate to "Default Website" in IIS Server. But I keep getting
System.Runtime.InteropServices.COMException (0x8000500C) in statement "website.Properties["SSLCertHash"].Add(x509.GetCertHash());".
Do you know the reason why?
string defaultWebsite = "Default Web Site";
foreach (DirectoryEntry website in sites)
{
if (website.Properties["ServerComment"] != null)
{
if (website.Properties["ServerComment"].Value != null)
{
SrmLogManager.logMessage(SrmLogMgrLevel.SRM_LOGMGR_LEVEL_INFO, funcName + "Website found" + website.Properties["ServerComment"].Value.ToString());
PropertyCollection pc = website.Properties;
IDictionaryEnumerator ide = pc.GetEnumerator();
ide.Reset();
while (ide.MoveNext())
{
PropertyValueCollection pvc = ide.Entry.Value as PropertyValueCollection;
// Dump out the website properties into the log, can be removed in future
SrmLogManager.logMessage(SrmLogMgrLevel.SRM_LOGMGR_LEVEL_INFO,"Name: "+ ide.Entry.Key.ToString());
SrmLogManager.logMessage(SrmLogMgrLevel.SRM_LOGMGR_LEVEL_INFO,"Value: " + pvc.Value);
}
// Add the Secure (https) binding to port 443 at hostname = localhost
website.Properties["SecureBindings"].Clear();
website.Properties["SecureBindings"].Add(":443:localhost");
// Bind the AppAssure certificate
website.Properties["SSLCertHash"].Clear();
website.Properties["SSLCertHash"].Add(x509.GetCertHash());
website.CommitChanges();
if (string.Compare(website.Properties["ServerComment"].Value.ToString(), defaultWebsite) == 0)
{
SrmLogManager.logMessage(SrmLogMgrLevel.SRM_LOGMGR_LEVEL_INFO, funcName + "Default Website is : " + website.Properties["ServerComment"].Value.ToString());
}
}
}
}
Here is the exception I am getting:
Exception occured while binding AA cert System.Runtime.InteropServices.COMException (0x8000500C): Exception from HRESULT: 0x8000500C at System.DirectoryServices.Interop.UnsafeNativeMethods.IAds.PutEx(Int32 lnControlCode, String bstrName, Object vProp) at System.DirectoryServices.PropertyValueCollection.OnInsertComplete(Int32 index, Object value) at System.Collections.CollectionBase.System.Collections.IList.Add(Object value) at System.DirectoryServices.PropertyValueCollection.Add(Object value) at AAA.Web.Controllers.Global.importAppAssureSoftwareCert() in c:\Users\Administrator\Documents\AppAssureAppliance2.0\SRMWebClient\AAA.Web\Controllers\Global.cs:line 80
Yep, this is a problem. You have to use the low level COM API, bypassing DirectoryEntry
entirely. This is how I did it:
private static void SetSslCertHash(string siteId, byte[] hash)
{
using (var adminBase = TemporaryComObject.Wrap(new MSAdminBase_W()))
using (var ptrHash = new AllocHGlobal(hash))
{
using (var siteKey = new AdminBaseKey(adminBase.Com, adminBase.Com.OpenKey(METADATA_MASTER_ROOT_HANDLE, "/LM/W3SVC/" + siteId, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE, 1000)))
{
var record = new METADATA_RECORD
{
dwMDIdentifier = SslCertHashCode,
dwMDAttributes = METADATA_INHERIT,
dwMDUserType = IIS_MD_UT_SERVER,
dwMDDataType = BINARY_METADATA,
pbMDData = ptrHash.Buffer,
dwMDDataLen = hash.Length
};
adminBase.Com.SetData(siteKey.Handle, string.Empty, ref record);
}
adminBase.Com.SaveData();
}
}
It is annoying that DirectoryEntry
API is broken for this particular property. Anyway, more help on the low level COM API is here - http://support.microsoft.com/kb/313624/en-US
Of course, you will need the .NET declaration of the MSAdminBase_W
COM class. At the time I wrote this code I could not find anything ready, so I just opened "c:\Program Files\Microsoft SDKs\Windows\v7.1\Include\Iadmw.h" and extracted all the pieces from there. Here it is, for you to copy and enjoy:
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace MSAdminBaseLib
{
[StructLayout(LayoutKind.Sequential)]
public struct _FILETIME
{
public uint dwLowDateTime;
public uint dwHighDateTime;
}
[ComImport, Guid("70B51430-B6CA-11D0-B9B9-00A0C922E750"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMSAdminBase_W
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void AddKey([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void DeleteKey([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void DeleteChildKeys([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void EnumKeys([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0, SizeConst = 0x100)] ushort[] szMDName, [In] int dwMDEnumObjectIndex);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void CopyKey([In] int hMDSourceHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDSourcePath, [In] int hMDDestHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDDestPath, [In] int bMDOverwriteFlag, [In] int bMDCopyFlag);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void RenameKey([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDNewName);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void SetData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] ref METADATA_RECORD pmdrMDData);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In, Out] ref METADATA_RECORD pmdrMDData, out int pdwMDRequiredDataLen);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void DeleteData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDIdentifier, [In] int dwMDDataType);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void EnumData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In, Out] ref METADATA_RECORD pmdrMDData, [In] int dwMDEnumDataIndex, out int pdwMDRequiredDataLen);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetAllData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDAttributes, [In] int dwMDUserType, [In] int dwMDDataType, out int pdwMDNumDataEntries, out int pdwMDDataSetNumber, [In] int dwMDBufferSize, out byte pbMDBuffer, out int pdwMDRequiredBufferSize);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void DeleteAllData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDUserType, [In] int dwMDDataType);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void CopyData([In] int hMDSourceHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDSourcePath, [In] int hMDDestHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDDestPath, [In] int dwMDAttributes, [In] int dwMDUserType, [In] int dwMDDataType, [In] int bMDCopyFlag);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetDataPaths([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDIdentifier, [In] int dwMDDataType, [In] int dwMDBufferSize, out ushort pszBuffer, out int pdwMDRequiredBufferSize);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
int OpenKey([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDAccessRequested, [In] int dwMDTimeOut);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void CloseKey([In] int hMDHandle);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void ChangePermissions([In] int hMDHandle, [In] int dwMDTimeOut, [In] int dwMDAccessRequested);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void SaveData();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetHandleInfo([In] int hMDHandle, out METADATA_HANDLE_INFO pmdhiInfo);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetSystemChangeNumber(out int pdwSystemChangeNumber);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetDataSetNumber([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, out int pdwMDDataSetNumber);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void SetLastChangeTime([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] ref _FILETIME pftMDLastChangeTime, [In] int bLocalTime);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetLastChangeTime([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, out _FILETIME pftMDLastChangeTime, [In] int bLocalTime);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), TypeLibFunc(TypeLibFuncFlags.FRestricted)]
void KeyExchangePhase1();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), TypeLibFunc(TypeLibFuncFlags.FRestricted)]
void KeyExchangePhase2();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void Backup([In, MarshalAs(UnmanagedType.LPWStr)] string pszMDBackupLocation, [In] int dwMDVersion, [In] int dwMDFlags);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void Restore([In, MarshalAs(UnmanagedType.LPWStr)] string pszMDBackupLocation, [In] int dwMDVersion, [In] int dwMDFlags);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void EnumBackups([In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0, SizeConst = 0x100)] ushort[] szMDBackupLocation, out int pdwMDVersion, out _FILETIME pftMDBackupTime, [In] int dwMDEnumIndex);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void DeleteBackup([In, MarshalAs(UnmanagedType.LPWStr)] string pszMDBackupLocation, [In] int dwMDVersion);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void UnmarshalInterface([MarshalAs(UnmanagedType.Interface)] out MSAdminBase_W piadmbwInterface);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), TypeLibFunc(TypeLibFuncFlags.FRestricted)]
void GetServerGuid();
}
[StructLayout(LayoutKind.Sequential)]
public struct METADATA_HANDLE_INFO
{
public int dwMDPermissions;
public int dwMDSystemChangeNumber;
}
[StructLayout(LayoutKind.Sequential)]
public struct METADATA_RECORD
{
public int dwMDIdentifier;
public int dwMDAttributes;
public int dwMDUserType;
public int dwMDDataType;
public int dwMDDataLen;
public IntPtr pbMDData;
public int dwMDDataTag;
}
[ComImport, Guid("70B51430-B6CA-11D0-B9B9-00A0C922E750"), CoClass(typeof(MSAdminBase_WClass))]
public interface MSAdminBase_W : IMSAdminBase_W
{
}
[ComImport, TypeLibType(TypeLibTypeFlags.FCanCreate), ClassInterface(ClassInterfaceType.None), Guid("A9E69610-B80D-11D0-B9B9-00A0C922E750")]
public class MSAdminBase_WClass : MSAdminBase_W
{
// Methods
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void AddKey([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void Backup([In, MarshalAs(UnmanagedType.LPWStr)] string pszMDBackupLocation, [In] int dwMDVersion, [In] int dwMDFlags);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void ChangePermissions([In] int hMDHandle, [In] int dwMDTimeOut, [In] int dwMDAccessRequested);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void CloseKey([In] int hMDHandle);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void CopyData([In] int hMDSourceHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDSourcePath, [In] int hMDDestHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDDestPath, [In] int dwMDAttributes, [In] int dwMDUserType, [In] int dwMDDataType, [In] int bMDCopyFlag);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void CopyKey([In] int hMDSourceHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDSourcePath, [In] int hMDDestHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDDestPath, [In] int bMDOverwriteFlag, [In] int bMDCopyFlag);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void DeleteAllData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDUserType, [In] int dwMDDataType);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void DeleteBackup([In, MarshalAs(UnmanagedType.LPWStr)] string pszMDBackupLocation, [In] int dwMDVersion);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void DeleteChildKeys([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void DeleteData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDIdentifier, [In] int dwMDDataType);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void DeleteKey([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void EnumBackups([In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0, SizeConst = 0x100)] ushort[] szMDBackupLocation, out int pdwMDVersion, out _FILETIME pftMDBackupTime, [In] int dwMDEnumIndex);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void EnumData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In, Out] ref METADATA_RECORD pmdrMDData, [In] int dwMDEnumDataIndex, out int pdwMDRequiredDataLen);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void EnumKeys([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0, SizeConst = 0x100)] ushort[] szMDName, [In] int dwMDEnumObjectIndex);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void GetAllData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDAttributes, [In] int dwMDUserType, [In] int dwMDDataType, out int pdwMDNumDataEntries, out int pdwMDDataSetNumber, [In] int dwMDBufferSize, out byte pbMDBuffer, out int pdwMDRequiredBufferSize);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void GetData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In, Out] ref METADATA_RECORD pmdrMDData, out int pdwMDRequiredDataLen);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void GetDataPaths([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDIdentifier, [In] int dwMDDataType, [In] int dwMDBufferSize, out ushort pszBuffer, out int pdwMDRequiredBufferSize);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void GetDataSetNumber([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, out int pdwMDDataSetNumber);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void GetHandleInfo([In] int hMDHandle, out METADATA_HANDLE_INFO pmdhiInfo);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void GetLastChangeTime([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, out _FILETIME pftMDLastChangeTime, [In] int bLocalTime);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), TypeLibFunc(TypeLibFuncFlags.FRestricted)]
public virtual extern void GetServerGuid();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void GetSystemChangeNumber(out int pdwSystemChangeNumber);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), TypeLibFunc(TypeLibFuncFlags.FRestricted)]
public virtual extern void KeyExchangePhase1();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), TypeLibFunc(TypeLibFuncFlags.FRestricted)]
public virtual extern void KeyExchangePhase2();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern int OpenKey([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDAccessRequested, [In] int dwMDTimeOut);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void RenameKey([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDNewName);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void Restore([In, MarshalAs(UnmanagedType.LPWStr)] string pszMDBackupLocation, [In] int dwMDVersion, [In] int dwMDFlags);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void SaveData();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void SetData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] ref METADATA_RECORD pmdrMDData);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void SetLastChangeTime([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] ref _FILETIME pftMDLastChangeTime, [In] int bLocalTime);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void UnmarshalInterface([MarshalAs(UnmanagedType.Interface)] out MSAdminBase_W piadmbwInterface);
}
}
Next, the easy part - auxiliary .NET types to implement a C# version of RAII:
TemporaryComObject:
public class TemporaryComObject
{
public static TemporaryComObject<T> Wrap<T>(T com) where T : class
{
return new TemporaryComObject<T>(com);
}
}
public class TemporaryComObject<T> : IDisposable where T : class
{
public TemporaryComObject(T com)
{
Com = com;
}
public T Com { get; private set; }
#region IDisposable Members
public void Dispose()
{
if (Com != null)
{
Marshal.FinalReleaseComObject(Com);
Com = null;
}
}
#endregion
}
AllocHGlobal:
public class AllocHGlobal : IDisposable
{
public readonly IntPtr Buffer;
public AllocHGlobal(int len)
{
Buffer = Marshal.AllocHGlobal(len);
}
public AllocHGlobal(byte[] data) :
this(data.Length)
{
Marshal.Copy(data, 0, Buffer, data.Length);
}
#region Implementation of IDisposable
public void Dispose()
{
Marshal.FreeHGlobal(Buffer);
}
#endregion
}
AdminBaseKey:
public class AdminBaseKey : IDisposable
{
private readonly IMSAdminBase_W m_adminBase;
public readonly int Handle;
public AdminBaseKey(IMSAdminBase_W adminBase, int handle)
{
m_adminBase = adminBase;
Handle = handle;
}
#region Implementation of IDisposable
public void Dispose()
{
m_adminBase.CloseKey(Handle);
}
#endregion
}
That's it. Works for me.
User contributions licensed under CC BY-SA 3.0