public object MarshalNativeToManaged(IntPtr pNativeData)
            {
                if (pNativeData == IntPtr.Zero)
                {
                    return(null);
                }

                var ncred = (NATIVECREDENTIAL)Marshal.PtrToStructure(pNativeData, typeof(NATIVECREDENTIAL));

                var securePass = (ncred.CredentialBlob == IntPtr.Zero) ? new SecureString()
                                : SecureStringHelper.CreateSecureString(ncred.CredentialBlob, (int)(ncred.CredentialBlobSize) / 2);

                var credEx = new PSObject(new PSCredential(ncred.UserName ?? "-", securePass));

                credEx.Members.Add(new PSNoteProperty("Target", ncred.TargetName));
                credEx.Members.Add(new PSNoteProperty("TargetAlias", ncred.TargetAlias));
                credEx.Members.Add(new PSNoteProperty("Type", (CredentialType)ncred.Type));
                credEx.Members.Add(new PSNoteProperty("Persistence", (PersistanceType)ncred.Persist));
                credEx.Members.Add(new PSNoteProperty("Description", ncred.Comment));
                credEx.Members.Add(new PSNoteProperty("LastWriteTime", DateTime.FromFileTime((((long)ncred.LastWritten.dwHighDateTime) << 32) + ncred.LastWritten.dwLowDateTime)));

                return(credEx);
            }
Exemplo n.º 2
0
        public override DialogResult ShowDialog(IntPtr owner)
        {
            CheckNotDisposed();

            if (string.IsNullOrEmpty(Title) && string.IsNullOrEmpty(Message))
            {
                throw new InvalidOperationException("Title or Message should always be set.");
            }

            if (!IsWinVistaOrHigher)
            {
                throw new InvalidOperationException("This Operating System does not support this prompt.");
            }

            uint   authPackage = 0;
            IntPtr outCredBuffer;
            uint   outCredSize;
            IntPtr inCredBuffer     = IntPtr.Zero;
            int    inCredBufferSize = 0;

            bool persist = SaveChecked;

            NativeMethods.CREDUI_INFO credUI = CreateCREDUI_INFO(owner);

            if (!string.IsNullOrEmpty(Username) || !string.IsNullOrEmpty(SecureStringHelper.CreateString(SecurePassword)))
            {
                // This seems to be very hacky but don't know a better way to do it yet
                // Call this method with the same credentials with the empty credentials buffer so that we can get it's size first
                // but it throws an error because the buffer is too small. So we'll re-initialize the buffer with correct size
                // and call again to populate the buffer this time.
                NativeMethods.CredPackAuthenticationBuffer(0, new StringBuilder(Username), new StringBuilder(SecureStringHelper.CreateString(SecurePassword)), inCredBuffer, ref inCredBufferSize);
                if (Marshal.GetLastWin32Error() == 122)
                {
                    // returned from prior method call and we now should have a valid size for the buffer
                    inCredBuffer = Marshal.AllocCoTaskMem(inCredBufferSize);
                    if (!NativeMethods.CredPackAuthenticationBuffer(0, new StringBuilder(Username), new StringBuilder(SecureStringHelper.CreateString(SecurePassword)), inCredBuffer, ref inCredBufferSize))
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error(), "There was an issue with the given Username or Password.");
                    }
                }
            }

            //Show the dialog
            NativeMethods.CredUIReturnCodes dialogResult;
            try
            {
                dialogResult = NativeMethods.CredUIPromptForWindowsCredentials(ref credUI, ErrorCode, ref authPackage,
                                                                               inCredBuffer,
                                                                               //You can force that a specific username is shown in the dialog. Create it with 'CredPackAuthenticationBuffer()'. Then, the buffer goes here...
                                                                               (uint)inCredBufferSize,
                                                                               //...and the size goes here. You also have to add CREDUIWIN_IN_CRED_ONLY to the flags (last argument).
                                                                               out outCredBuffer,
                                                                               out outCredSize,
                                                                               ref persist,
                                                                               DialogFlags);
                // If the user has checked the Save Credentials checkbox then the persist variable
                // will be set to true and we want to set it so that the consumer can approprietly act
                // on the user action.
                SaveChecked = persist;
            }
            catch (EntryPointNotFoundException e)
            {
                throw new InvalidOperationException("This functionality is not supported by this operating system.", e);
            }
            switch (dialogResult)
            {
            case NativeMethods.CredUIReturnCodes.ERROR_CANCELLED:
                return(DialogResult.Cancel);

            case NativeMethods.CredUIReturnCodes.ERROR_NO_SUCH_LOGON_SESSION:
            case NativeMethods.CredUIReturnCodes.ERROR_NOT_FOUND:
            case NativeMethods.CredUIReturnCodes.ERROR_INVALID_ACCOUNT_NAME:
            case NativeMethods.CredUIReturnCodes.ERROR_INSUFFICIENT_BUFFER:
            case NativeMethods.CredUIReturnCodes.ERROR_INVALID_PARAMETER:
            case NativeMethods.CredUIReturnCodes.ERROR_INVALID_FLAGS:
            case NativeMethods.CredUIReturnCodes.ERROR_BAD_ARGUMENTS:
                throw new InvalidOperationException("Invalid properties were specified.", new Win32Exception(Marshal.GetLastWin32Error()));
            }

            int maxUsername = 1000;
            int maxPassword = 1000;
            int maxDomain   = 1000;

            StringBuilder usernameBuffer = new StringBuilder(1000);
            StringBuilder passwordBuffer = new StringBuilder(1000);
            StringBuilder domainBuffer   = new StringBuilder(1000);

            bool result = NativeMethods.CredUnPackAuthenticationBuffer(0, outCredBuffer, outCredSize,
                                                                       usernameBuffer,
                                                                       ref maxUsername, domainBuffer,
                                                                       ref maxDomain,
                                                                       passwordBuffer, ref maxPassword);

            if (result)
            {
                NativeMethods.CoTaskMemFree(outCredBuffer);

                Username = usernameBuffer.ToString();
                Password = passwordBuffer.ToString();

                if (passwordBuffer.Length > 0)
                {
                    passwordBuffer.Remove(0, passwordBuffer.Length);
                }
            }

            return(DialogResult.OK);
        }