zoukankan      html  css  js  c++  java
  • RunAsUser

    /****************************** Module Header ******************************\
    * Module Name:  CppRunAsUser.cpp
    * Project:      CppRunAsUser
    * Copyright (c) Microsoft Corporation.
    *
    *
    *
    * This source is subject to the Microsoft Public License.
    * See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
    * All other rights reserved.
    *
    * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
    * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
    * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
    \***************************************************************************/

    #pragma region Includes and Manifest Dependencies
    #include <stdio.h>
    #include <windows.h>
    #include <windowsx.h>
    #include "Resource.h"

    #include <userenv.h>
    #pragma comment(lib, "userenv.lib")

    // Enable Visual Style
    #if defined _M_IX86
    #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
    #elif defined _M_IA64
    #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
    #elif defined _M_X64
    #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
    #else
    #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
    #endif
    #pragma endregion


    #pragma region Helper Functions

    //
    //   FUNCTION: ReportError(LPWSTR, DWORD)
    //
    //   PURPOSE: Display an error dialog for the failure of a certain function.
    //
    //   PARAMETERS:
    //   * pszFunction - the name of the function that failed.
    //   * dwError - the Win32 error code. Its default value is the calling
    //   thread's last-error code value.
    //
    //   NOTE: The failing function must be immediately followed by the call of
    //   ReportError if you do not explicitly specify the dwError parameter of
    //   ReportError. This is to ensure that the calling thread's last-error code
    //   value is not overwritten by any calls of API between the failing
    //   function and ReportError.
    //
    void ReportError(LPWSTR pszFunction, DWORD dwError = GetLastError())
    {
        wchar_t szMessage[200];
        int len = swprintf_s(szMessage, ARRAYSIZE(szMessage),
            L"%s failed w/err 0x%08lx", pszFunction, dwError);
        MessageBox(NULL, (len != -1) ? szMessage : pszFunction,
            L"An error occurred!", MB_ICONERROR);
    }


    //
    //   FUNCTION: GetLogonSID(HANDLE, PSID *)
    //
    //   PURPOSE: Obtain the logon SID of the user.
    //
    //   PARAMETERS:
    //   * hToken -
    //   * ppSid -
    //
    BOOL GetLogonSID(HANDLE hToken, PSID *ppSid)
    {
        BOOL fSucceeded = FALSE;
        DWORD cbTokenGroups = 0;
        PTOKEN_GROUPS pTokenGroups = NULL;
        DWORD dwIndex = 0;
        DWORD dwLength = 0;

        // Get required buffer size and allocate the TOKEN_GROUPS buffer.
        if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &cbTokenGroups))
        {
            if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
            {
                ReportError(L"GetTokenInformation");
                goto Exit;
            }

            pTokenGroups = (PTOKEN_GROUPS)LocalAlloc(LPTR, cbTokenGroups);
            if (pTokenGroups == NULL)
            {
                ReportError(L"LocalAlloc");
                goto Exit;
            }
        }

        // Get the token group information from the access token.
        if (!GetTokenInformation(hToken, TokenGroups, pTokenGroups,
            cbTokenGroups, &cbTokenGroups))
        {
            ReportError(L"GetTokenInformation");
            goto Exit;
        }

        // Loop through the groups to find the logon SID.
        for (dwIndex = 0; dwIndex < pTokenGroups->GroupCount; dwIndex++)
        {
            if ((pTokenGroups->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID)
                ==  SE_GROUP_LOGON_ID)
            {
                // Found the logon SID; make a copy of it.

                // Determine the length of the SID.
                dwLength = GetLengthSid(pTokenGroups->Groups[dwIndex].Sid);

                // Allocate a buffer for the logon SID.
                *ppSid = (PSID)LocalAlloc(LPTR, dwLength);
                if (*ppSid == NULL)
                {
                    ReportError(L"LocalAlloc");
                    goto Exit;
                }

                // Obtain a copy of the logon SID.
                if (!CopySid(dwLength, *ppSid, pTokenGroups->Groups[dwIndex].Sid))
                {
                    ReportError(L"CopySid");
                    goto Exit;
                }

                break;
            }
        }

        fSucceeded = TRUE;

    Exit:

        // Centralized cleanup for all allocated resources. Clean up only those
        // which were allocated, and clean them up in the right order.

        if (pTokenGroups)
        {
            if (LocalFree(pTokenGroups))
            {
                fSucceeded = FALSE;
                ReportError(L"LocalFree");
            }
            // Set variable to same state as resources
            pTokenGroups = NULL;
            cbTokenGroups = 0;
        }

        return fSucceeded;
    }


    //
    //   FUNCTION: FreeLogonSID(PSID *)
    //
    //   PURPOSE: Free the logon SID of the user.
    //
    //   PARAMETERS:
    //   * pSid -
    //
    void FreeLogonSID(PSID *ppSid)
    {
        if (LocalFree(*ppSid))
        {
            ReportError(L"LocalFree");
        }
    }


    #define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | \
        GENERIC_ALL)

    #define WINSTA_ALL (WINSTA_ACCESSCLIPBOARD  | WINSTA_ACCESSGLOBALATOMS | \
       WINSTA_CREATEDESKTOP    | WINSTA_ENUMDESKTOPS      | \
       WINSTA_ENUMERATE        | WINSTA_EXITWINDOWS       | \
       WINSTA_READATTRIBUTES   | WINSTA_READSCREEN        | \
       WINSTA_WRITEATTRIBUTES  | DELETE                   | \
       READ_CONTROL            | WRITE_DAC                | \
       WRITE_OWNER)

    #define DESKTOP_ALL (DESKTOP_CREATEMENU      | DESKTOP_CREATEWINDOW  | \
       DESKTOP_ENUMERATE       | DESKTOP_HOOKCONTROL   | \
       DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD | \
       DESKTOP_READOBJECTS     | DESKTOP_SWITCHDESKTOP | \
       DESKTOP_WRITEOBJECTS    | DELETE                | \
       READ_CONTROL            | WRITE_DAC             | \
       WRITE_OWNER)


    BOOL AddAceToWindowStation(HWINSTA hWinsta, PSID pSid)
    {
        BOOL fSucceeded = FALSE;
        SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;

        DWORD cbSd = 0;
        PSECURITY_DESCRIPTOR pSd = NULL;
        BOOL fDaclPresent = FALSE;
        BOOL fDaclExist = FALSE;
        ACL_SIZE_INFORMATION aclSizeInfo = { 0 };
        DWORD cbDacl = 0;
        PACL pDacl = NULL;

        PSECURITY_DESCRIPTOR pNewSd = NULL;
        DWORD cbNewDacl = 0;
        PACL pNewDacl = NULL;
        DWORD cbNewAce = 0;
        PACCESS_ALLOWED_ACE pNewAce = NULL;

        DWORD dwIndex = 0;
        PVOID pTempAce = NULL;

        // Get required buffer size and allocate the SECURITY_DESCRIPTOR buffer.
        if (!GetUserObjectSecurity(hWinsta, &si, NULL, 0, &cbSd))
        {
            if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
            {
                ReportError(L"GetUserObjectSecurity");
                goto Exit;
            }

            pSd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, cbSd);
            if (pSd == NULL)
            {
                ReportError(L"LocalAlloc");
                goto Exit;
            }
        }

        // Obtain the security descriptor for the window station.
        if (!GetUserObjectSecurity(hWinsta, &si, pSd, cbSd, &cbSd))
        {
            ReportError(L"GetUserObjectSecurity");
            goto Exit;
        }

        // Get the DACL from the security descriptor.
        if (!GetSecurityDescriptorDacl(pSd, &fDaclPresent, &pDacl, &fDaclExist))
        {
            ReportError(L"GetSecurityDescriptorDacl");
            goto Exit;
        }

        // Get the size information of the DACL.
        if (pDacl == NULL)
        {
            // If GetSecurityDescriptorDacl stores a NULL value in the pointer
            // pointed to by pDacl, the security descriptor has a NULL DACL. A
            // NULL DACL implicitly allows all access to an object.
            cbDacl = 0;
        }
        else
        {
            if (!GetAclInformation(pDacl, (LPVOID)&aclSizeInfo,
                sizeof(aclSizeInfo), AclSizeInformation))
            {
                ReportError(L"GetAclInformation");
                goto Exit;
            }
            cbDacl = aclSizeInfo.AclBytesInUse;
        }

        // Allocate memory for the new security descriptor.
        pNewSd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, cbSd);
        if (pNewSd == NULL)
        {
            ReportError(L"LocalAlloc");
            goto Exit;
        }

        // Initialize the new security descriptor.
        if (!InitializeSecurityDescriptor(pNewSd, SECURITY_DESCRIPTOR_REVISION))
        {
            ReportError(L"InitializeSecurityDescriptor");
            goto Exit;
        }

        // Compute the size of a DACL to be added to the new security descriptor.
        cbNewAce = sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pSid) - sizeof(DWORD);
        cbNewDacl = (cbDacl == 0 ? sizeof(ACL) : cbDacl) + 2 * cbNewAce;

        // Allocate memory for the new DACL.
        pNewDacl = (PACL)LocalAlloc(LPTR, cbNewDacl);
        if (pNewDacl == NULL)
        {
            ReportError(L"LocalAlloc");
            goto Exit;
        }

        // Initialize the new DACL.
        if (!InitializeAcl(pNewDacl, cbNewDacl, ACL_REVISION))
        {
            ReportError(L"InitializeAcl");
            goto Exit;
        }

        // If the original DACL is present, copy it to the new DACL.
        if (fDaclPresent)
        {
            // Copy the ACEs to the new DACL.
            if (aclSizeInfo.AceCount)
            {
                for (dwIndex = 0; dwIndex < aclSizeInfo.AceCount; dwIndex++)
                {
                    // Get an ACE.
                    if (!GetAce(pDacl, dwIndex, &pTempAce))
                    {
                        ReportError(L"GetAce");
                        goto Exit;
                    }

                    // Add the ACE to the new ACL.
                    if (!AddAce(pNewDacl, ACL_REVISION, MAXDWORD, pTempAce,
                        ((PACE_HEADER)pTempAce)->AceSize))
                    {
                        ReportError(L"AddAce");
                        goto Exit;
                    }
                }
            }
        }

        // Add two new ACEs to the new DACL to allow the SID full access to the
        // interactive window station.

        pNewAce = (PACCESS_ALLOWED_ACE)LocalAlloc(LPTR, cbNewAce);
        if (pNewAce == NULL)
        {
            ReportError(L"LocalAlloc");
            goto Exit;
        }

        pNewAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
        pNewAce->Header.AceFlags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE |
            OBJECT_INHERIT_ACE;
        pNewAce->Header.AceSize = (WORD)cbNewAce;
        pNewAce->Mask = GENERIC_ACCESS;
        if (!CopySid(GetLengthSid(pSid), &pNewAce->SidStart, pSid))
        {
            ReportError(L"CopySid");
            goto Exit;
        }

        if (!AddAce(pNewDacl, ACL_REVISION, MAXDWORD, (LPVOID)pNewAce,
            pNewAce->Header.AceSize))
        {
            ReportError(L"AddAce");
            goto Exit;
        }

        pNewAce->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE;
        pNewAce->Mask = WINSTA_ALL;

        if (!AddAce(pNewDacl, ACL_REVISION, MAXDWORD, (LPVOID)pNewAce,
            pNewAce->Header.AceSize))
        {
            ReportError(L"AddAce");
            goto Exit;
        }

        // Assign the new DACL to the new security descriptor.
        if (!SetSecurityDescriptorDacl(pNewSd, TRUE, pNewDacl, FALSE))
        {
            ReportError(L"SetSecurityDescriptorDacl");
            goto Exit;
        }

        // Set the new security descriptor for the window station.
        if (!SetUserObjectSecurity(hWinsta, &si, pNewSd))
        {
            ReportError(L"SetUserObjectSecurity");
            goto Exit;
        }

        fSucceeded = TRUE;

    Exit:

        // Centralized cleanup for all allocated resources. Clean up only those
        // which were allocated, and clean them up in the right order.

        if (pSd)
        {
            if (LocalFree(pSd))
            {
                fSucceeded = FALSE;
                ReportError(L"LocalFree");
            }
            pSd = NULL;
            cbSd = 0;
        }

        if (pNewSd)
        {
            if (LocalFree(pNewSd))
            {
                fSucceeded = FALSE;
                ReportError(L"LocalFree");
            }
            pNewSd = NULL;
        }

        if (pNewDacl)
        {
            if (LocalFree(pNewDacl))
            {
                fSucceeded = FALSE;
                ReportError(L"LocalFree");
            }
            pNewDacl = NULL;
            cbNewDacl = 0;
        }

        if (pNewAce)
        {
            if (LocalFree(pNewAce))
            {
                fSucceeded = FALSE;
                ReportError(L"LocalFree");
            }
            pNewAce = NULL;
            cbNewAce = 0;
        }

        return fSucceeded;
    }


    BOOL AddAceToDesktop(HDESK hDesktop, PSID pSid)
    {
        BOOL fSucceeded = FALSE;
        SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;

        DWORD cbSd = 0;
        PSECURITY_DESCRIPTOR pSd = NULL;
        BOOL fDaclPresent = FALSE;
        BOOL fDaclExist = FALSE;
        ACL_SIZE_INFORMATION aclSizeInfo = { 0 };
        DWORD cbDacl = 0;
        PACL pDacl = NULL;

        PSECURITY_DESCRIPTOR pNewSd = NULL;
        DWORD cbNewDacl = 0;
        PACL pNewDacl = NULL;
        DWORD cbNewAce = 0;
        PACCESS_ALLOWED_ACE pNewAce = NULL;

        DWORD dwIndex = 0;
        PVOID pTempAce = NULL;

        // Get required buffer size and allocate the SECURITY_DESCRIPTOR buffer.
        if (!GetUserObjectSecurity(hDesktop, &si, NULL, 0, &cbSd))
        {
            if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
            {
                ReportError(L"GetUserObjectSecurity");
                goto Exit;
            }

            pSd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, cbSd);
            if (pSd == NULL)
            {
                ReportError(L"LocalAlloc");
                goto Exit;
            }
        }

        // Obtain the security descriptor for the desktop object.
        if (!GetUserObjectSecurity(hDesktop, &si, pSd, cbSd, &cbSd))
        {
            ReportError(L"GetUserObjectSecurity");
            goto Exit;
        }

        // Get the DACL from the security descriptor.
        if (!GetSecurityDescriptorDacl(pSd, &fDaclPresent, &pDacl, &fDaclExist))
        {
            ReportError(L"GetSecurityDescriptorDacl");
            goto Exit;
        }

        // Get the size information of the DACL.
        if (pDacl == NULL)
        {
            cbDacl = 0;
        }
        else
        {
            if (!GetAclInformation(pDacl, (LPVOID)&aclSizeInfo,
                sizeof(aclSizeInfo), AclSizeInformation))
            {
                ReportError(L"GetAclInformation");
                goto Exit;
            }
            cbDacl = aclSizeInfo.AclBytesInUse;
        }

        // Allocate memory for the new security descriptor.
        pNewSd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, cbSd);
        if (pNewSd == NULL)
        {
            ReportError(L"LocalAlloc");
            goto Exit;
        }

        // Initialize the new security descriptor.
        if (!InitializeSecurityDescriptor(pNewSd, SECURITY_DESCRIPTOR_REVISION))
        {
            ReportError(L"InitializeSecurityDescriptor");
            goto Exit;
        }

        // Compute the size of a DACL to be added to the new security descriptor.
        cbNewAce = sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pSid) - sizeof(DWORD);
        cbNewDacl = (cbDacl == 0 ? sizeof(ACL) : cbDacl) + cbNewAce;

        // Allocate memory for the new DACL.
        pNewDacl = (PACL)LocalAlloc(LPTR, cbNewDacl);
        if (pNewDacl == NULL)
        {
            ReportError(L"LocalAlloc");
            goto Exit;
        }

        // Initialize the new DACL.
        if (!InitializeAcl(pNewDacl, cbNewDacl, ACL_REVISION))
        {
            ReportError(L"InitializeAcl");
            goto Exit;
        }

        // If the original DACL is present, copy it to the new DACL.
        if (fDaclPresent)
        {
            // Copy the ACEs to the new DACL.
            if (aclSizeInfo.AceCount)
            {
                for (dwIndex = 0; dwIndex < aclSizeInfo.AceCount; dwIndex++)
                {
                    // Get an ACE.
                    if (!GetAce(pDacl, dwIndex, &pTempAce))
                    {
                        ReportError(L"GetAce");
                        goto Exit;
                    }

                    // Add the ACE to the new ACL.
                    if (!AddAce(pNewDacl, ACL_REVISION, MAXDWORD, pTempAce,
                        ((PACE_HEADER)pTempAce)->AceSize))
                    {
                        ReportError(L"AddAce");
                        goto Exit;
                    }
                }
            }
        }

        // Add a new ACE to the new DACL.
        if (!AddAccessAllowedAce(pNewDacl, ACL_REVISION, DESKTOP_ALL, pSid))
        {
            ReportError(L"AddAccessAllowedAce");
            goto Exit;
        }

        // Assign the new DACL to the new security descriptor.
        if (!SetSecurityDescriptorDacl(pNewSd, TRUE, pNewDacl, FALSE))
        {
            ReportError(L"SetSecurityDescriptorDacl");
            goto Exit;
        }

        //  Set the new security descriptor for the desktop object.
        if (!SetUserObjectSecurity(hDesktop, &si, pNewSd))
        {
            ReportError(L"SetUserObjectSecurity");
            goto Exit;
        }

        fSucceeded = TRUE;

    Exit:

        // Centralized cleanup for all allocated resources. Clean up only those
        // which were allocated, and clean them up in the right order.

        if (pSd)
        {
            if (LocalFree(pSd))
            {
                fSucceeded = FALSE;
                ReportError(L"LocalFree");
            }
            pSd = NULL;
            cbSd = 0;
        }

        if (pNewSd)
        {
            if (LocalFree(pNewSd))
            {
                fSucceeded = FALSE;
                ReportError(L"LocalFree");
            }
            pNewSd = NULL;
        }

        if (pNewDacl)
        {
            if (LocalFree(pNewDacl))
            {
                fSucceeded = FALSE;
                ReportError(L"LocalFree");
            }
            pNewDacl = NULL;
            cbNewDacl = 0;
        }

        if (pNewAce)
        {
            if (LocalFree(pNewAce))
            {
                fSucceeded = FALSE;
                ReportError(L"LocalFree");
            }
            pNewAce = NULL;
            cbNewAce = 0;
        }

        return fSucceeded;
    }

    #pragma endregion


    #pragma region CreateInteractiveProcessWithLogon

    //
    //   FUNCTION: CreateInteractiveProcessWithLogon(LPCWSTR, LPCWSTR, LPCWSTR, LPWSTR)
    //
    //   PURPOSE:
    //
    //   PARAMETERS:
    //   * pszUserName - A pointer to a null-terminated string that specifies the
    //   name of the user. This is the name of the user account to log on to. If
    //   you use the user principal name (UPN) format, User@DNSDomainName, the
    //   pszDomain parameter must be NULL.
    //   * pszDomain - A pointer to a null-terminated string that specifies the
    //   name of the domain or server whose account database contains the
    //   pszUsername account. If this parameter is NULL, the user name must be
    //   specified in UPN format. If this parameter is ".", the function validates
    //   the account by using only the local account database.
    //   * pszPassword - A pointer to a null-terminated string that specifies the
    //   plaintext password for the user account specified by lpszUsername. When
    //   you have finished using the password, clear the password from memory by
    //   calling the SecureZeroMemory function.
    //   * pszCommandLine - The command line to be executed. The maximum length
    //   of this string is 1024 characters. The module name portion of
    //   pszCommandLine is limited to MAX_PATH characters.
    //
    //   NOTE:
    //
    BOOL CreateInteractiveProcessWithLogon(LPCWSTR pszUserName,
                                           LPCWSTR pszDomain,
                                           LPCWSTR pszPassword,
                                           LPWSTR pszCommandLine)
    {
        BOOL fSucceeded = FALSE;
        HANDLE hToken = NULL;
        LPVOID lpvEnv = NULL;
        wchar_t szUserProfile[MAX_PATH];
        DWORD dwSize = 0;
        STARTUPINFO si = { sizeof(si) };
        PROCESS_INFORMATION pi = { 0 };

        // Attempt to log the user on to the local computer. The logon type is
        // intended for users who will be interactively using the computer.
        if (!LogonUser(pszUserName, pszDomain, pszPassword,
            LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken))
        {
            ReportError(L"LogonUser");
            goto Exit;
        }

        // Retrieve the environment variables for the specified user. The
        // environment block inherits from the current process's environment.
        if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))
        {
            ReportError(L"CreateEnvironmentBlock");
            goto Exit;
        }

        // Retrieve the path to the root directory of the user's profile.
        dwSize = ARRAYSIZE(szUserProfile);
        if (!GetUserProfileDirectory(hToken, szUserProfile, &dwSize))
        {
            ReportError(L"GetUserProfileDirectory");
            goto Exit;
        }

        // If the lpDesktop member of the STARTUPINFO structure is initialized
        // to either NULL or "", CreateProcessWithLogonW implementation adds
        // permissions for the specified user account to the window station and
        // desktop inherited from the parent process, which is "winsta0\default"
        // for the "Default" application desktop.
        si.lpDesktop = NULL;

        // Launch the interative child process.
        if (!CreateProcessWithLogonW(pszUserName, pszDomain, pszPassword,
            LOGON_WITH_PROFILE, NULL, pszCommandLine,
            CREATE_UNICODE_ENVIRONMENT, lpvEnv, szUserProfile, &si, &pi))
        {
            ReportError(L"CreateProcessWithLogonW");
            goto Exit;
        }

        // The child process is running now ...

        // (Optional) Wait for the exit of the child process.
        //WaitForSingleObject(pi.hProcess);

        fSucceeded = TRUE;

    Exit:

        // Centralized cleanup for all allocated resources. Clean up only those
        // which were allocated, and clean them up in the right order.

        if (hToken)
        {
            if (!CloseHandle(hToken))
            {
                fSucceeded = FALSE;
                ReportError(L"CloseHandle");
            }
            hToken = NULL;
        }

        if (lpvEnv)
        {
            if (!DestroyEnvironmentBlock(lpvEnv))
            {
                fSucceeded = FALSE;
                ReportError(L"DestroyEnvironmentBlock");
            }
            lpvEnv = NULL;
        }

        if (pi.hProcess)
        {
            if (!CloseHandle(pi.hProcess))
            {
                fSucceeded = FALSE;
                ReportError(L"CloseHandle");
            }
            pi.hProcess = NULL;
        }

        if (pi.hThread)
        {
            if (!CloseHandle(pi.hThread))
            {
                fSucceeded = FALSE;
                ReportError(L"CloseHandle");
            }
            pi.hThread = NULL;
        }

        return fSucceeded;
    }

    #pragma endregion


    #pragma region CreateInteractiveProcessWithToken

    //
    //   FUNCTION: CreateInteractiveProcessWithToken(LPCWSTR, LPCWSTR, LPCWSTR, LPWSTR)
    //
    //   PURPOSE:
    //
    //   PARAMETERS:
    //   * pszUserName - A pointer to a null-terminated string that specifies the
    //   name of the user. This is the name of the user account to log on to. If
    //   you use the user principal name (UPN) format, User@DNSDomainName, the
    //   pszDomain parameter must be NULL.
    //   * pszDomain - A pointer to a null-terminated string that specifies the
    //   name of the domain or server whose account database contains the
    //   pszUsername account. If this parameter is NULL, the user name must be
    //   specified in UPN format. If this parameter is ".", the function validates
    //   the account by using only the local account database.
    //   * pszPassword - A pointer to a null-terminated string that specifies the
    //   plaintext password for the user account specified by lpszUsername. When
    //   you have finished using the password, clear the password from memory by
    //   calling the SecureZeroMemory function.
    //   * pszCommandLine - The command line to be executed. The maximum length
    //   of this string is 1024 characters. The module name portion of
    //   pszCommandLine is limited to MAX_PATH characters.
    //
    //   NOTE:
    //
    BOOL CreateInteractiveProcessWithToken(LPCWSTR pszUserName,
                                           LPCWSTR pszDomain,
                                           LPCWSTR pszPassword,
                                           LPWSTR pszCommandLine)
    {
        BOOL fSucceeded = FALSE;
        HANDLE hToken = NULL;
        HWINSTA hWinstaSave = NULL;
        HWINSTA hWinsta = NULL;
        HDESK hDesktop = NULL;
        PSID pSid = NULL;
        wchar_t szUserProfile[MAX_PATH];
        DWORD dwSize = ARRAYSIZE(szUserProfile);
        STARTUPINFO si = { sizeof(si) };
        PROCESS_INFORMATION pi = { 0 };

        // Attempt to log the user on to the local computer. The logon type is
        // intended for users who will be interactively using the computer.
        if (!LogonUser(pszUserName, pszDomain, pszPassword,
            LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken))
        {
            ReportError(L"LogonUser");
            goto Exit;
        }

        // Save a handle to the caller's current window station.
        hWinstaSave = GetProcessWindowStation();
        if (hWinstaSave == NULL)
        {
            ReportError(L"GetProcessWindowStation");
            goto Exit;
        }

        // Get a handle to the interactive window station.
        hWinsta = OpenWindowStation(
            L"winsta0",                  // The interactive window station
            FALSE,                       // Handle is not inheritable
            READ_CONTROL | WRITE_DAC);   // Rights to read/write the DACL
        if (hWinsta == NULL)
        {
            ReportError(L"OpenWindowStation");
            goto Exit;
        }

        // To get the correct default desktop, set the caller's window station
        // to the interactive window station.
        if (!SetProcessWindowStation(hWinsta))
        {
            ReportError(L"SetProcessWindowStation");
            goto Exit;
        }

        // Get a handle to the interactive desktop.
        hDesktop = OpenDesktop(
            L"default",            // The interactive window station
            0,                     // No interaction with other desktop processes
            FALSE,                 // Handle is not inheritable
            READ_CONTROL | WRITE_DAC | DESKTOP_WRITEOBJECTS |
            DESKTOP_READOBJECTS);  // Rights to read/write the DACL

        // Restore the caller's window station.
        if (!SetProcessWindowStation(hWinstaSave))
        {
            ReportError(L"SetProcessWindowStation");
            goto Exit;
        }

        if (hDesktop == NULL)
        {
            ReportError(L"OpenDesktop");
            goto Exit;
        }

        // Get the SID for the client's logon session.
        if (!GetLogonSID(hToken, &pSid))
        {
            goto Exit;
        }

        // Allow logon SID full access to interactive window station.
        if (!AddAceToWindowStation(hWinsta, pSid))
        {
            goto Exit;
        }

        // Allow logon SID full access to interactive desktop.
        if (!AddAceToDesktop(hDesktop, pSid))
        {
            goto Exit;
        }

        // Retrieve the path to the root directory of the user's profile.
        if (!GetUserProfileDirectory(hToken, szUserProfile, &dwSize))
        {
            ReportError(L"GetUserProfileDirectory");
            goto Exit;
        }

        // Specify that the child process runs in the interactive desktop.
        si.lpDesktop = L"winsta0\\default";

        // Launch the process in the client's logon session.
        if (!CreateProcessWithTokenW(hToken, LOGON_WITH_PROFILE, NULL,
            pszCommandLine, CREATE_UNICODE_ENVIRONMENT, NULL, szUserProfile,
            &si, &pi))
        {
            ReportError(L"CreateProcessWithTokenW");
            goto Exit;
        }

        // The child process is running now ...

        // (Optional) Wait for the exit of the child process.
        //WaitForSingleObject(pi.hProcess);

        fSucceeded = TRUE;

    Exit:

        // Centralized cleanup for all allocated resources. Clean up only those
        // which were allocated, and clean them up in the right order.

        if (hToken)
        {
            if (!CloseHandle(hToken))
            {
                fSucceeded = FALSE;
                ReportError(L"CloseHandle");
            }
            hToken = NULL;
        }

        if (hWinsta)
        {
            if (!CloseWindowStation(hWinsta))
            {
                fSucceeded = FALSE;
                ReportError(L"CloseWindowStation");
            }
            hWinsta = NULL;
        }

        if (hDesktop)
        {
            if (!CloseDesktop(hDesktop))
            {
                fSucceeded = FALSE;
                ReportError(L"CloseDesktop");
            }
            hDesktop = NULL;
        }

        if (pSid)
        {
            FreeLogonSID(&pSid);
            pSid = NULL;
        }

        if (pi.hProcess)
        {
            if (!CloseHandle(pi.hProcess))
            {
                fSucceeded = FALSE;
                ReportError(L"CloseHandle");
            }
            pi.hProcess = NULL;
        }

        if (pi.hThread)
        {
            if (!CloseHandle(pi.hThread))
            {
                fSucceeded = FALSE;
                ReportError(L"CloseHandle");
            }
            pi.hThread = NULL;
        }

        return fSucceeded;
    }

    #pragma endregion


    #pragma region CreateInteractiveProcessAsUser


    //
    //   FUNCTION: CreateInteractiveProcessAsUser(LPCWSTR, LPCWSTR, LPCWSTR, LPWSTR)
    //
    //   PURPOSE:
    //
    //   PARAMETERS:
    //   * pszUserName - A pointer to a null-terminated string that specifies the
    //   name of the user. This is the name of the user account to log on to. If
    //   you use the user principal name (UPN) format, User@DNSDomainName, the
    //   pszDomain parameter must be NULL.
    //   * pszDomain - A pointer to a null-terminated string that specifies the
    //   name of the domain or server whose account database contains the
    //   pszUsername account. If this parameter is NULL, the user name must be
    //   specified in UPN format. If this parameter is ".", the function validates
    //   the account by using only the local account database.
    //   * pszPassword - A pointer to a null-terminated string that specifies the
    //   plaintext password for the user account specified by lpszUsername. When
    //   you have finished using the password, clear the password from memory by
    //   calling the SecureZeroMemory function.
    //   * pszCommandLine - The command line to be executed. The maximum length
    //   of this string is 1024 characters. The module name portion of
    //   pszCommandLine is limited to MAX_PATH characters.
    //
    //   NOTE:
    //
    BOOL CreateInteractiveProcessAsUser(LPCWSTR pszUserName,
                                        LPCWSTR pszDomain,
                                        LPCWSTR pszPassword,
                                        LPWSTR pszCommandLine)
    {
        BOOL fSucceeded = FALSE;
        HANDLE hToken = NULL;
        HWINSTA hWinstaSave = NULL;
        HWINSTA hWinsta = NULL;
        HDESK hDesktop = NULL;
        PSID pSid = NULL;
        wchar_t szUserProfile[MAX_PATH];
        DWORD dwSize = ARRAYSIZE(szUserProfile);
        STARTUPINFO si = { sizeof(si) };
        PROCESS_INFORMATION pi = { 0 };

        // Attempt to log the user on to the local computer. The logon type is
        // intended for users who will be interactively using the computer.
        if (!LogonUser(pszUserName, pszDomain, pszPassword,
            LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken))
        {
            ReportError(L"LogonUser");
            goto Exit;
        }

        // Save a handle to the caller's current window station.
        hWinstaSave = GetProcessWindowStation();
        if (hWinstaSave == NULL)
        {
            ReportError(L"GetProcessWindowStation");
            goto Exit;
        }

        // Get a handle to the interactive window station.
        hWinsta = OpenWindowStation(
            L"winsta0",                  // The interactive window station
            FALSE,                       // Handle is not inheritable
            READ_CONTROL | WRITE_DAC);   // Rights to read/write the DACL
        if (hWinsta == NULL)
        {
            ReportError(L"OpenWindowStation");
            goto Exit;
        }

        // To get the correct default desktop, set the caller's window station
        // to the interactive window station.
        if (!SetProcessWindowStation(hWinsta))
        {
            ReportError(L"SetProcessWindowStation");
            goto Exit;
        }

        // Get a handle to the interactive desktop.
        hDesktop = OpenDesktop(
            L"default",            // The interactive window station
            0,                     // No interaction with other desktop processes
            FALSE,                 // Handle is not inheritable
            READ_CONTROL | WRITE_DAC | DESKTOP_WRITEOBJECTS |
            DESKTOP_READOBJECTS);  // Rights to read/write the DACL

        // Restore the caller's window station.
        if (!SetProcessWindowStation(hWinstaSave))
        {
            ReportError(L"SetProcessWindowStation");
            goto Exit;
        }

        if (hDesktop == NULL)
        {
            ReportError(L"OpenDesktop");
            goto Exit;
        }

        // Get the SID for the client's logon session.
        if (!GetLogonSID(hToken, &pSid))
        {
            goto Exit;
        }

        // Allow logon SID full access to interactive window station.
        if (!AddAceToWindowStation(hWinsta, pSid))
        {
            goto Exit;
        }

        // Allow logon SID full access to interactive desktop.
        if (!AddAceToDesktop(hDesktop, pSid))
        {
            goto Exit;
        }

        // Retrieve the path to the root directory of the user's profile.
        if (!GetUserProfileDirectory(hToken, szUserProfile, &dwSize))
        {
            ReportError(L"GetUserProfileDirectory");
            goto Exit;
        }

        // Specify that the child process runs in the interactive desktop.
        si.lpDesktop = L"winsta0\\default";

        // Launch the process in the client's logon session. The process that
        // calls the CreateProcessAsUser function must have the
        // SE_ASSIGNPRIMARYTOKEN_NAME and SE_INCREASE_QUOTA_NAME privileges.
        // Generally only processes run as the SYSTEM account has both
        // privileges. The function fails with the ERROR_PRIVILEGE_NOT_HELD
        // (0x522) error when the required privileges are not available.
        if (!CreateProcessAsUser(hToken, NULL, pszCommandLine, NULL, NULL, FALSE,
            CREATE_UNICODE_ENVIRONMENT, NULL, szUserProfile, &si, &pi))
        {
            ReportError(L"CreateProcessAsUser");
            goto Exit;
        }

        // The child process is running now ...

        // (Optional) Wait for the exit of the child process.
        //WaitForSingleObject(pi.hProcess);

        fSucceeded = TRUE;

    Exit:

        // Centralized cleanup for all allocated resources. Clean up only those
        // which were allocated, and clean them up in the right order.

        if (hToken)
        {
            if (!CloseHandle(hToken))
            {
                fSucceeded = FALSE;
                ReportError(L"CloseHandle");
            }
            hToken = NULL;
        }

        if (hWinsta)
        {
            if (!CloseWindowStation(hWinsta))
            {
                fSucceeded = FALSE;
                ReportError(L"CloseWindowStation");
            }
            hWinsta = NULL;
        }

        if (hDesktop)
        {
            if (!CloseDesktop(hDesktop))
            {
                fSucceeded = FALSE;
                ReportError(L"CloseDesktop");
            }
            hDesktop = NULL;
        }

        if (pSid)
        {
            FreeLogonSID(&pSid);
            pSid = NULL;
        }

        if (pi.hProcess)
        {
            if (!CloseHandle(pi.hProcess))
            {
                fSucceeded = FALSE;
                ReportError(L"CloseHandle");
            }
            pi.hProcess = NULL;
        }

        if (pi.hThread)
        {
            if (!CloseHandle(pi.hThread))
            {
                fSucceeded = FALSE;
                ReportError(L"CloseHandle");
            }
            pi.hThread = NULL;
        }

        return fSucceeded;
    }

    #pragma endregion


    void OnCreateProcess(HWND hWnd, int id)
    {
        int cchText;
        DWORD cbUserName = 0;
        PWSTR pszUserName = NULL;
        DWORD cbDomain = 0;
        PWSTR pszDomain = NULL;
        DWORD cbPassword = 0;
        PWSTR pszPassword = NULL;
        DWORD cbCommand = 0;
        PWSTR pszCommand = NULL;

        // Get the user name from the dialog.
        HWND hUserNameEdit = GetDlgItem(hWnd, IDC_USERNAME_EDIT);
        cchText = GetWindowTextLength(hUserNameEdit);
        if (cchText == 0)
        {
            MessageBox(hWnd, L"User Name cannot be empty", L"Error", MB_ICONERROR);
            goto Exit;
        }
        cbUserName = (cchText + 1) * sizeof(*pszUserName);
        pszUserName = (PWSTR)LocalAlloc(LPTR, cbUserName);
        GetWindowText(hUserNameEdit, pszUserName, cchText + 1);

        // Get the domain from the dialog.
        HWND hDomainEdit = GetDlgItem(hWnd, IDC_DOMAIN_EDIT);
        cchText = GetWindowTextLength(hDomainEdit);
        if (cchText != 0)
        {
            cbDomain = (cchText + 1) * sizeof(*pszDomain);
            pszDomain = (PWSTR)LocalAlloc(LPTR, cbDomain);
            GetWindowText(hDomainEdit, pszDomain, cchText + 1);
        }

        // Get the password from the dialog.
        HWND hPasswordEdit = GetDlgItem(hWnd, IDC_PASSWORD_EDIT);
        cchText = GetWindowTextLength(hPasswordEdit);
        if (cchText != 0)
        {
            cbPassword = (cchText + 1) * sizeof(*pszPassword);
            pszPassword = (PWSTR)LocalAlloc(LPTR, cbPassword);
            GetWindowText(hPasswordEdit, pszPassword, cchText + 1);
        }

        // Get the command from the dialog.
        HWND hCommandEdit = GetDlgItem(hWnd, IDC_COMMAND_EDIT);
        cchText = GetWindowTextLength(hCommandEdit);
        if (cchText == 0)
        {
            MessageBox(hWnd, L"Command cannot be empty", L"Error", MB_ICONERROR);
            goto Exit;
        }
        cbCommand = (cchText + 1) * sizeof(*pszCommand);
        pszCommand = (PWSTR)LocalAlloc(LPTR, cbCommand);
        GetWindowText(hCommandEdit, pszCommand, cchText + 1);

        // Create the child process.

        switch (id)
        {
        case IDC_CREATEPROCESSWITHLOGON_BN:
            if (!CreateInteractiveProcessWithLogon(pszUserName, pszDomain,
                pszPassword, pszCommand))
            {
                ReportError(L"CreateInteractiveProcessWithLogon");
            }
            break;

        case IDC_CREATEPROCESSWITHTOKEN_BN:
            if (!CreateInteractiveProcessWithToken(pszUserName, pszDomain,
                pszPassword, pszCommand))
            {
                ReportError(L"CreateInteractiveProcessWithToken");
            }
            break;

        case IDC_CREATEPROCESSASUSER_BN:
            if (!CreateInteractiveProcessAsUser(pszUserName, pszDomain,
                pszPassword, pszCommand))
            {
                ReportError(L"CreateInteractiveProcessAsUser");
            }
            break;
        }

    Exit:

        if (pszUserName)
        {
            if (LocalFree(pszUserName))
            {
                ReportError(L"LocalFree");
            }
            pszUserName = NULL;
            cbUserName = 0;
        }

        if (pszDomain)
        {
            if (LocalFree(pszDomain))
            {
                ReportError(L"LocalFree");
            }
            pszDomain = NULL;
            cbDomain = 0;
        }

        if (pszPassword)
        {
            SecureZeroMemory(pszPassword, cbPassword);
            if (LocalFree(pszPassword))
            {
                ReportError(L"LocalFree");
            }
            pszPassword = NULL;
            cbPassword = 0;
        }

        if (pszCommand)
        {
            if (LocalFree(pszCommand))
            {
                ReportError(L"LocalFree");
            }
            pszCommand = NULL;
            cbCommand = 0;
        }
    }


    //
    //   FUNCTION: OnInitDialog(HWND, HWND, LPARAM)
    //
    //   PURPOSE: Process the WM_INITDIALOG message.
    //
    BOOL OnInitDialog(HWND hWnd, HWND hwndFocus, LPARAM lParam)
    {
        return TRUE;
    }


    //
    //   FUNCTION: OnCommand(HWND, int, HWND, UINT)
    //
    //   PURPOSE: Process the WM_COMMAND message.
    //
    void OnCommand(HWND hWnd, int id, HWND hwndCtl, UINT codeNotify)
    {
        switch (id)
        {
        case IDC_CREATEPROCESSWITHLOGON_BN:
        case IDC_CREATEPROCESSWITHTOKEN_BN:
        case IDC_CREATEPROCESSASUSER_BN:
            OnCreateProcess(hWnd, id);
            break;
        case IDOK:
        case IDCANCEL:
            EndDialog(hWnd, 0);
            break;
        }
    }


    //
    //   FUNCTION: OnClose(HWND)
    //
    //   PURPOSE: Process the WM_CLOSE message.
    //
    void OnClose(HWND hWnd)
    {
        EndDialog(hWnd, 0);
    }


    //
    //  FUNCTION: DialogProc(HWND, UINT, WPARAM, LPARAM)
    //
    //  PURPOSE:  Processes messages for the main dialog.
    //
    INT_PTR CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
            // Handle the WM_INITDIALOG message in OnInitDialog
            HANDLE_MSG (hWnd, WM_INITDIALOG, OnInitDialog);

            // Handle the WM_COMMAND message in OnCommand
            HANDLE_MSG (hWnd, WM_COMMAND, OnCommand);

            // Handle the WM_CLOSE message in OnClose
            HANDLE_MSG (hWnd, WM_CLOSE, OnClose);

        default:
            return FALSE;
        }
        return 0;
    }


    //
    //  FUNCTION: wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
    //
    //  PURPOSE:  The entry point of the application.
    //
    int APIENTRY wWinMain(HINSTANCE hInstance,
                          HINSTANCE hPrevInstance,
                          LPWSTR    lpCmdLine,
                          int       nCmdShow)
    {
        return DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAINDIALOG), NULL, DialogProc);
    }

  • 相关阅读:
    问题 A: C#抽象类Vehicles
    最短路练习
    BFS
    poj 1083 Moving Tables
    组合数
    hdu 1443 Joseph【约瑟夫环】
    poj 2449 Remmarguts' Date【第K短路】
    hdu 1695 GCD 【莫比乌斯函数】
    hdu 2178 猜数字
    bzoj 2440 完全平方数 【莫比乌斯函数】
  • 原文地址:https://www.cnblogs.com/lzjsky/p/1893694.html
Copyright © 2011-2022 走看看