mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-13 17:23:02 -05:00
* Bump to SDK 7.0 and related updates * More net 7 updates * Install SDK 2.0 for ESRP * Fix typo * Address comment and update integration test script * Disable new warnings from SDK update
110 lines
4.1 KiB
C#
110 lines
4.1 KiB
C#
//
|
|
// 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<CREDENTIAL>(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;
|
|
}
|
|
}
|
|
}
|
|
}
|