// // Code originally from http://credentialmanagement.codeplex.com/, // Licensed under the Apache License 2.0 // using System; using System.Runtime.InteropServices; using System.Text; namespace Microsoft.SqlTools.Credentials.Win32 { internal class NativeMethods { [StructLayout(LayoutKind.Sequential)] internal struct CREDENTIAL { public int Flags; public int Type; [MarshalAs(UnmanagedType.LPWStr)] public string TargetName; [MarshalAs(UnmanagedType.LPWStr)] public string Comment; public long LastWritten; public int CredentialBlobSize; public IntPtr CredentialBlob; public int Persist; public int AttributeCount; public IntPtr Attributes; [MarshalAs(UnmanagedType.LPWStr)] public string TargetAlias; [MarshalAs(UnmanagedType.LPWStr)] public string UserName; } [DllImport("Advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)] internal static extern bool CredRead(string target, CredentialType type, int reservedFlag, out IntPtr CredentialPtr); [DllImport("Advapi32.dll", EntryPoint = "CredWriteW", CharSet = CharSet.Unicode, SetLastError = true)] internal static extern bool CredWrite([In] ref CREDENTIAL userCredential, [In] UInt32 flags); [DllImport("Advapi32.dll", EntryPoint = "CredFree", SetLastError = true)] internal static extern bool CredFree([In] IntPtr cred); [DllImport("advapi32.dll", EntryPoint = "CredDeleteW", CharSet = CharSet.Unicode)] internal static extern bool CredDelete(StringBuilder target, CredentialType type, int flags); [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] internal static extern bool CredEnumerateW(string filter, int flag, out uint count, out IntPtr pCredentials); [DllImport("ole32.dll")] internal static extern void CoTaskMemFree(IntPtr ptr); internal abstract class CriticalHandleZeroOrMinusOneIsInvalid : CriticalHandle { protected CriticalHandleZeroOrMinusOneIsInvalid() : base(IntPtr.Zero) { } public override bool IsInvalid { get { return handle == new IntPtr(0) || handle == new IntPtr(-1); } } } internal sealed class CriticalCredentialHandle : CriticalHandleZeroOrMinusOneIsInvalid { // Set the handle. internal CriticalCredentialHandle(IntPtr preexistingHandle) { SetHandle(preexistingHandle); } internal CREDENTIAL GetCredential() { if (!IsInvalid) { // Get the Credential from the mem location return (CREDENTIAL)Marshal.PtrToStructure(handle); } else { throw new InvalidOperationException(SR.CredentialsServiceInvalidCriticalHandle); } } // Perform any specific actions to release the handle in the ReleaseHandle method. // Often, you need to use Pinvoke to make a call into the Win32 API to release the // handle. In this case, however, we can use the Marshal class to release the unmanaged memory. protected override bool ReleaseHandle() { // If the handle was set, free it. Return success. if (!IsInvalid) { // NOTE: We should also ZERO out the memory allocated to the handle, before free'ing it // so there are no traces of the sensitive data left in memory. CredFree(handle); // Mark the handle as invalid for future users. SetHandleAsInvalid(); return true; } // Return false. return false; } } } }