Vanara/PInvoke/Security/AdvApi32/WinCred.cs

1917 lines
94 KiB
C#

using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Vanara.Extensions;
using Vanara.InteropServices;
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
namespace Vanara.PInvoke
{
public static partial class AdvApi32
{
/// <summary>Maximum number of attributes per credential</summary>
public const int CRED_MAX_ATTRIBUTES = 64;
/// <summary>Maximum length of the TargetName field for CRED_TYPE_DOMAIN_* (in characters). Largest one is DfsRoot\DfsShare</summary>
public const int CRED_MAX_DOMAIN_TARGET_NAME_LENGTH = (256 + 1 + 80);
/// <summary>Maximum length of the TargetName field for CRED_TYPE_GENERIC (in characters)</summary>
public const int CRED_MAX_GENERIC_TARGET_NAME_LENGTH = 32767;
/// <summary>Maximum length of the various credential string fields (in characters)</summary>
public const int CRED_MAX_STRING_LENGTH = 256;
/// <summary>Maximum length of a target attribute</summary>
public const int CRED_MAX_TARGETNAME_ATTRIBUTE_LENGTH = (256);
/// <summary>Maximum length of a target namespace</summary>
public const int CRED_MAX_TARGETNAME_NAMESPACE_LENGTH = (256);
/// <summary>Maximum length of the UserName field. The worst case is User@DnsDomain</summary>
public const int CRED_MAX_USERNAME_LENGTH = (256 + 1 + 256);
/// <summary>Maximum size of the Credential Attribute Value field (in bytes)</summary>
public const int CRED_MAX_VALUE_SIZE = (256);
/// <summary>Flags used by CredEnumerate.</summary>
[PInvokeData("wincred.h", MSDNShortId = "ef0b7620-7b00-45f1-af16-141d2e940783")]
public enum CRED_ENUM
{
/// <summary>No flags.</summary>
NONE = 0,
/// <summary>
/// This function enumerates all of the credentials in the user's credential set. The target name of each credential is returned
/// in the "namespace:attribute=target" format. If this flag is set and the Filter parameter is not NULL, the function fails and
/// returns ERROR_INVALID_FLAGS.
/// <para>Windows Server 2003 and Windows XP: This flag is not supported.</para>
/// </summary>
CRED_ENUMERATE_ALL_CREDENTIALS = 0x1,
}
/// <summary>A bit member that identifies characteristics of the credential.</summary>
[PInvokeData("wincred.h")]
[Flags]
public enum CRED_FLAGS
{
/// <summary/>
CRED_FLAGS_PASSWORD_FOR_CERT = 0x1,
/// <summary>
/// Bit set if the credential does not persist the CredentialBlob and the credential has not been written during this logon
/// session. This bit is ignored on input and is set automatically when queried.
/// <para>
/// If Type is CRED_TYPE_DOMAIN_CERTIFICATE, the CredentialBlob is not persisted across logon sessions because the PIN of a
/// certificate is very sensitive information. Indeed, when the credential is written to credential manager, the PIN is passed to
/// the CSP associated with the certificate. The CSP will enforce a PIN retention policy appropriate to the certificate.
/// </para>
/// <para>
/// If Type is CRED_TYPE_DOMAIN_PASSWORD or CRED_TYPE_DOMAIN_CERTIFICATE, an authentication package always fails an
/// authentication attempt when using credentials marked as CRED_FLAGS_PROMPT_NOW. The application (typically through the key
/// ring UI) prompts the user for the password. The application saves the credential and retries the authentication. Because the
/// credential has been recently written, the authentication package now gets a credential that is not marked as CRED_FLAGS_PROMPT_NOW.
/// </para>
/// </summary>
CRED_FLAGS_PROMPT_NOW = 0x2,
/// <summary>
/// Bit is set if this credential has a TargetName member set to the same value as the UserName member. Such a credential is one
/// designed to store the CredentialBlob for a specific user. For more information, see the CredMarshalCredential function.
/// <para>This bit can only be specified if Type is CRED_TYPE_DOMAIN_PASSWORD or CRED_TYPE_DOMAIN_CERTIFICATE.</para>
/// </summary>
CRED_FLAGS_USERNAME_TARGET = 0x4,
/// <summary/>
CRED_FLAGS_OWF_CRED_BLOB = 0x0008,
/// <summary/>
CRED_FLAGS_REQUIRE_CONFIRMATION = 0x0010,
/// <summary/>
CRED_FLAGS_WILDCARD_MATCH = 0x0020,
/// <summary/>
CRED_FLAGS_VSM_PROTECTED = 0x0040,
/// <summary/>
CRED_FLAGS_NGC_CERT = 0x0080,
/// <summary/>
CRED_FLAGS_VALID_FLAGS = 0xF0FF,
/// <summary/>
CRED_FLAGS_VALID_INPUT_FLAGS = 0xF09F,
}
/// <summary>
/// <para>
/// The <c>CRED_MARSHAL_TYPE</c> enumeration specifies the types of credential to be marshaled by CredMarshalCredential or
/// unmarshaled by CredUnmarshalCredential.
/// </para>
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/ne-wincred-_cred_marshal_type typedef enum _CRED_MARSHAL_TYPE {
// CertCredential , UsernameTargetCredential , BinaryBlobCredential , UsernameForPackedCredentials , BinaryBlobForSystem }
// CRED_MARSHAL_TYPE, *PCRED_MARSHAL_TYPE;
[PInvokeData("wincred.h", MSDNShortId = "612fdd6f-2b4c-4f41-a00b-250f90eb85d3")]
public enum CRED_MARSHAL_TYPE
{
/// <summary>Specifies that the credential is a certificate reference described by a CERT_CREDENTIAL_INFO structure.</summary>
[CorrespondingType(typeof(CERT_CREDENTIAL_INFO))]
CertCredential = 1,
/// <summary>
/// Specifies that the credential is a reference to a CRED_FLAGS_USERNAME_TARGET credential described by a
/// USERNAME_TARGET_CREDENTIAL_INFO structure.
/// </summary>
[CorrespondingType(typeof(USERNAME_TARGET_CREDENTIAL_INFO))]
UsernameTargetCredential,
/// <summary>Undocumented.</summary>
[CorrespondingType(typeof(BINARY_BLOB_CREDENTIAL_INFO))]
BinaryBlobCredential,
}
/// <summary>Specifies the maximum persistence supported by the corresponding credential type.</summary>
[PInvokeData("wincred.h", MSDNShortId = "70f8d5e0-235b-4330-8add-566b41c91c17")]
public enum CRED_PERSIST
{
/// <summary>
/// No credential can be stored. This value will be returned if the credential type is not supported or has been disabled by policy.
/// </summary>
CRED_PERSIST_NONE = 0,
/// <summary>
/// The credential persists for the life of the logon session. It will not be visible to other logon sessions of this same user.
/// It will not exist after this user logs off and back on.
/// </summary>
CRED_PERSIST_SESSION = 1,
/// <summary>
/// The credential persists for all subsequent logon sessions on this same computer. It is visible to other logon sessions of
/// this same user on this same computer and not visible to logon sessions for this user on other computers.
/// <para>
/// Windows Vista Home Basic, Windows Vista Home Premium, Windows Vista Starter and Windows XP Home Edition: This value is not supported.
/// </para>
/// </summary>
CRED_PERSIST_LOCAL_MACHINE = 2,
/// <summary>
/// The credential persists for all subsequent logon sessions on this same computer. It is visible to other logon sessions of
/// this same user on this same computer and to logon sessions for this user on other computers.
/// <para>
/// This option can be implemented as locally persisted credential if the administrator or user configures the user account to
/// not have roam-able state. For instance, if the user has no roaming profile, the credential will only persist locally.
/// </para>
/// <para>
/// Windows Vista Home Basic, Windows Vista Home Premium, Windows Vista Starter and Windows XP Home Edition: This value is not supported.
/// </para>
/// </summary>
CRED_PERSIST_ENTERPRISE = 3,
}
/// <summary>
/// <para>
/// The <c>CRED_PROTECTION_TYPE</c> enumeration specifies the security context in which credentials are encrypted when using the
/// CredProtect function.
/// </para>
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/ne-wincred-_cred_protection_type typedef enum _CRED_PROTECTION_TYPE {
// CredUnprotected , CredUserProtection , CredTrustedProtection , CredForSystemProtection } CRED_PROTECTION_TYPE, *PCRED_PROTECTION_TYPE;
[PInvokeData("wincred.h", MSDNShortId = "6d8d8ad6-1b44-4482-a9a2-9c50d522b8d9")]
public enum CRED_PROTECTION_TYPE
{
/// <summary>The credentials are not encrypted.</summary>
CredUnprotected,
/// <summary>
/// The credentials are encrypted and can be decrypted only in the security context in which they were encrypted or in the
/// security context of a trusted component.
/// </summary>
CredUserProtection,
/// <summary>The credentials are encrypted and can only be decrypted by a trusted component.</summary>
CredTrustedProtection,
/// <summary/>
CredForSystemProtection,
}
/// <summary>Type of credential used by CREDENTIAL structure.</summary>
[PInvokeData("wincred.h")]
public enum CRED_TYPE
{
/// <summary>
/// The credential is a generic credential. The credential will not be used by any particular authentication package. The
/// credential will be stored securely but has no other significant characteristics.
/// </summary>
CRED_TYPE_GENERIC = 1,
/// <summary>
/// The credential is a password credential and is specific to Microsoft's authentication packages. The NTLM, Kerberos, and
/// Negotiate authentication packages will automatically use this credential when connecting to the named target.
/// </summary>
CRED_TYPE_DOMAIN_PASSWORD = 2,
/// <summary>
/// The credential is a certificate credential and is specific to Microsoft's authentication packages. The Kerberos, Negotiate,
/// and Schannel authentication packages automatically use this credential when connecting to the named target.
/// </summary>
CRED_TYPE_DOMAIN_CERTIFICATE = 3,
/// <summary>
/// This value is no longer supported.
/// <para>
/// <c>Windows Server 2003 and Windows XP:</c> The credential is a password credential and is specific to authentication packages
/// from Microsoft. The Passport authentication package will automatically use this credential when connecting to the named target.
/// </para>
/// <para>
/// Additional values will be defined in the future. Applications should be written to allow for credential types they do not understand.
/// </para>
/// </summary>
CRED_TYPE_DOMAIN_VISIBLE_PASSWORD = 4,
/// <summary>
/// The credential is a certificate credential that is a generic authentication package.
/// <para><c>Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP:</c> This value is not supported.</para>
/// </summary>
CRED_TYPE_GENERIC_CERTIFICATE = 5,
/// <summary>
/// The credential is supported by extended Negotiate packages.
/// <para><c>Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP:</c> This value is not supported.</para>
/// </summary>
CRED_TYPE_DOMAIN_EXTENDED = 6,
/// <summary>
/// The maximum number of supported credential types. <note type="note">Windows Server 2008, Windows Vista, Windows Server 2003
/// and Windows XP: This value is not supported.</note>
/// </summary>
CRED_TYPE_MAXIMUM = 7,
/// <summary>
/// The extended maximum number of supported credential types that now allow new applications to run on older operating systems.
/// <note type="note">Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This value is not supported.</note>
/// </summary>
CRED_TYPE_MAXIMUM_EX = CRED_TYPE_MAXIMUM + 1000,
}
/// <summary>Flags for CredWrite.</summary>
[PInvokeData("wincred.h", MSDNShortId = "9a590347-d610-4916-bf63-60fbec173ac2")]
public enum CRED_WRITE
{
/// <summary>
/// The credential BLOB from an existing credential is preserved with the same credential name and credential type. The
/// CredentialBlobSize of the passed in Credential structure must be zero.
/// </summary>
CRED_PRESERVE_CREDENTIAL_BLOB = 0x01,
}
/// <summary>
/// <para>
/// The <c>CredDelete</c> function deletes a credential from the user's credential set. The credential set used is the one associated
/// with the logon session of the current token. The token must not have the user's SID disabled.
/// </para>
/// </summary>
/// <param name="TargetName">
/// <para>Pointer to a null-terminated string that contains the name of the credential to delete.</para>
/// </param>
/// <param name="Type">
/// <para>
/// Type of the credential to delete. Must be one of the CRED_TYPE_* defined types. For a list of the defined types, see the
/// <c>Type</c> member of the CREDENTIAL structure.
/// </para>
/// <para>
/// If the value of this parameter is <c>CRED_TYPE_DOMAIN_EXTENDED</c>, this function can delete a credential that specifies a user
/// name when there are multiple credentials for the same target. The value of the TargetName parameter must specify the user name as
/// Target <c>|</c> UserName.
/// </para>
/// </param>
/// <param name="Flags">
/// <para>Reserved and must be zero.</para>
/// </param>
/// <returns>
/// <para>
/// The function returns <c>TRUE</c> on success and <c>FALSE</c> on failure. The GetLastError function can be called to get a more
/// specific status code. The following status codes can be returned:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>ERROR_NOT_FOUND</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_LOGON_SESSION</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// </item>
/// </list>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-creddeletea BOOL CredDeleteA( LPCSTR TargetName, DWORD
// Type, DWORD Flags );
[DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("wincred.h", MSDNShortId = "154af9c8-18fd-412d-899d-7c6d2138380d")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredDelete(string TargetName, CRED_TYPE Type, uint Flags = 0);
/// <summary>
/// <para>
/// The <c>CredEnumerate</c> function enumerates the credentials from the user's credential set. The credential set used is the one
/// associated with the logon session of the current token. The token must not have the user's SID disabled.
/// </para>
/// </summary>
/// <param name="Filter">
/// <para>
/// Pointer to a <c>null</c>-terminated string that contains the filter for the returned credentials. Only credentials with a
/// TargetName matching the filter will be returned. The filter specifies a name prefix followed by an asterisk. For instance, the
/// filter "FRED*" will return all credentials with a TargetName beginning with the string "FRED".
/// </para>
/// <para>If <c>NULL</c> is specified, all credentials will be returned.</para>
/// </param>
/// <param name="Flags">
/// <para>The value of this parameter can be zero or more of the following values combined with a bitwise- <c>OR</c> operation.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>CRED_ENUMERATE_ALL_CREDENTIALS 0x1</term>
/// <term>
/// This function enumerates all of the credentials in the user's credential set. The target name of each credential is returned in
/// the "namespace:attribute=target" format. If this flag is set and the Filter parameter is not NULL, the function fails and returns
/// ERROR_INVALID_FLAGS. Windows Server 2003 and Windows XP: This flag is not supported.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="Count">
/// <para>Count of the credentials returned in the Credentials array.</para>
/// </param>
/// <param name="Credential">
/// <para>
/// Pointer to an array of pointers to credentials. The returned credential is a single allocated block. Any pointers contained
/// within the buffer are pointers to locations within this single allocated block. The single returned buffer must be freed by
/// calling CredFree.
/// </para>
/// </param>
/// <returns>
/// <para>
/// The function returns <c>TRUE</c> on success and <c>FALSE</c> on failure. The GetLastError function can be called to get a more
/// specific status code. The following status codes can be returned.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_NOT_FOUND 1168 (0x490)</term>
/// <term>No credential exists matching the specified Filter.</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_LOGON_SESSION 1312 (0x520)</term>
/// <term>
/// The logon session does not exist or there is no credential set associated with this logon session. Network logon sessions do not
/// have an associated credential set.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_FLAGS 1004 (0x3EC)</term>
/// <term>
/// A flag that is not valid was specified for the Flags parameter, or CRED_ENUMERATE_ALL_CREDENTIALS is specified for the Flags
/// parameter and the Filter parameter is not NULL.
/// </term>
/// </item>
/// </list>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credenumeratea BOOL CredEnumerateA( LPCSTR Filter, DWORD
// Flags, DWORD *Count, PCREDENTIALA **Credential );
[DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("wincred.h", MSDNShortId = "ef0b7620-7b00-45f1-af16-141d2e940783")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredEnumerate(string Filter, CRED_ENUM Flags, out uint Count, out SafeCredMemoryHandle Credential);
/// <summary>
/// The <c>CredEnumerate</c> function enumerates the credentials from the user's credential set. The credential set used is the one
/// associated with the logon session of the current token. The token must not have the user's SID disabled.
/// </summary>
/// <param name="filter">
/// <para>
/// A string that contains the filter for the returned credentials. Only credentials with a TargetName matching the filter will be
/// returned. The filter specifies a name prefix followed by an asterisk. For instance, the filter "FRED*" will return all
/// credentials with a TargetName beginning with the string "FRED".
/// </para>
/// <para>
/// If this value is <see langword="null"/>, this function enumerates all of the credentials in the user's credential set. The target
/// name of each credential is returned in the "namespace:attribute=target" format.
/// </para>
/// </param>
/// <returns>An array of credentials.</returns>
public static CREDENTIAL_MGD[] CredEnumerate(string filter = null)
{
if (!CredEnumerate(filter, filter is null ? CRED_ENUM.CRED_ENUMERATE_ALL_CREDENTIALS : CRED_ENUM.NONE, out var cnt, out var creds))
Win32Error.ThrowLastError();
using (creds)
return creds.GetCredArray((int)cnt);
}
/// <summary>
/// <para>
/// The <c>CredFindBestCredential</c> function searches the Credentials Management (CredMan) database for the set of generic
/// credentials that are associated with the current logon session and that best match the specified target resource.
/// </para>
/// </summary>
/// <param name="TargetName">
/// <para>A pointer to a null-terminated string that contains the name of the target resource for which to find credentials.</para>
/// </param>
/// <param name="Type">
/// <para>The type of credentials to search for. Currently, this function supports only <c>CRED_TYPE_GENERIC</c>.</para>
/// </param>
/// <param name="Flags">
/// <para>Reserved.</para>
/// </param>
/// <param name="Credential">
/// <para>The address of a pointer to a CREDENTIAL structure that specifies the set of credentials this function finds.</para>
/// <para>When you have finished using this structure, free it by calling the CredFree function.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>TRUE</c>.</para>
/// <para>If the function fails, it returns <c>FALSE</c>. To get extended error information, call GetLastError.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credfindbestcredentiala BOOL CredFindBestCredentialA(
// LPCSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALA *Credential );
[DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("wincred.h", MSDNShortId = "b39e3167-dd63-4b81-b850-f3117be348a5")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredFindBestCredential(string TargetName, CRED_TYPE Type, [Optional] uint Flags, out SafeCredMemoryHandle Credential);
/// <summary>
/// The <c>CredFindBestCredential</c> function searches the Credentials Management (CredMan) database for the set of generic
/// credentials that are associated with the current logon session and that best match the specified target resource.
/// </summary>
/// <param name="TargetName">
/// A pointer to a null-terminated string that contains the name of the target resource for which to find credentials.
/// </param>
/// <param name="Type">The type of credentials to search for. Currently, this function supports only <c>CRED_TYPE_GENERIC</c>.</param>
/// <param name="Credential">On success, gets a CREDENTIAL_MGD structure that specifies the set of credentials this function finds.</param>
/// <returns>
/// <para>If the function succeeds, it returns <c>TRUE</c>.</para>
/// <para>If the function fails, it returns <c>FALSE</c>. To get extended error information, call GetLastError.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credfindbestcredentiala BOOL CredFindBestCredentialA(
// LPCSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALA *Credential );
[PInvokeData("wincred.h", MSDNShortId = "b39e3167-dd63-4b81-b850-f3117be348a5")]
public static bool CredFindBestCredential(string TargetName, CRED_TYPE Type, out CREDENTIAL_MGD Credential)
{
var b = CredFindBestCredential(TargetName, Type, 0, out var cred);
using (cred)
Credential = b ? cred : default;
return b;
}
/// <summary>
/// <para>The <c>CredFree</c> function frees a buffer returned by any of the credentials management functions.</para>
/// </summary>
/// <param name="Buffer">
/// <para>Pointer to the buffer to be freed.</para>
/// </param>
/// <returns>
/// <para>This function does not return a value.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credfree void CredFree( PVOID Buffer );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("wincred.h", MSDNShortId = "bc33ab1b-dd3f-4e1b-96d2-e32ceff89ada")]
public static extern void CredFree(IntPtr Buffer);
/// <summary>
/// <para>
/// The <c>CredGetSessionTypes</c> function returns the maximum persistence supported by the current logon session. A separate
/// maximum persistence is returned for each credential type.
/// </para>
/// </summary>
/// <param name="MaximumPersistCount">
/// <para>
/// Number of elements in the MaximumPersist array. Use CRED_TYPE_MAXIMUM to return all of the currently defined credential types.
/// </para>
/// </param>
/// <param name="MaximumPersist">
/// <para>
/// Pointer to an array to return the persistence values in. The passed in array should be MaximumPersistCount elements long. On
/// return, each element specifies the maximum persistence supported by the corresponding credential type.
/// </para>
/// <para>The caller should use one of the following defines to index into the array:</para>
/// <list type="bullet">
/// <item>
/// <term>CRED_TYPE_GENERIC</term>
/// </item>
/// <item>
/// <term>CRED_TYPE_DOMAIN_PASSWORD</term>
/// </item>
/// <item>
/// <term>CRED_TYPE_DOMAIN_CERTIFICATE</term>
/// </item>
/// </list>
/// <para>That is,</para>
/// <para>MaximumPersist</para>
/// <para>[CRED_TYPE_GENERIC] specifies the maximum persistence supported for generic credentials.</para>
/// <para>The following values can be returned in each element of the array.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>CRED_PERSIST_NONE</term>
/// <term>
/// No credential can be stored. This value will be returned if the credential type is not supported or has been disabled by policy.
/// </term>
/// </item>
/// <item>
/// <term>CRED_PERSIST_SESSION</term>
/// <term>Only a session-specific credential can be stored.</term>
/// </item>
/// <item>
/// <term>CRED_PERSIST_LOCAL_MACHINE</term>
/// <term>
/// Session-specific and computer-specific credentials can be stored. Windows XP: This credential cannot be stored for sessions in
/// which the profile is not loaded.
/// </term>
/// </item>
/// <item>
/// <term>CRED_PERSIST_ENTERPRISE</term>
/// <term>Any credential can be stored. Windows XP: This credential cannot be stored for sessions in which the profile is not loaded.</term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <para>
/// This function returns <c>TRUE</c> on success and <c>FALSE</c> on failure. The GetLastError function can be called to get a more
/// specific status code. The following status code can be returned:
/// </para>
/// <para>ERROR_NO_SUCH_LOGON_SESSION</para>
/// <para>
/// The logon session does not exist or there is no credential set associated with this logon session. Network logon sessions do not
/// have an associated credential set.
/// </para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credgetsessiontypes BOOL CredGetSessionTypes( DWORD
// MaximumPersistCount, LPDWORD MaximumPersist );
[DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("wincred.h", MSDNShortId = "70f8d5e0-235b-4330-8add-566b41c91c17")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredGetSessionTypes(uint MaximumPersistCount, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] CRED_PERSIST[] MaximumPersist);
/// <summary>
/// <para>
/// The <c>CredGetTargetInfo</c> function retrieves all known target name information for the named target computer. This executed
/// locally and does not need any particular privilege. The information returned is expected to be passed to the
/// CredReadDomainCredentials and CredWriteDomainCredentials functions. The information should not be used for any other purpose.
/// </para>
/// <para>
/// Authentication packages compute TargetInfo when attempting to authenticate to a TargetName. The authentication packages cache
/// this target information to make it available to <c>CredGetTargetInfo</c>. Therefore, the target information will only be
/// available from a recent attempt to authenticate a TargetName.
/// </para>
/// <para>
/// Authentication packages not in the LSA process can cache a TargetInfo for later retrieval by <c>CredGetTargetInfo</c> by calling
/// CredReadDomainCredentials with the CRED_CACHE_TARGET_INFORMATION flag.
/// </para>
/// </summary>
/// <param name="TargetName">
/// <para>Pointer to a null-terminated string that contains the name of the target computer for which information is to be retrieved.</para>
/// </param>
/// <param name="Flags">
/// <para>Flags controlling the operation of the function. The following flag can be used:</para>
/// <para>CRED_ALLOW_NAME_RESOLUTION</para>
/// <para>
/// If no target information can be found for TargetName name resolution is done on TargetName to convert it to other forms. If
/// target information exists for any of those other forms, it is returned. Currently only DNS name resolution is done.
/// </para>
/// <para>
/// This is useful if the application does not call an authentication package directly. The application can pass the TargetName to
/// another layer of software to authenticate to the server, and that layer of software might resolve the name and pass the resolved
/// name to the authentication package. As such, there will be no target information for the original TargetName.
/// </para>
/// </param>
/// <param name="TargetInfo">
/// <para>
/// Pointer to a single allocated block buffer to contain the target information. At least one of the returned members of TargetInfo
/// will be non-NULL. Any pointers contained within the buffer are pointers to locations within this single allocated block. The
/// single returned buffer must be freed by calling CredFree.
/// </para>
/// </param>
/// <returns>
/// <para>
/// The function returns <c>TRUE</c> on success and <c>FALSE</c> on failure. The GetLastError function can be called to get a more
/// specific status code. The following status code can be returned:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>ERROR_NOT_FOUND</term>
/// </item>
/// </list>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credgettargetinfoa BOOL CredGetTargetInfoA( LPCSTR
// TargetName, DWORD Flags, PCREDENTIAL_TARGET_INFORMATIONA *TargetInfo );
[DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("wincred.h", MSDNShortId = "14dca0af-72d7-4ca8-84bb-c7040c5b5fb9")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredGetTargetInfo(string TargetName, uint Flags, out SafeCredMemoryHandle TargetInfo);
/// <summary>
/// <para>
/// The <c>CredIsMarshaledCredential</c> function determines whether a specified user name string is a marshaled credential
/// previously marshaled by CredMarshalCredential.
/// </para>
/// </summary>
/// <param name="MarshaledCredential">
/// <para>Pointer to a null-terminated string that contains the marshaled credential.</para>
/// </param>
/// <returns>
/// <para>This function returns <c>TRUE</c> if MarshaledCredential is a marshaled credential and <c>FALSE</c> if it is not.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credismarshaledcredentiala BOOL
// CredIsMarshaledCredentialA( LPCSTR MarshaledCredential );
[DllImport(Lib.AdvApi32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("wincred.h", MSDNShortId = "fc902c0c-41e0-4178-8ca0-227a1d218388")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredIsMarshaledCredential(string MarshaledCredential);
/// <summary>
/// <para>
/// The <c>CredIsProtected</c> function specifies whether the specified credentials are encrypted by a previous call to the
/// CredProtect function.
/// </para>
/// </summary>
/// <param name="pszProtectedCredentials">
/// <para>A pointer to a null-terminated string that specifies the credentials to test.</para>
/// </param>
/// <param name="pProtectionType">
/// <para>
/// A pointer to a value from the CRED_PROTECTION_TYPE enumeration that specifies whether the credentials specified in the
/// pszProtectedCredentials parameter are protected.
/// </para>
/// </param>
/// <returns>
/// <para><c>TRUE</c> if the function succeeds; otherwise, <c>FALSE</c>.</para>
/// <para>For extended error information, call the GetLastError function.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credisprotecteda BOOL CredIsProtectedA( LPSTR
// pszProtectedCredentials, CRED_PROTECTION_TYPE *pProtectionType );
[DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("wincred.h", MSDNShortId = "3c38ecf5-1288-4a50-ad17-595e9ff4aaca")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredIsProtected(string pszProtectedCredentials, out CRED_PROTECTION_TYPE pProtectionType);
/// <summary>
/// <para>
/// The <c>CredMarshalCredential</c> function transforms a credential into a text string. Historically, many functions, such as
/// NetUseAdd, take a domain name, user name, and password as credentials. These functions do not accept certificates as credentials.
/// The <c>CredMarshalCredential</c> function converts such credentials into a form that can be passed into these APIs.
/// </para>
/// <para>
/// The marshaled credential should be passed as the user name string to any API that is currently passed credentials. The domain
/// name, if applicable, passed to that API should be passed as <c>NULL</c> or empty. For certificate credentials, the PIN of the
/// certificate should be passed to that API as the password.
/// </para>
/// <para>
/// The caller should not modify or print marshaled credentials. The returned value can be freely converted between the Unicode,
/// ANSI, and OEM characters sets. The string is case sensitive.
/// </para>
/// </summary>
/// <param name="CredType">
/// <para>Type of the credential to marshal.</para>
/// </param>
/// <param name="Credential">
/// <para>Credential to marshal.</para>
/// <para>This is one of the CRED_MARSHAL_TYPE values.</para>
/// <para>If CredType is CertCredential, Credential points to a CERT_CREDENTIAL_INFO structure.</para>
/// <para>If CredType is UsernameTargetCredential, Credential points to a USERNAME_TARGET_CREDENTIAL_INFO structure.</para>
/// </param>
/// <param name="MarshaledCredential">
/// <para>
/// Pointer to a <c>null</c>-terminated string that contains the marshaled credential. The caller should free the returned buffer
/// using CredFree.
/// </para>
/// </param>
/// <returns>
/// <para>
/// This function returns <c>TRUE</c> on success and <c>FALSE</c> on failure. The GetLastError function can be called to get a more
/// specific status code. The following status code can be returned:
/// </para>
/// <para>ERROR_INVALID_PARAMETER</para>
/// <para>CredType is not valid.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credmarshalcredentiala BOOL CredMarshalCredentialA(
// CRED_MARSHAL_TYPE CredType, PVOID Credential, LPSTR *MarshaledCredential );
[DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("wincred.h", MSDNShortId = "20a1d54b-04a7-4b0a-88e4-1970d1f71502")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredMarshalCredential(CRED_MARSHAL_TYPE CredType, IntPtr Credential, out SafeCredMemoryHandle MarshaledCredential);
/// <summary>
/// <para>
/// The <c>CredMarshalCredential</c> function transforms a credential into a text string. Historically, many functions, such as
/// NetUseAdd, take a domain name, user name, and password as credentials. These functions do not accept certificates as credentials.
/// The <c>CredMarshalCredential</c> function converts such credentials into a form that can be passed into these APIs.
/// </para>
/// <para>
/// The marshaled credential should be passed as the user name string to any API that is currently passed credentials. The domain
/// name, if applicable, passed to that API should be passed as <c>NULL</c> or empty. For certificate credentials, the PIN of the
/// certificate should be passed to that API as the password.
/// </para>
/// <para>
/// The caller should not modify or print marshaled credentials. The returned value can be freely converted between the Unicode,
/// ANSI, and OEM characters sets. The string is case sensitive.
/// </para>
/// </summary>
/// <param name="CredType">
/// <para>Type of the credential to marshal.</para>
/// </param>
/// <param name="Credential">
/// <para>Credential to marshal.</para>
/// <para>This is one of the CRED_MARSHAL_TYPE values.</para>
/// <para>If CredType is CertCredential, Credential points to a CERT_CREDENTIAL_INFO structure.</para>
/// <para>If CredType is UsernameTargetCredential, Credential points to a USERNAME_TARGET_CREDENTIAL_INFO structure.</para>
/// </param>
/// <param name="MarshaledCredential">
/// <para>
/// Pointer to a <c>null</c>-terminated string that contains the marshaled credential. The caller should free the returned buffer
/// using CredFree.
/// </para>
/// </param>
/// <returns>
/// <para>
/// This function returns <c>TRUE</c> on success and <c>FALSE</c> on failure. The GetLastError function can be called to get a more
/// specific status code. The following status code can be returned:
/// </para>
/// <para>ERROR_INVALID_PARAMETER</para>
/// <para>CredType is not valid.</para>
/// </returns>
[PInvokeData("wincred.h", MSDNShortId = "20a1d54b-04a7-4b0a-88e4-1970d1f71502")]
public static bool CredMarshalCredential<T>(T Credential, out string MarshaledCredential, CRED_MARSHAL_TYPE CredType = 0) where T : struct
{
if (CredType == 0 ? !CorrespondingTypeAttribute.CanGet<T, CRED_MARSHAL_TYPE>(out CredType) : !CorrespondingTypeAttribute.CanGet(CredType, typeof(T)))
throw new InvalidCastException();
using (var mem = SafeHGlobalHandle.CreateFromStructure(Credential))
{
var b = CredMarshalCredential(CredType, mem, out var cred);
MarshaledCredential = b ? cred : null;
return b;
}
}
/// <summary>
/// <para>
/// The <c>CredProtect</c> function encrypts the specified credentials so that only the current security context can decrypt them.
/// </para>
/// </summary>
/// <param name="fAsSelf">
/// <para>
/// Set to <c>TRUE</c> to specify that the credentials are encrypted in the security context of the current process. Set to
/// <c>FALSE</c> to specify that credentials are encrypted in the security context of the calling thread security context.
/// </para>
/// </param>
/// <param name="pszCredentials">
/// <para>
/// A pointer to a string that specifies the credentials to encrypt. The function encrypts the number of characters provided in the
/// cchCredentials parameter.
/// </para>
/// </param>
/// <param name="cchCredentials">
/// <para>The size, in characters, of the pszCredentials buffer.</para>
/// </param>
/// <param name="pszProtectedCredentials">
/// <para>A pointer to a string that, on output, receives the encrypted credentials.</para>
/// </param>
/// <param name="pcchMaxChars">
/// <para>
/// The size, in characters of the pszProtectedCredentials buffer. On output, if the pszProtectedCredentials is not of sufficient
/// size to receive the encrypted credentials, this parameter specifies the required size, in characters, of the
/// pszProtectedCredentials buffer.
/// </para>
/// </param>
/// <param name="ProtectionType">
/// <para>A pointer to a CRED_PROTECTION_TYPE enumeration type that, on output, specifies the type of protection provided.</para>
/// </param>
/// <returns>
/// <para><c>TRUE</c> if the function succeeds; otherwise, <c>FALSE</c>.</para>
/// <para>For extended error information, call the GetLastError function.</para>
/// </returns>
/// <remarks>
/// <para>
/// Note that the output of the <c>CredProtect</c> function is not integrity protected, so if the output is modified, the
/// CredUnprotect function is not updated and may produce incorrect results.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credprotecta BOOL CredProtectA( BOOL fAsSelf, LPSTR
// pszCredentials, DWORD cchCredentials, LPSTR pszProtectedCredentials, DWORD *pcchMaxChars, CRED_PROTECTION_TYPE *ProtectionType );
[DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("wincred.h", MSDNShortId = "1e299dfb-2ffe-463c-9e2c-b7774a2216e3")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredProtect([MarshalAs(UnmanagedType.Bool)] bool fAsSelf, string pszCredentials, uint cchCredentials, StringBuilder pszProtectedCredentials, ref uint pcchMaxChars, out CRED_PROTECTION_TYPE ProtectionType);
/// <summary>
/// <para>
/// The <c>CredRead</c> function reads a credential from the user's credential set. The credential set used is the one associated
/// with the logon session of the current token. The token must not have the user's SID disabled.
/// </para>
/// </summary>
/// <param name="TargetName">
/// <para>Pointer to a null-terminated string that contains the name of the credential to read.</para>
/// </param>
/// <param name="Type">
/// <para>Type of the credential to read. Type must be one of the CRED_TYPE_* defined types.</para>
/// </param>
/// <param name="Flags">
/// <para>Currently reserved and must be zero.</para>
/// </param>
/// <param name="Credential">
/// <para>
/// Pointer to a single allocated block buffer to return the credential. Any pointers contained within the buffer are pointers to
/// locations within this single allocated block. The single returned buffer must be freed by calling CredFree.
/// </para>
/// </param>
/// <returns>
/// <para>
/// The function returns <c>TRUE</c> on success and <c>FALSE</c> on failure. The GetLastError function can be called to get a more
/// specific status code. The following status codes can be returned:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>ERROR_NOT_FOUND</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_LOGON_SESSION</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// If the value of the <c>Type</c> member of the CREDENTIAL structure specified by the Credential parameter is
/// <c>CRED_TYPE_DOMAIN_EXTENDED</c>, a namespace must be specified in the target name. This function can return only one credential
/// of the specified type.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credreada BOOL CredReadA( LPCSTR TargetName, DWORD Type,
// DWORD Flags, PCREDENTIALA *Credential );
[DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("wincred.h", MSDNShortId = "3222de7b-5290-4e82-a382-b2db6afc78cc")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredRead(string TargetName, CRED_TYPE Type, [Optional] uint Flags, out SafeCredMemoryHandle Credential);
/// <summary>
/// <para>
/// The <c>CredRead</c> function reads a credential from the user's credential set. The credential set used is the one associated
/// with the logon session of the current token. The token must not have the user's SID disabled.
/// </para>
/// </summary>
/// <param name="TargetName">
/// <para>Pointer to a null-terminated string that contains the name of the credential to read.</para>
/// </param>
/// <param name="Type">
/// <para>Type of the credential to read. Type must be one of the CRED_TYPE_* defined types.</para>
/// </param>
/// <param name="Credential">
/// <para>The credential.</para>
/// </param>
/// <returns>
/// <para>
/// The function returns <c>TRUE</c> on success and <c>FALSE</c> on failure. The GetLastError function can be called to get a more
/// specific status code. The following status codes can be returned:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>ERROR_NOT_FOUND</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_LOGON_SESSION</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// If the value of the <c>Type</c> member of the CREDENTIAL structure specified by the Credential parameter is
/// <c>CRED_TYPE_DOMAIN_EXTENDED</c>, a namespace must be specified in the target name. This function can return only one credential
/// of the specified type.
/// </para>
/// </remarks>
[PInvokeData("wincred.h", MSDNShortId = "3222de7b-5290-4e82-a382-b2db6afc78cc")]
public static bool CredRead(string TargetName, CRED_TYPE Type, out CREDENTIAL_MGD Credential)
{
var b = CredRead(TargetName, Type, 0, out var cred);
using (cred)
Credential = b ? cred : default;
return b;
}
/// <summary>
/// <para>
/// The <c>CredReadDomainCredentials</c> function reads the domain credentials from the user's credential set. The credential set
/// used is the one associated with the logon session of the current token. The token must not have the user's SID disabled.
/// </para>
/// </summary>
/// <param name="TargetInfo">
/// <para>
/// Target information that identifies the target server. At least one of the naming members must not be <c>NULL</c>:
/// NetbiosServerName, DnsServerName, NetbiosDomainName, DnsDomainName or DnsTreeName.
/// </para>
/// </param>
/// <param name="Flags">
/// <para>Flags controlling the operation of the function.</para>
/// <para>The following flag is defined:</para>
/// <para>CRED_CACHE_TARGET_INFORMATION</para>
/// <para>Cache the TargetInfo for a subsequent read using CredGetTargetInfo.</para>
/// </param>
/// <param name="Count">
/// <para>Count of the credentials returned in the Credentials array.</para>
/// </param>
/// <param name="Credential">
/// <para>
/// Pointer to an array of pointers to credentials. The most specific existing credential matching the TargetInfo is returned. If
/// credentials of various types (for example, CRED_TYPE_DOMAIN_PASSWORD and CRED_TYPE_DOMAIN_CERTIFICATE credentials) exist, one of
/// each type is returned. If a connection were to be made to the named target, this most-specific credential would be used.
/// </para>
/// <para>
/// Only those credential types specified by the TargetInfo.CredTypes array are returned. The returned Credentials array is sorted in
/// the same order as the TargetInfo.CredTypes array. That is, authentication packages specify a preferred credential type by
/// specifying it earlier in the TargetInfo.CredTypes array.If TargetInfo.CredTypeCount is zero, the Credentials array is returned in
/// the following sorted order:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>CRED_TYPE_DOMAIN_CERTIFICATE</term>
/// </item>
/// <item>
/// <term>CRED_TYPE_DOMAIN_PASSWORD</term>
/// </item>
/// </list>
/// <para>
/// The returned buffer is a single allocated block. Any pointers contained within the buffer are pointers to locations within this
/// single allocated block. The single returned buffer must be freed by calling CredFree.
/// </para>
/// </param>
/// <returns>
/// <para>
/// The function returns <c>TRUE</c> on success and <c>FALSE</c> on failure. The GetLastError function can be called to get a more
/// specific status code. The following status codes can be returned:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_FOUND</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_LOGON_SESSION</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// This function returns the most specific credentials matching the naming parameters. For instance, if there is a credential that
/// matches the target server name and a credential that matches the target domain name, only the server specific credential is
/// returned. This is the credential that would be used.
/// </para>
/// <para>
/// The following list specifies the order (from most specific to least specific) of what credential is returned if more than one matches:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>The credential target name is of the form &lt;DfsRoot&gt;\&lt;DfsShare&gt;, and it is an exact match on the TargetName.</term>
/// </item>
/// <item>
/// <term>An exact match on the DnsServerName.</term>
/// </item>
/// <item>
/// <term>An exact match on the NetBIOSServerName.</term>
/// </item>
/// <item>
/// <term>An exact match on TargetName.</term>
/// </item>
/// <item>
/// <term>
/// A match of the DnsServerName to a wildcard server credential. If more than one wildcard server credential matches, the credential
/// with the longer TargetName is used. That is, a credential for *.example.microsoft.com is used instead of a credential for *.microsoft.com.
/// </term>
/// </item>
/// <item>
/// <term>An exact match of the DnsDomainName to a wildcard domain credential of the form &lt;DnsDomainName&gt;\*.</term>
/// </item>
/// <item>
/// <term>An exact match of the NetBIOSDomainName to a wildcard domain credential of the form &lt;NetBIOSDomainName&gt;\*</term>
/// </item>
/// <item>
/// <term>The credential named CRED_SESSION_WILDCARD_NAME.</term>
/// </item>
/// <item>
/// <term>The credential named "*".</term>
/// </item>
/// </list>
/// <para>
/// <c>CredReadDomainCredentials</c> differs from CredRead in that it handles the idiosyncrasies of domain (CRED_TYPE_DOMAIN_PASSWORD
/// or CRED_TYPE_DOMAIN_CERTIFICATE) credentials. Domain credentials contain more than one target member.
/// </para>
/// <para>
/// If the value of the <c>Type</c> member of the CREDENTIAL structure specified by the Credentials parameter is
/// <c>CRED_TYPE_DOMAIN_EXTENDED</c>, a namespace must be specified in the target name. This function can return only one credential
/// of the specified type.
/// </para>
/// <para>
/// This function can return multiple credentials of this type, but <c>CRED_TYPE_DOMAIN_EXTENDED</c> cannot be mixed with other types
/// in the <c>CredTypes</c> member of the CREDENTIAL_TARGET_INFORMATION structure specified by the TargetInfo parameter.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credreaddomaincredentialsa BOOL
// CredReadDomainCredentialsA( PCREDENTIAL_TARGET_INFORMATIONA TargetInfo, DWORD Flags, DWORD *Count, PCREDENTIALA **Credential );
[DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("wincred.h", MSDNShortId = "b62cb9c9-2a64-4ef4-97f0-e1ea85976d3e")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredReadDomainCredentials(in CREDENTIAL_TARGET_INFORMATION TargetInfo, uint Flags, out uint Count, out SafeCredMemoryHandle Credential);
/// <summary>
/// <para>[ <c>CredRename</c> is no longer supported. Starting with Windows Vista, calls to <c>CredRename</c> always return ERROR_NOT_SUPPORTED.]</para>
/// <para>
/// The <c>CredRename</c> function renames a credential in the user's credential set. The credential set used is the one associated
/// with the logon session of the current token. The token must not have the user's SID disabled.
/// </para>
/// </summary>
/// <param name="OldTargetName">
/// <para>Pointer to a null-terminated string that contains the current name of the credential to be renamed.</para>
/// </param>
/// <param name="NewTargetName">
/// <para>Pointer to a null-terminated string that contains the new name for the credential.</para>
/// </param>
/// <param name="Type">
/// <para>Type of the credential to rename. Must be one of the CRED_TYPE_* defines.</para>
/// </param>
/// <param name="Flags">
/// <para>Flags to control the operation of the function. Currently reserved and must be zero.</para>
/// </param>
/// <returns>
/// <para>
/// The function returns <c>TRUE</c> on success and <c>FALSE</c> on failure. The GetLastError function can be called to get a more
/// specific status code. The following status codes can be returned:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>ERROR_NOT_FOUND</term>
/// </item>
/// <item>
/// <term>ERROR_ALREADY_EXISTS</term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_LOGON_SESSION</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// </item>
/// </list>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credrenamea BOOL CredRenameA( LPCSTR OldTargetName, LPCSTR
// NewTargetName, DWORD Type, DWORD Flags );
[DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto), Obsolete("CredRename is no longer supported as of Windows Vista.")]
[PInvokeData("wincred.h", MSDNShortId = "e598f2ae-f975-4dd2-bf0b-e2fd96d4c940")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredRename(string OldTargetName, string NewTargetName, CRED_TYPE Type, uint Flags = 0);
/// <summary>
/// <para>The <c>CredUnmarshalCredential</c> function transforms a marshaled credential back into its original form.</para>
/// </summary>
/// <param name="MarshaledCredential">
/// <para>Pointer to a null-terminated string that contains the marshaled credential.</para>
/// </param>
/// <param name="CredType">
/// <para>Type of credential specified by MarshaledCredential.</para>
/// <para>This is one of the CRED_MARSHAL_TYPE values.</para>
/// </param>
/// <param name="Credential">
/// <para>
/// Pointer to the unmarshaled credential. If CredType returns CertCredential, the returned pointer is to a CERT_CREDENTIAL_INFO
/// structure. If CredType returns UsernameTargetCredential, the returned pointer is to a USERNAME_TARGET_CREDENTIAL_INFO structure.
/// </para>
/// <para>The caller should free the returned buffer using CredFree.</para>
/// </param>
/// <returns>
/// <para>
/// This function returns <c>TRUE</c> on success and <c>FALSE</c> on failure. The GetLastError function can be called to get a more
/// specific status code. The following status code can be returned:
/// </para>
/// <para>ERROR_INVALID_PARAMETER</para>
/// <para>MarshaledCredential is not valid.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credunmarshalcredentiala BOOL CredUnmarshalCredentialA(
// LPCSTR MarshaledCredential, PCRED_MARSHAL_TYPE CredType, PVOID *Credential );
[DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("wincred.h", MSDNShortId = "65757235-d92c-479f-8e2b-1f8d8564792b")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredUnmarshalCredential(string MarshaledCredential, out CRED_MARSHAL_TYPE CredType, out SafeCredMemoryHandle Credential);
/// <summary>
/// <para>
/// The <c>CredUnprotect</c> function decrypts credentials that were previously encrypted by using the CredProtect function. The
/// credentials must have been encrypted in the same security context in which <c>CredUnprotect</c> is called.
/// </para>
/// </summary>
/// <param name="fAsSelf">
/// <para>
/// Set to <c>TRUE</c> to specify that the credentials were encrypted in the security context of the current process. Set to
/// <c>FALSE</c> to specify that credentials were encrypted in the security context of the calling thread security context.
/// </para>
/// </param>
/// <param name="pszProtectedCredentials">
/// <para>A pointer to a string that specifies the encrypted credentials.</para>
/// </param>
/// <param name="cchProtectedCredentials">
/// <para>The size, in characters, of the pszProtectedCredentials buffer.</para>
/// </param>
/// <param name="pszCredentials">
/// <para>A pointer to a string that, on output, receives the decrypted credentials.</para>
/// </param>
/// <param name="pcchMaxChars">
/// <para>
/// The size, in characters of the pszCredentials buffer. On output, if the pszCredentials is not of sufficient size to receive the
/// encrypted credentials, this parameter specifies the required size, in characters, of the pszCredentials buffer.
/// </para>
/// </param>
/// <returns>
/// <para><c>TRUE</c> if the function succeeds; otherwise, <c>FALSE</c>.</para>
/// <para>
/// For extended error information, call the GetLastError function. The following table shows common values for the
/// <c>GetLastError</c> function.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_NOT_CAPABLE</term>
/// <term>The security context used to encrypt the credentials is different from the security context used to decrypt the credentials.</term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICIENT_BUFFER</term>
/// <term>The pszCredentials buffer was of insufficient size.</term>
/// </item>
/// </list>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credunprotecta BOOL CredUnprotectA( BOOL fAsSelf, LPSTR
// pszProtectedCredentials, DWORD cchProtectedCredentials, LPSTR pszCredentials, DWORD *pcchMaxChars );
[DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("wincred.h", MSDNShortId = "7a22fb2b-edfc-45f2-b2d2-729f3761584d")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredUnprotect([MarshalAs(UnmanagedType.Bool)] bool fAsSelf, StringBuilder pszProtectedCredentials, uint cchProtectedCredentials, StringBuilder pszCredentials, ref uint pcchMaxChars);
/// <summary>
/// <para>
/// The <c>CredWrite</c> function creates a new credential or modifies an existing credential in the user's credential set. The new
/// credential is associated with the logon session of the current token. The token must not have the user's security identifier
/// (SID) disabled.
/// </para>
/// </summary>
/// <param name="Credential">
/// <para>A pointer to the CREDENTIAL structure to be written.</para>
/// </param>
/// <param name="Flags">
/// <para>Flags that control the function's operation. The following flag is defined.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>CRED_PRESERVE_CREDENTIAL_BLOB</term>
/// <term>
/// The credential BLOB from an existing credential is preserved with the same credential name and credential type. The
/// CredentialBlobSize of the passed in Credential structure must be zero.
/// </term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns <c>TRUE</c>.</para>
/// <para>
/// If the function fails, it returns <c>FALSE</c>. Call the GetLastError function to get a more specific status code. The following
/// status codes can be returned.
/// </para>
/// <para>Other smart card errors can be returned when writing a CRED_TYPE_CERTIFICATE credential.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_NO_SUCH_LOGON_SESSION</term>
/// <term>
/// The logon session does not exist or there is no credential set associated with this logon session. Network logon sessions do not
/// have an associated credential set.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>
/// Certain fields cannot be changed in an existing credential. This error is returned if a field does not match the value in a
/// protected field of the existing credential.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>A value that is not valid was specified for the Flags parameter.</term>
/// </item>
/// <item>
/// <term>ERROR_BAD_USERNAME</term>
/// <term>
/// The UserName member of the passed in Credential structure is not valid. For a description of valid user name syntax, see the
/// definition of that member.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_NOT_FOUND</term>
/// <term>CRED_PRESERVE_CREDENTIAL_BLOB was specified and there is no existing credential by the same TargetName and Type.</term>
/// </item>
/// <item>
/// <term>SCARD_E_NO_READERS_AVAILABLE</term>
/// <term>The CRED_TYPE_CERTIFICATE credential being written requires the smart card reader to be available.</term>
/// </item>
/// <item>
/// <term>SCARD_E_NO_SMARTCARD or SCARD_W_REMOVED_CARD</term>
/// <term>A CRED_TYPE_CERTIFICATE credential being written requires the smart card to be inserted.</term>
/// </item>
/// <item>
/// <term>SCARD_W_WRONG_CHV</term>
/// <term>The wrong PIN was supplied for the CRED_TYPE_CERTIFICATE credential being written.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// This function creates a credential if a credential with the specified <c>TargetName</c> and <c>Type</c> does not exist. If a
/// credential with the specified <c>TargetName</c> and <c>Type</c> exists, the new specified credential replaces the existing one.
/// </para>
/// <para>
/// When this function writes a CRED_TYPE_CERTIFICATE credential, the Credential-&gt; <c>CredentialBlob</c> member specifies the PIN
/// protecting the private key of the certificate specified by the Credential-&gt; <c>UserName</c> member. The credential manager
/// does not maintain the PIN. Rather, the PIN is passed to the cryptographic service provider (CSP) indicated on the certificate for
/// later use by the CSP and the authentication packages. The CSP defines the lifetime of the PIN. Most CSPs flush the PIN when the
/// smart card removal from the smart card reader.
/// </para>
/// <para>
/// If the value of the <c>Type</c> member of the CREDENTIAL structure specified by the Credential parameter is
/// <c>CRED_TYPE_DOMAIN_EXTENDED</c>, a namespace must be specified in the target name. This function does not support writing to
/// target names that contain wildcards.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credwritea BOOL CredWriteA( PCREDENTIALA Credential, DWORD
// Flags );
[DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("wincred.h", MSDNShortId = "9a590347-d610-4916-bf63-60fbec173ac2")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredWrite(in CREDENTIAL Credential, CRED_WRITE Flags);
/// <summary>
/// <para>
/// The <c>CredWriteDomainCredentials</c> function writes domain credentials to the user's credential set. The credential set used is
/// the one associated with the logon session of the current token. The token must not have the user's SID disabled.
/// </para>
/// </summary>
/// <param name="TargetInfo">
/// <para>
/// Identifies the target server. At least one of the naming members must be non- <c>NULL</c> and can be <c>NetbiosServerName</c>,
/// <c>DnsServerName</c>, <c>NetbiosDomainName</c>, <c>DnsDomainName</c>, or <c>DnsTreeName</c>.
/// </para>
/// </param>
/// <param name="Credential">
/// <para>Credential to be written.</para>
/// <para>
/// The credential must be one that matches TargetInfo For instance, if the <c>TargetName</c> is a wildcard DNS name, then the
/// <c>TargetName</c> member of the credential must be a postfix of the <c>DnsServerName</c> member from the TargetInfo.
/// </para>
/// </param>
/// <param name="Flags">
/// <para>Flags to control the operation of the API. The following flag is defined.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>CRED_PRESERVE_CREDENTIAL_BLOB</term>
/// <term>
/// The credential BLOB should be preserved from the already existing credential with the same credential name and credential type.
/// The CredentialBlobSize of the passed in Credential structure must be zero.
/// </term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns <c>TRUE</c>.</para>
/// <para>
/// If the function fails, it returns <c>FALSE</c>. Call the GetLastError function to get a more specific status code. The following
/// status codes can be returned.
/// </para>
/// <para>Other smart card errors can be returned when writing a CRED_TYPE_CERTIFICATE credential.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>
/// One or more of the parameters are not valid. Either none of the naming parameters were specified, or the credential specified did
/// not have the Type member set to CRED_TYPE_DOMAIN_PASSWORD or CRED_TYPE_DOMAIN_CERTIFICATE, or the Credential does not match the TargetInfo.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_NO_SUCH_LOGON_SESSION</term>
/// <term>
/// The logon session does not exist or there is no credential set associated with this logon session. Network logon sessions do not
/// have an associated credential set.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_FLAGS</term>
/// <term>A value that is not valid was specified for the Flags parameter.</term>
/// </item>
/// <item>
/// <term>ERROR_BAD_USERNAME</term>
/// <term>
/// The UserName member of the passed in Credential structure is not valid. For a description of valid syntaxes, see the definition
/// of that member.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_NOT_FOUND</term>
/// <term>CRED_PRESERVE_CREDENTIAL_BLOB was specified and there is no existing credential by the same TargetName and Type.</term>
/// </item>
/// <item>
/// <term>SCARD_E_NO_READERS_AVAILABLE</term>
/// <term>The CRED_TYPE_CERTIFICATE credential being written requires the smart card reader to be available.</term>
/// </item>
/// <item>
/// <term>SCARD_E_NO_SMARTCARD or SCARD_W_REMOVED_CARD: The CRED_TYPE_CERTIFICATE</term>
/// <term>The credential being written requires the smart card to be inserted.</term>
/// </item>
/// <item>
/// <term>SCARD_W_WRONG_CHV</term>
/// <term>The wrong PIN was supplied for the CRED_TYPE_CERTIFICATE credential being written.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// When this function writes a CRED_TYPE_CERTIFICATE credential, the Credential-&gt; <c>CredentialBlob</c> member specifies the PIN
/// that protects the private key of the certificate specified by the Credential-&gt; <c>UserName</c>. The credential manager does
/// not maintain the PIN. Rather, the PIN is passed to the CSP of the certificate for later use by the CSP and authentication
/// packages. The CSP defines the lifetime of the PIN. For instance, most CSPs flush the PIN upon smart card removal.
/// </para>
/// <para>
/// <c>CredWriteDomainCredentials</c> differs from CredWrite in that it handles the idiosyncrasies of domain
/// (CRED_TYPE_DOMAIN_PASSWORD or CRED_TYPE_DOMAIN_CERTIFICATE) credentials. Domain credentials contain more than one target member.
/// </para>
/// <para>
/// If the value of the <c>Type</c> member of the CREDENTIAL structure specified by the Credential parameter is
/// <c>CRED_TYPE_DOMAIN_EXTENDED</c>, a namespace must be specified in the target name.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/nf-wincred-credwritedomaincredentialsa BOOL
// CredWriteDomainCredentialsA( PCREDENTIAL_TARGET_INFORMATIONA TargetInfo, PCREDENTIALA Credential, DWORD Flags );
[DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("wincred.h", MSDNShortId = "6b54c14f-a736-4fb0-b4e4-97765a792a5e")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredWriteDomainCredentials(in CREDENTIAL_TARGET_INFORMATION TargetInfo, in CREDENTIAL Credential, CRED_WRITE Flags);
/// <summary>Undocumented.</summary>
[PInvokeData("wincred.h", MSDNShortId = "20a1d54b-04a7-4b0a-88e4-1970d1f71502")]
[StructLayout(LayoutKind.Sequential)]
public struct BINARY_BLOB_CREDENTIAL_INFO
{
/// <summary>Undocumented.</summary>
public uint cbBlob;
/// <summary>Undocumented.</summary>
public IntPtr pbBlob;
}
/// <summary>
/// <para>The <c>CERT_CREDENTIAL_INFO</c> structure contains a reference to a certificate.</para>
/// </summary>
/// <remarks>
/// <para><c>CERT_HASH_LENGTH</c> is defined as 20 in WinCred.h.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/ns-wincred-_cert_credential_info typedef struct _CERT_CREDENTIAL_INFO
// { ULONG cbSize; UCHAR rgbHashOfCert[CERT_HASH_LENGTH]; } CERT_CREDENTIAL_INFO, *PCERT_CREDENTIAL_INFO;
[PInvokeData("wincred.h", MSDNShortId = "acaa94c3-0562-420a-95c7-44a71374d5ea")]
[StructLayout(LayoutKind.Sequential)]
public struct CERT_CREDENTIAL_INFO
{
/// <summary>
/// <para>
/// Size of the structure in bytes. This member should be set to . This structure might be a larger value in the future,
/// indicating a newer version of the structure.
/// </para>
/// </summary>
public uint cbSize;
/// <summary>
/// <para>SHA-1 hash of the certificate referenced.</para>
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public byte[] rgbHashOfCert;
}
/// <summary>The CREDENTIAL structure contains an individual credential.</summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
[PInvokeData("wincred.h")]
public struct CREDENTIAL
{
/// <summary>The flags</summary>
public CRED_FLAGS Flags;
/// <summary>The type of the credential. This member cannot be changed after the credential is created.</summary>
public CRED_TYPE Type;
/// <summary>
/// The name of the credential. The TargetName and Type members uniquely identify the credential. This member cannot be changed
/// after the credential is created. Instead, the credential with the old name should be deleted and the credential with the new
/// name created.
/// <para>
/// If Type is CRED_TYPE_DOMAIN_PASSWORD or CRED_TYPE_DOMAIN_CERTIFICATE, this member identifies the server or servers that the
/// credential is to be used for. The member is either a NetBIOS or DNS server name, a DNS host name suffix that contains a
/// wildcard character, a NetBIOS or DNS domain name that contains a wildcard character sequence, or an asterisk.
/// </para>
/// <para>If TargetName is a DNS host name, the TargetAlias member can be the NetBIOS name of the host.</para>
/// <para>
/// If the TargetName is a DNS host name suffix that contains a wildcard character, the leftmost label of the DNS host name is an
/// asterisk (*), which denotes that the target name is any server whose name ends in the specified name, for example, *.microsoft.com.
/// </para>
/// <para>
/// If the TargetName is a domain name that contains a wildcard character sequence, the syntax is the domain name followed by a
/// backslash and asterisk (\*), which denotes that the target name is any server that is a member of the named domain (or realm).
/// </para>
/// <para>
/// If TargetName is a DNS domain name that contains a wildcard character sequence, the TargetAlias member can be a NetBIOS
/// domain name that uses a wildcard sequence for the same domain.
/// </para>
/// <para>
/// If TargetName specifies a DFS share, for example, DfsRoot\DfsShare, then this credential matches the specific DFS share and
/// any servers reached through that DFS share.
/// </para>
/// <para>If TargetName is a single asterisk (*), this credential matches any server name.</para>
/// <para>
/// If TargetName is CRED_SESSION_WILDCARD_NAME, this credential matches any server name. This credential matches before a single
/// asterisk and is only valid if Persist is CRED_PERSIST_SESSION. The credential can be set by applications that want to
/// temporarily override the default credential.
/// </para>
/// <para>This member cannot be longer than CRED_MAX_DOMAIN_TARGET_NAME_LENGTH (337) characters.</para>
/// <para>
/// If the Type is CRED_TYPE_GENERIC, this member should identify the service that uses the credential in addition to the actual
/// target. Microsoft suggests the name be prefixed by the name of the company implementing the service. Microsoft will use the
/// prefix "Microsoft". Services written by Microsoft should append their service name, for example Microsoft_RAS_TargetName.
/// This member cannot be longer than CRED_MAX_GENERIC_TARGET_NAME_LENGTH (32767) characters.
/// </para>
/// <para>This member is case-insensitive.</para>
/// </summary>
public StrPtrAuto TargetName;
/// <summary>
/// A string comment from the user that describes this credential. This member cannot be longer than CRED_MAX_STRING_LENGTH (256) characters.
/// </summary>
public StrPtrAuto Comment;
/// <summary>
/// The time, in Coordinated Universal Time (Greenwich Mean Time), of the last modification of the credential. For write
/// operations, the value of this member is ignored.
/// </summary>
public FILETIME LastWritten;
/// <summary>
/// The size, in bytes, of the CredentialBlob member. This member cannot be larger than CRED_MAX_CREDENTIAL_BLOB_SIZE (512) bytes.
/// </summary>
public uint CredentialBlobSize;
/// <summary>
/// Secret data for the credential. The CredentialBlob member can be both read and written.
/// <para>
/// If the Type member is CRED_TYPE_DOMAIN_PASSWORD, this member contains the plaintext Unicode password for UserName. The
/// CredentialBlob and CredentialBlobSize members do not include a trailing zero character. Also, for CRED_TYPE_DOMAIN_PASSWORD,
/// this member can only be read by the authentication packages.
/// </para>
/// <para>
/// If the Type member is CRED_TYPE_DOMAIN_CERTIFICATE, this member contains the clear test Unicode PIN for UserName. The
/// CredentialBlob and CredentialBlobSize members do not include a trailing zero character. Also, this member can only be read by
/// the authentication packages.
/// </para>
/// <para>If the Type member is CRED_TYPE_GENERIC, this member is defined by the application.</para>
/// <para>
/// Credentials are expected to be portable. Applications should ensure that the data in CredentialBlob is portable. The
/// application defines the byte-endian and alignment of the data in CredentialBlob.
/// </para>
/// </summary>
public IntPtr CredentialBlob;
/// <summary>
/// Defines the persistence of this credential. This member can be read and written.
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>CRED_PERSIST_SESSION (0x1)</term>
/// <description>
/// The credential persists for the life of the logon session. It will not be visible to other logon sessions of this same user.
/// It will not exist after this user logs off and back on.
/// </description>
/// </item>
/// <item>
/// <term>CRED_PERSIST_LOCAL_MACHINE (0x2)</term>
/// <description>
/// The credential persists for all subsequent logon sessions on this same computer. It is visible to other logon sessions of
/// this same user on this same computer and not visible to logon sessions for this user on other computers.
/// <para>
/// <c>Windows Vista Home Basic, Windows Vista Home Premium, Windows Vista Starter and Windows XP Home Edition:</c> This value is
/// not supported.
/// </para>
/// </description>
/// </item>
/// <item>
/// <term>CRED_PERSIST_ENTERPRISE (0x3)</term>
/// <description>
/// The credential persists for all subsequent logon sessions on this same computer. It is visible to other logon sessions of
/// this same user on this same computer and to logon sessions for this user on other computers.
/// <para>
/// This option can be implemented as locally persisted credential if the administrator or user configures the user account to
/// not have roam-able state. For instance, if the user has no roaming profile, the credential will only persist locally.
/// </para>
/// <para>
/// <c>Windows Vista Home Basic, Windows Vista Home Premium, Windows Vista Starter and Windows XP Home Edition:</c> This value is
/// not supported.
/// </para>
/// </description>
/// </item>
/// </list>
/// </summary>
public CRED_PERSIST Persist;
/// <summary>
/// The number of application-defined attributes to be associated with the credential. This member can be read and written. Its
/// value cannot be greater than CRED_MAX_ATTRIBUTES (64).
/// </summary>
public uint AttributeCount;
/// <summary>Application-defined attributes that are associated with the credential. This member can be read and written.</summary>
public IntPtr Attributes;
/// <summary>
/// Alias for the TargetName member. This member can be read and written. It cannot be longer than CRED_MAX_STRING_LENGTH (256) characters.
/// <para>If the credential Type is CRED_TYPE_GENERIC, this member can be non-NULL, but the credential manager ignores the member.</para>
/// </summary>
public StrPtrAuto TargetAlias;
/// <summary>
/// The user name of the account used to connect to TargetName.
/// <para>If the credential Type is CRED_TYPE_DOMAIN_PASSWORD, this member can be either a DomainName\UserName or a UPN.</para>
/// <para>
/// If the credential Type is CRED_TYPE_DOMAIN_CERTIFICATE, this member must be a marshaled certificate reference created by
/// calling CredMarshalCredential with a CertCredential.
/// </para>
/// <para>If the credential Type is CRED_TYPE_GENERIC, this member can be non-NULL, but the credential manager ignores the member.</para>
/// <para>This member cannot be longer than CRED_MAX_USERNAME_LENGTH (513) characters.</para>
/// </summary>
public StrPtrAuto UserName;
}
/// <summary>The CREDENTIAL structure contains an individual credential.</summary>
[PInvokeData("wincred.h")]
public struct CREDENTIAL_MGD
{
/// <summary>
/// The number of application-defined attributes to be associated with the credential. This member can be read and written. Its
/// value cannot be greater than CRED_MAX_ATTRIBUTES (64).
/// </summary>
public uint AttributeCount;
/// <summary>Application-defined attributes that are associated with the credential. This member can be read and written.</summary>
public byte[] Attributes;
/// <summary>
/// A string comment from the user that describes this credential. This member cannot be longer than CRED_MAX_STRING_LENGTH (256) characters.
/// </summary>
public string Comment;
/// <summary>
/// Secret data for the credential. The CredentialBlob member can be both read and written.
/// <para>
/// If the Type member is CRED_TYPE_DOMAIN_PASSWORD, this member contains the plaintext Unicode password for UserName. The
/// CredentialBlob and CredentialBlobSize members do not include a trailing zero character. Also, for CRED_TYPE_DOMAIN_PASSWORD,
/// this member can only be read by the authentication packages.
/// </para>
/// <para>
/// If the Type member is CRED_TYPE_DOMAIN_CERTIFICATE, this member contains the clear test Unicode PIN for UserName. The
/// CredentialBlob and CredentialBlobSize members do not include a trailing zero character. Also, this member can only be read by
/// the authentication packages.
/// </para>
/// <para>If the Type member is CRED_TYPE_GENERIC, this member is defined by the application.</para>
/// <para>
/// Credentials are expected to be portable. Applications should ensure that the data in CredentialBlob is portable. The
/// application defines the byte-endian and alignment of the data in CredentialBlob.
/// </para>
/// </summary>
public byte[] CredentialBlob;
/// <summary>The flags</summary>
public CRED_FLAGS Flags;
/// <summary>
/// The time, in Coordinated Universal Time (Greenwich Mean Time), of the last modification of the credential. For write
/// operations, the value of this member is ignored.
/// </summary>
public FILETIME LastWritten;
/// <summary>
/// Defines the persistence of this credential. This member can be read and written.
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>CRED_PERSIST_SESSION (0x1)</term>
/// <description>
/// The credential persists for the life of the logon session. It will not be visible to other logon sessions of this same user.
/// It will not exist after this user logs off and back on.
/// </description>
/// </item>
/// <item>
/// <term>CRED_PERSIST_LOCAL_MACHINE (0x2)</term>
/// <description>
/// The credential persists for all subsequent logon sessions on this same computer. It is visible to other logon sessions of
/// this same user on this same computer and not visible to logon sessions for this user on other computers.
/// <para>
/// <c>Windows Vista Home Basic, Windows Vista Home Premium, Windows Vista Starter and Windows XP Home Edition:</c> This value is
/// not supported.
/// </para>
/// </description>
/// </item>
/// <item>
/// <term>CRED_PERSIST_ENTERPRISE (0x3)</term>
/// <description>
/// The credential persists for all subsequent logon sessions on this same computer. It is visible to other logon sessions of
/// this same user on this same computer and to logon sessions for this user on other computers.
/// <para>
/// This option can be implemented as locally persisted credential if the administrator or user configures the user account to
/// not have roam-able state. For instance, if the user has no roaming profile, the credential will only persist locally.
/// </para>
/// <para>
/// <c>Windows Vista Home Basic, Windows Vista Home Premium, Windows Vista Starter and Windows XP Home Edition:</c> This value is
/// not supported.
/// </para>
/// </description>
/// </item>
/// </list>
/// </summary>
public CRED_PERSIST Persist;
/// <summary>
/// Alias for the TargetName member. This member can be read and written. It cannot be longer than CRED_MAX_STRING_LENGTH (256) characters.
/// <para>If the credential Type is CRED_TYPE_GENERIC, this member can be non-NULL, but the credential manager ignores the member.</para>
/// </summary>
public string TargetAlias;
/// <summary>
/// The name of the credential. The TargetName and Type members uniquely identify the credential. This member cannot be changed
/// after the credential is created. Instead, the credential with the old name should be deleted and the credential with the new
/// name created.
/// <para>
/// If Type is CRED_TYPE_DOMAIN_PASSWORD or CRED_TYPE_DOMAIN_CERTIFICATE, this member identifies the server or servers that the
/// credential is to be used for. The member is either a NetBIOS or DNS server name, a DNS host name suffix that contains a
/// wildcard character, a NetBIOS or DNS domain name that contains a wildcard character sequence, or an asterisk.
/// </para>
/// <para>If TargetName is a DNS host name, the TargetAlias member can be the NetBIOS name of the host.</para>
/// <para>
/// If the TargetName is a DNS host name suffix that contains a wildcard character, the leftmost label of the DNS host name is an
/// asterisk (*), which denotes that the target name is any server whose name ends in the specified name, for example, *.microsoft.com.
/// </para>
/// <para>
/// If the TargetName is a domain name that contains a wildcard character sequence, the syntax is the domain name followed by a
/// backslash and asterisk (\*), which denotes that the target name is any server that is a member of the named domain (or realm).
/// </para>
/// <para>
/// If TargetName is a DNS domain name that contains a wildcard character sequence, the TargetAlias member can be a NetBIOS
/// domain name that uses a wildcard sequence for the same domain.
/// </para>
/// <para>
/// If TargetName specifies a DFS share, for example, DfsRoot\DfsShare, then this credential matches the specific DFS share and
/// any servers reached through that DFS share.
/// </para>
/// <para>If TargetName is a single asterisk (*), this credential matches any server name.</para>
/// <para>
/// If TargetName is CRED_SESSION_WILDCARD_NAME, this credential matches any server name. This credential matches before a single
/// asterisk and is only valid if Persist is CRED_PERSIST_SESSION. The credential can be set by applications that want to
/// temporarily override the default credential.
/// </para>
/// <para>This member cannot be longer than CRED_MAX_DOMAIN_TARGET_NAME_LENGTH (337) characters.</para>
/// <para>
/// If the Type is CRED_TYPE_GENERIC, this member should identify the service that uses the credential in addition to the actual
/// target. Microsoft suggests the name be prefixed by the name of the company implementing the service. Microsoft will use the
/// prefix "Microsoft". Services written by Microsoft should append their service name, for example Microsoft_RAS_TargetName.
/// This member cannot be longer than CRED_MAX_GENERIC_TARGET_NAME_LENGTH (32767) characters.
/// </para>
/// <para>This member is case-insensitive.</para>
/// </summary>
public string TargetName;
/// <summary>The type of the credential. This member cannot be changed after the credential is created.</summary>
public CRED_TYPE Type;
/// <summary>
/// The user name of the account used to connect to TargetName.
/// <para>If the credential Type is CRED_TYPE_DOMAIN_PASSWORD, this member can be either a DomainName\UserName or a UPN.</para>
/// <para>
/// If the credential Type is CRED_TYPE_DOMAIN_CERTIFICATE, this member must be a marshaled certificate reference created by
/// calling CredMarshalCredential with a CertCredential.
/// </para>
/// <para>If the credential Type is CRED_TYPE_GENERIC, this member can be non-NULL, but the credential manager ignores the member.</para>
/// <para>This member cannot be longer than CRED_MAX_USERNAME_LENGTH (513) characters.</para>
/// </summary>
public string UserName;
/// <summary>Initializes a new instance of the <see cref="CREDENTIAL_MGD"/> struct.</summary>
/// <param name="c">The c.</param>
internal CREDENTIAL_MGD(in CREDENTIAL c)
{
Flags = c.Flags;
Type = c.Type;
TargetName = c.TargetName;
Comment = c.Comment;
LastWritten = c.LastWritten;
CredentialBlob = c.CredentialBlob.ToArray<byte>((int)c.CredentialBlobSize);
Persist = c.Persist;
AttributeCount = c.AttributeCount;
Attributes = c.Attributes.ToArray<byte>((int)c.AttributeCount);
TargetAlias = c.TargetAlias;
UserName = c.UserName;
}
}
/// <summary>
/// <para>The <c>CREDENTIAL_TARGET_INFORMATION</c> structure contains the target computer's name, domain, and tree.</para>
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/ns-wincred-_credential_target_informationa typedef struct
// _CREDENTIAL_TARGET_INFORMATIONA { LPSTR TargetName; LPSTR NetbiosServerName; LPSTR DnsServerName; LPSTR NetbiosDomainName; LPSTR
// DnsDomainName; LPSTR DnsTreeName; LPSTR PackageName; ULONG Flags; DWORD CredTypeCount; LPDWORD CredTypes; }
// CREDENTIAL_TARGET_INFORMATIONA, *PCREDENTIAL_TARGET_INFORMATIONA;
[PInvokeData("wincred.h", MSDNShortId = "92180f2c-ef7c-4481-9b6f-19234c114afb")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct CREDENTIAL_TARGET_INFORMATION
{
/// <summary>
/// Name of the target server as specified by the caller accessing the target. It is typically the NetBIOS or DNS name of the
/// target server.
/// </summary>
public string TargetName;
/// <summary>NetBIOS name of the target server. If the name is not known, this member can be NULL.</summary>
public string NetbiosServerName;
/// <summary>DNS name of the target server. If the name is not known, this member can be NULL.</summary>
public string DnsServerName;
/// <summary>
/// NetBIOS name of the target server's domain. If the name is not known, this member can be NULL. If the target server is a
/// member of a workgroup, this member must be NULL.
/// </summary>
public string NetbiosDomainName;
/// <summary>
/// DNS name of the target server's domain. If the name is not known, this member can be NULL. If the target server is a member
/// of a workgroup, this member must be NULL.
/// </summary>
public string DnsDomainName;
/// <summary>
/// DNS name of the target server's tree. If the tree name is not known, this member can be NULL. If the target server is a
/// member of a workgroup, this member must be NULL.
/// </summary>
public string DnsTreeName;
/// <summary>
/// Name of the authentication package that determined the values NetbiosServerName, DnsServerName, NetbiosDomainName,
/// DnsDomainName, and DnsTreeName as a function of TargetName. This member can be passed to AcquireCredentialsHandle as the
/// package name.
/// </summary>
public string PackageName;
/// <summary>
/// Attributes of the target.
/// <list type="bullet">
/// <item>
/// <term>CRED_TI_SERVER_FORMAT_UNKNOWN (0x1)</term>
/// <description>
/// Set if the authentication package cannot determine whether the server name is a DNS name or a NetBIOS name. In that case, the
/// NetbiosServerName member is set to NULL and the DnsServerName member is set to the server name of unknown format.
/// </description>
/// </item>
/// <item>
/// <term>CRED_TI_DOMAIN_FORMAT_UNKNOWN (0x2)</term>
/// <description>
/// Set if the authentication package cannot determine whether the domain name is a DNS name or a NetBIOS name. In that case, the
/// NetbiosDomainName member is set to NULL and the DnsDomainName member is set to the domain name of unknown format.
/// </description>
/// </item>
/// <item>
/// <term>CRED_TI_ONLY_PASSWORD_REQUIRED (0x4)</term>
/// <description>
/// Set if the authentication package has determined that the server only needs a password to authenticate. The caller can use
/// this flag to prompt only for a password and not a user name.
/// </description>
/// </item>
/// </list>
/// <para>
/// Stored credentials require a UserName member. A value of &lt;DnsServerName&gt;\Guest or &lt;NetbiosServerName&gt;\Guest
/// should be used for these servers.
/// </para>
/// </summary>
public uint Flags;
/// <summary>Number of elements in the CredTypes array.</summary>
public uint CredTypeCount;
/// <summary>
/// Array specifying the credential types acceptable by the authentication package used by the target server. Each element is one
/// of the CRED_TYPE_* defines. The order of this array specifies the preference order of the authentication package. More
/// preferable types are specified earlier in the list.
/// </summary>
public IntPtr CredTypes;
/// <summary>Extracts array of <see cref="CRED_TYPE"/> values from <see cref="CredTypes"/>.</summary>
public CRED_TYPE[] GetCredTypes() => CredTypes.ToArray<CRED_TYPE>((int)CredTypeCount);
}
/// <summary>
/// <para>
/// The <c>USERNAME_TARGET_CREDENTIAL_INFO</c> structure contains a reference to a credential. This structure is used to pass a user
/// name into the CredMarshalCredential function and out of the CredUnmarshalCredential. The resultant marshaled credential can be
/// passed as the lpszUserName parameter of the LogonUser function to direct that API to get the password from the corresponding
/// CRED_FLAGS_USERNAME_TARGET credential instead of from the lpszPassword parameter of the function.
/// </para>
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/wincred/ns-wincred-_username_target_credential_info typedef struct
// _USERNAME_TARGET_CREDENTIAL_INFO { LPWSTR UserName; } USERNAME_TARGET_CREDENTIAL_INFO, *PUSERNAME_TARGET_CREDENTIAL_INFO;
[PInvokeData("wincred.h", MSDNShortId = "1cb56a85-fafd-4471-b0e9-660ac0dc0219")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct USERNAME_TARGET_CREDENTIAL_INFO
{
/// <summary>
/// <para>User name of the USERNAME_TARGET_CREDENTIAL_INFO credential.</para>
/// </summary>
public string UserName;
}
/// <summary>Safe handle for WinCred functions.</summary>
public class SafeCredMemoryHandle : GenericSafeHandle
{
/// <summary>Initializes a new instance of the <see cref="SafeCredMemoryHandle"/> class.</summary>
public SafeCredMemoryHandle() : this(IntPtr.Zero) { }
/// <summary>Initializes a new instance of the <see cref="SafeCredMemoryHandle"/> class.</summary>
/// <param name="ptr">The pointer to the memory allocated by an WinCred function.</param>
/// <param name="own">if set to <c>true</c> release the memory when out of scope.</param>
public SafeCredMemoryHandle(IntPtr ptr, bool own = true) : base(ptr, h => { CredFree(h); return true; }, own) { }
/// <summary>Performs an implicit conversion from <see cref="SafeCredMemoryHandle"/> to <see cref="CREDENTIAL"/>.</summary>
/// <param name="h">The handle.</param>
/// <returns>The resulting <see cref="CREDENTIAL"/> instance from the conversion.</returns>
public static implicit operator CREDENTIAL(SafeCredMemoryHandle h) => h.ToStructure<CREDENTIAL>();
/// <summary>Performs an implicit conversion from <see cref="SafeCredMemoryHandle"/> to <see cref="CREDENTIAL_MGD"/>.</summary>
/// <param name="h">The handle.</param>
/// <returns>The resulting <see cref="CREDENTIAL_MGD"/> instance from the conversion.</returns>
public static implicit operator CREDENTIAL_MGD(SafeCredMemoryHandle h) => new CREDENTIAL_MGD(h.ToStructure<CREDENTIAL>());
/// <summary>Performs an implicit conversion from <see cref="SafeCredMemoryHandle"/> to <see cref="CREDENTIAL_TARGET_INFORMATION"/>.</summary>
/// <param name="h">The handle.</param>
/// <returns>The resulting <see cref="CREDENTIAL_TARGET_INFORMATION"/> instance from the conversion.</returns>
public static implicit operator CREDENTIAL_TARGET_INFORMATION(SafeCredMemoryHandle h) => h.ToStructure<CREDENTIAL_TARGET_INFORMATION>();
/// <summary>Performs an implicit conversion from <see cref="SafeCredMemoryHandle"/> to <see cref="System.String"/>.</summary>
/// <param name="h">The handle.</param>
/// <returns>The resulting <see cref="System.String"/> instance from the conversion.</returns>
public static implicit operator string(SafeCredMemoryHandle h) => Marshal.PtrToStringAuto(h.handle);
/// <summary>Marshals data to the type specified by a generic type parameter.</summary>
/// <typeparam name="T">The type of the object to which the data is to be copied. This must be a structure.</typeparam>
/// <returns>A managed object that contains the data of type <typeparamref name="T"/>.</returns>
/// <exception cref="InsufficientMemoryException"></exception>
public T ToStructure<T>() => handle.ToStructure<T>();
internal CREDENTIAL_MGD[] GetCredArray(int count) => handle.ToIEnum<IntPtr>(count).Select(p => new CREDENTIAL_MGD(p.ToStructure<CREDENTIAL>())).ToArray();
}
}
}