/// <summary>
        /// Saves the given Network Credential into Windows Credential store
        /// </summary>
        /// <param name="target">Name of the application/Url where the credential is used for</param>
        /// <param name="credential">Credential to store</param>
        /// <returns>True:Success, throw if failed</returns>
        public static bool SaveCredentials(string target, NetworkCredential credential)
        {
            // Go ahead with what we have are stuff it into the CredMan structures.
            var cred = new Credential(credential)
            {
                TargetName = target, Persist = NativeCode.Persistance.Entrprise
            };

            NativeCode.NativeCredential ncred = cred.GetNativeCredential();

            // Write the info into the CredMan storage.
            if (NativeCode.CredWrite(ref ncred, 0))
            {
                return(true);
            }

            int    lastError = Marshal.GetLastWin32Error();
            string message   = String.Format("'CredWrite' call throw an error (Error code: {0})", lastError);

            throw new Win32Exception(lastError, message);
        }
        /// <summary>
        /// Saves the given Network Credential into Windows Credential store
        /// </summary>
        /// <param name="Target">Name of the application/Url where the credential is used for</param>
        /// <param name="credential">Credential to store</param>
        /// <returns>True:Success, False:Failure</returns>
        public static bool SaveCredentials(string Target, NetworkCredential credential)
        {
            // Go ahead with what we have are stuff it into the CredMan structures.
            Credential cred = new Credential(credential);

            cred.TargetName = Target;
            cred.Persist    = NativeCode.Persistance.Entrprise;
            NativeCode.NativeCredential ncred = cred.GetNativeCredential();
            // Write the info into the CredMan storage.
            bool written   = NativeCode.CredWrite(ref ncred, 0);
            int  lastError = Marshal.GetLastWin32Error();

            if (written)
            {
                return(true);
            }
            else
            {
                string message = string.Format("CredWrite failed with the error code {0}.", lastError);
                throw new Exception(message);
            }
        }
        public bool SaveCredential(bool AllowBlankPassword = false)
        {
            IntPtr   buffer = default(IntPtr);
            GCHandle pinned = default(GCHandle);

            if (!String.IsNullOrEmpty(this.Comment) && Encoding.Unicode.GetBytes(this.Comment).Length > 256)
            {
                throw new ArgumentException("Comment can't be more than 256 bytes long", "Comment");
            }

            if (String.IsNullOrEmpty(this.TargetName))
            {
                throw new ArgumentNullException("TargetName", "TargetName can't be Null or Empty");
            }
            else if (this.TargetName.Length > 32767)
            {
                throw new ArgumentNullException("TargetName can't be more than 32kB", "TargetName");
            }

            if (!AllowBlankPassword && String.IsNullOrEmpty(this.CredentialBlob))
            {
                throw new ArgumentNullException("CredentialBlob", "CredentialBlob can't be Null or Empty");
            }

            NativeCode.NativeCredential ncred = new NativeCode.NativeCredential
            {
                Comment            = this.Comment,
                TargetAlias        = null,
                Type               = (UInt32)this.Type,
                Persist            = (UInt32)this.Persistance,
                UserName           = this.UserName,
                TargetName         = this.TargetName,
                CredentialBlobSize = (UInt32)Encoding.Unicode.GetBytes(this.CredentialBlob).Length
            };
            if (ncred.CredentialBlobSize > MaxCredentialBlobSize)
            {
                throw new ArgumentException($"Credential can't be more than {MaxCredentialBlobSize} bytes long", "CredentialBlob");
            }

            ncred.CredentialBlob = Marshal.StringToCoTaskMemUni(this.CredentialBlob);
            if (this.LastWritten != DateTime.MinValue)
            {
                var fileTime = this.LastWritten.ToFileTimeUtc();
                ncred.LastWritten.dwLowDateTime  = (int)(fileTime & 0xFFFFFFFFL);
                ncred.LastWritten.dwHighDateTime = (int)((fileTime >> 32) & 0xFFFFFFFFL);
            }

            NativeCode.NativeCredentialAttribute[] nativeAttribs = null;
            try
            {
                if (Attributes == null || Attributes.Count == 0)
                {
                    ncred.AttributeCount = 0;
                    ncred.Attributes     = IntPtr.Zero;
                }
                else
                {
                    if (Attributes.Count > 64)
                    {
                        throw new ArgumentException("Credentials can't have more than 64 Attributes!!");
                    }

                    ncred.AttributeCount = (UInt32)Attributes.Count;
                    nativeAttribs        = new NativeCode.NativeCredentialAttribute[Attributes.Count];
                    var    attribSize = Marshal.SizeOf(typeof(NativeCode.NativeCredentialAttribute));
                    byte[] rawData    = new byte[Attributes.Count * attribSize];
                    buffer = Marshal.AllocHGlobal(attribSize);
                    var formatter = new BinaryFormatter();

                    var i = 0;
                    foreach (var a in Attributes)
                    {
                        if (a.Key.Length > 256)
                        {
                            throw new ArgumentException($"Attribute names can't be more than 256 bytes long. Error with key:{a.Key}", a.Key);
                        }
                        if (a.Value == null)
                        {
                            throw new ArgumentNullException(a.Key, $"Attribute value cant'be null. Error with key:{a.Key}");
                        }
                        if (!a.Value.GetType().IsSerializable)
                        {
                            throw new ArgumentException($"Attribute value must be Serializable. Error with key:{a.Key}", a.Key);
                        }

                        using var stream = new MemoryStream();
                        formatter.Serialize(stream, a.Value);
                        var value = stream.ToArray();

                        if (value.Length > 256)
                        {
                            throw new ArgumentException($"Attribute values can't be more than 256 bytes long after serialization. Error with Value for key:{a.Key}", a.Key);
                        }

                        var attrib = new NativeCode.NativeCredentialAttribute
                        {
                            Keyword   = a.Key,
                            ValueSize = (UInt32)value.Length
                        };

                        attrib.Value = Marshal.AllocHGlobal(value.Length);
                        Marshal.Copy(value, 0, attrib.Value, value.Length);
                        nativeAttribs[i] = attrib;

                        Marshal.StructureToPtr(attrib, buffer, false);
                        Marshal.Copy(buffer, rawData, i * attribSize, attribSize);
                        i++;
                    }
                    pinned           = GCHandle.Alloc(rawData, GCHandleType.Pinned);
                    ncred.Attributes = pinned.AddrOfPinnedObject();
                }
                // Write the info into the CredMan storage.

                if (NativeCode.CredWrite(ref ncred, 0))
                {
                    return(true);
                }
                else
                {
                    int lastError = Marshal.GetLastWin32Error();
                    throw new CredentialAPIException($"Unable to Save Credential", "CredWrite", lastError);
                }
            }

            finally
            {
                if (ncred.CredentialBlob != default(IntPtr))
                {
                    Marshal.FreeCoTaskMem(ncred.CredentialBlob);
                }
                if (nativeAttribs != null)
                {
                    foreach (var a in nativeAttribs)
                    {
                        if (a.Value != default(IntPtr))
                        {
                            Marshal.FreeHGlobal(a.Value);
                        }
                    }
                    if (pinned.IsAllocated)
                    {
                        pinned.Free();
                    }
                    if (buffer != default(IntPtr))
                    {
                        Marshal.FreeHGlobal(buffer);
                    }
                }
            }
        }