Export (0) Print
Expand All
Expand Minimize

Marshal.SecureStringToGlobalAllocUnicode Method

Updated: September 2010

Copies the contents of a managed SecureString object into unmanaged memory.

Namespace:  System.Runtime.InteropServices
Assembly:  mscorlib (in mscorlib.dll)

[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static IntPtr SecureStringToGlobalAllocUnicode(
	SecureString s
)

Parameters

s
Type: System.Security.SecureString

The managed object to be copied.

Return Value

Type: System.IntPtr
The address, in unmanaged memory, where s was copied, or 0 if s is a SecureString object whose length is 0.

ExceptionCondition
ArgumentNullException

The s parameter is null.

NotSupportedException

The current computer is not running Windows 2000 Service Pack 3 or later.

OutOfMemoryException

There is insufficient memory available.

The SecureStringToGlobalAllocUnicode method is useful for custom marshaling or for use when mixing managed and unmanaged code. Since this method allocates the unmanaged memory required for a string, always free the memory by calling the ZeroFreeGlobalAllocUnicode method.

NoteNote:

This method uses SecurityAction.LinkDemand to prevent it from being called from untrusted code; only the immediate caller is required to have SecurityPermissionAttribute.UnmanagedCode permission. If your code can be called from partially trusted code, do not pass user input to Marshal class methods without validation. For important limitations on using the LinkDemand member, see Demand vs. LinkDemand.

Notes to Callers:

This method is only supported on computers running Windows 2000 Service Pack 3 or later.

The following code example demonstrates how to use the SecureStringToGlobalAllocUnicode method to with the unmanaged LogonUser function to perform impersonation with the SecureString class. The example then uses the ZeroFreeGlobalAllocUnicode method to zero out and free the unmanaged string reference.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Principal;
using System.Text;

namespace SecureStringImpersonationExample
{

    class ImpersonationExample
    {

        // PInvoke into the Win32 API to provide access to the  
        // LogonUser and CloseHandle functions.
        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        internal static extern bool LogonUser(String username, String domain, IntPtr password,
                int logonType, int logonProvider, ref IntPtr token);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public extern static bool CloseHandle(IntPtr handle);

        // Define the required LogonUser enumerations. 
        const int LOGON32_PROVIDER_DEFAULT = 0;
        const int LOGON32_LOGON_INTERACTIVE = 2;


        static void Main(string[] args)
        {
            try
            {
                // Display the current user before impersonation.
                Console.WriteLine("Before impersonation: "
                    + WindowsIdentity.GetCurrent().Name);

                // Ask the user for a network domain.
                Console.Write("Please enter your domain:");

                string domain = Console.ReadLine();

                // Ask the user for a user name.
                Console.Write("Please enter your user name:");

                string username = Console.ReadLine();

                // Ask the user for a password.
                Console.Write("Please enter your password:");

                SecureString passWord = GetPassword();

                // Impersonate the account provided by the user.
                WindowsImpersonationContext userContext = ImpersonateUser(passWord, username, domain);

                // Display the current user after impersonation.
                Console.WriteLine("After impersonation: "
                    + WindowsIdentity.GetCurrent().Name);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            Console.ReadLine();


        }

        public static SecureString GetPassword()
        {
            SecureString password = new SecureString();

            // get the first character of the password
            ConsoleKeyInfo nextKey = Console.ReadKey(true);

            while (nextKey.Key != ConsoleKey.Enter)
            {
                if (nextKey.Key == ConsoleKey.Backspace)
                {
                    if (password.Length > 0)
                    {
                        password.RemoveAt(password.Length - 1);

                        // erase the last * as well
                        Console.Write(nextKey.KeyChar);
                        Console.Write(" ");
                        Console.Write(nextKey.KeyChar);
                    }
                }
                else
                {
                    password.AppendChar(nextKey.KeyChar);
                    Console.Write("*");
                }

                nextKey = Console.ReadKey(true);
            }

            Console.WriteLine();

            // lock the password down
            password.MakeReadOnly();
            return password;
        }


        public static WindowsImpersonationContext ImpersonateUser(SecureString password, string userName, string domainName)
        {
            IntPtr tokenHandle = IntPtr.Zero;

            IntPtr passwordPtr = IntPtr.Zero;

            bool returnValue = false;

            try
            {
                // Marshal the SecureString to unmanaged memory.
                passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(password);

                // Call LogonUser, passing the unmanaged (and decrypted) copy of 
                // the SecureString password.
                returnValue = LogonUser(userName, domainName, passwordPtr, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle);

            }
            finally
            {
                // Zero-out and free the unmanaged string reference.
                Marshal.ZeroFreeGlobalAllocUnicode(passwordPtr);

                // Close the token handle.
                CloseHandle(tokenHandle);
            }

            // Get the Last win32 Error and throw an exception. 
            if (!returnValue && tokenHandle == IntPtr.Zero)
            {
                int error = Marshal.GetLastWin32Error();

                throw new System.ComponentModel.Win32Exception(error);

            }
            // The token that is passed to the following constructor must  
            // be a primary token in order to use it for impersonation.
            WindowsIdentity newId = new WindowsIdentity(tokenHandle);

            return newId.Impersonate();
        }
    }
}

Windows 7, Windows Vista, Windows XP SP2, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP Starter Edition, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, Windows Server 2000 SP4, Windows Millennium Edition, Windows 98

The .NET Framework and .NET Compact Framework do not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.

.NET Framework

Supported in: 3.5, 3.0, 2.0

Date

History

Reason

September 2010

Clarified that 0 is returned if the length of s is 0.

Customer feedback.

Community Additions

ADD
Show:
© 2015 Microsoft