impersonateCurrentUser

 avatar
PaNda
c_cpp
a year ago
4.0 kB
2
Indexable
#pragma once
#include <Windows.h>
#include <WtsApi32.h>
#pragma comment(lib, "Wtsapi32.lib") 
 
  bool getCurrentSessions(vector<DWORD>& vecSessionIds,
                          WTS_CONNECTSTATE_CLASS state = WTSActive) {
    bool rc = false;

    PWTS_SESSION_INFO pSessionInfo = 0;
    DWORD dwCount = 0;

    vecSessionIds.clear();

    // Get the list of all terminal sessions (If the function fails, the return
    // value is zero.)
    if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo,
                              &dwCount))
      return rc;

    // look over obtained list in search of the active session
    for (DWORD i = 0; i < dwCount; ++i) {
      WTS_SESSION_INFO si = pSessionInfo[i];
      if (state == si.State) {
        // If the current session is active � store its ID
        vecSessionIds.push_back(si.SessionId);
      }
    }

    // Free session info
    WTSFreeMemory((PVOID)pSessionInfo);

    rc = true;

    return rc;
  }
  
    bool impersonateCurrentUser() {
    bool rc = false;
    HANDLE hToken = NULL, hCurrentProcess = NULL, hProcessToken = NULL,
           hCurrentToken = NULL;
    vector<DWORD> vecSessionIds;
    BOOL bRet = 0;
    DWORD dwActiveUserSessionId;

    // Get active session(s)
    if (!getCurrentSessions(vecSessionIds)) {
      goto end;
    }

    // Attempt to impersonate a user and start the application until it is
    // successful.
    for (size_t i = 0; i < vecSessionIds.size(); i++) {
      dwActiveUserSessionId = vecSessionIds[i];

      // Get current process
      // GetCurrenProcess() returns a pseudo handle (currently -1) that is
      // interpreted as the current process. For compatibility with future OS's,
      // it's best to call GetCurrentProcess() rather than hard-coding the -1.
      HANDLE hPseudoForCurrentProcess = GetCurrentProcess();

      // Convert pseudo handle to a real process handle
      if (DuplicateHandle(hPseudoForCurrentProcess, hPseudoForCurrentProcess,
                          hPseudoForCurrentProcess, &hCurrentProcess, 0, true,
                          DUPLICATE_SAME_ACCESS) == 0)
        return rc;

      // Get token for current process
      bRet = OpenProcessToken(hCurrentProcess,
                              TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
                              &hProcessToken);
      if (!bRet) goto end;

      // Build privileges we will need (TCB = trusted computer base. Act as part
      // of the operating system).
      TOKEN_PRIVILEGES tokenPrivs;
      bRet = LookupPrivilegeValue(NULL, SE_TCB_NAME,
                                  &tokenPrivs.Privileges[0].Luid);
      if (!bRet) goto end;

      tokenPrivs.PrivilegeCount = 1;
      tokenPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

      // Adjust our privileges for our process
      bRet = AdjustTokenPrivileges(hProcessToken, FALSE, &tokenPrivs, 0,
                                   (PTOKEN_PRIVILEGES)NULL, 0);
      if (!bRet) goto end;

      // Get token of the logged in user by the active session ID
      if (!WTSQueryUserToken(dwActiveUserSessionId, &hCurrentToken)) goto end;

      // Obtain a token for current user finally
      bRet = DuplicateTokenEx(hCurrentToken,
                              TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, 0,
                              SecurityImpersonation, TokenPrimary, &hToken);
      if ((bRet == false) || (hToken == 0)) goto end;

      // Impersonate the user using the user token
      if (ImpersonateLoggedOnUser(hToken)) {
        rc = true;
      }

      // Break out if impersonation was successful
      if (rc) break;
    }  // for loop for session id's

  end:
    if (hProcessToken) CloseHandle(hProcessToken);
    if (hCurrentProcess) CloseHandle(hCurrentProcess);
    if (hCurrentToken) CloseHandle(hCurrentToken);
    if (hToken) CloseHandle(hToken);

    return rc;
  }