Article

From:
To:
All
Subject:
Impersonate user from service: SetTokenInformation err 998 "Invalidaccess
Newsgroup:
embarcadero.public.delphi.nativeapi

Impersonate user from service: SetTokenInformation err 998 "Invalidaccess

I want to set a HKCU registry setting from my service app; I know a Windows user is logged on at that moment. I used the sample code at http://www.delphifaq.com/faq/delphi_windows_API/f663.shtml to impersonate the logged on user. I get error 998 "Invalid access to memory location" at the call to SetTokenInformation
I failed to contact the original author.

The original call to DuplicateTokenEx used params SecurityIdentification and TokenPrimary, I also tried SecurityImpersonation and TokenImpersonation (see code)
Testing under XP Prof

What could be going wrong? One hint maybe: hUserToken is retrieved in WTSQueryUserToken, but never used??
Below is the code; Write2Log is my own debugging stuff (all values reported look fine); GLE=GetlastError description

Thanks in advance
Jan


function xbwImpersonateLoggedOnUser: Boolean; var   winlogonPid,   dwSessionId: DWord;   hUserToken,   hPToken,   hProcess : THANDLE;   tp : TOKEN_PRIVILEGES;   bError : Boolean;   strClone : String; begin
{ Start process as elevated by cloning existing process, as we're running as admin... }
  Result := True;
  bError := False;
  if not InitProcLibs then begin
    Write2Log(xbwImpersonateLoggedOnUser InitProcLibs failed');
    Exit;
    end;
  // Get explorer.exe process ID:
  strClone := 'explorer.exe';
  winlogonPid := xbwGetProcessID(strClone);
  Write2Log('winLogonPiD: ' + inttostr(winlogonpid));
  try
    // Get user token for winlogon:
    dwSessionId := WTSGetActiveConsoleSessionId;
    Write2Log('dwSessionId: ' + inttostr(dwSessionId));
// Get the primary access token of the logged-on user specified by the session ID
    if not WTSQueryUserToken(dwSessionId, hUserToken) then
      begin
      Write2Log('WTSQueryUserToken error: ' + GLE);
      bError := True;
      end;
    Write2Log('hUserToken: ' + inttostr(hUserToken));

    // Open the existing local process object identified by winlogonPid     hProcess := OpenProcess(MAXIMUM_ALLOWED, FALSE, winlogonPid);     Write2Log('hProcess: ' + inttostr(hProcess));
// Open the access token associated with the process, result is put in hPToken if (not OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY or TOKEN_DUPLICATE or TOKEN_ASSIGN_PRIMARY or TOKEN_ADJUST_SESSIONID or TOKEN_READ or TOKEN_WRITE, hPToken)) then
      begin
      Write2Log('OpenProcessToken error: ' + GLE);
      bError := True;
      end;
// Retrieve the locally unique identifier (LUID) used on a specified system to locally represent the specified privilege name.
    // Put it in the TOKEN_PRIVILEGES structure tp
if (not LookupPrivilegeValue(nil, SE_DEBUG_NAME, tp.Privileges[0].Luid)) then
      begin
      Write2Log('LookupPrivilegeValue error: ' + GLE);
      bError := True;
      end;
    // Set other tp params:
    tp.PrivilegeCount := 1;
    tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
// Create a new access token FhUserTokenDup that duplicates the existing token hPToken
    if not DuplicateTokenEx(hPToken,
MAXIMUM_ALLOWED, // Request all access rights that are valid for the caller Nil, // Token gets a default security descriptor // SecurityIdentification, // Value from the SECURITY_IMPERSONATION_LEVEL enumeration that indicates the impersonation level of the new token SecurityImpersonation, // Value from the SECURITY_IMPERSONATION_LEVEL enumeration that indicates the impersonation level of the new token // http://msdn.microsoft.com/en-us/library/aa379572(VS.85).aspx // TokenPrimary, // Value from the TOKEN_TYPE enumeration TokenImpersonation, // Value from the TOKEN_TYPE enumeration
                            FhUserTokenDup) then
      begin
      Write2Log('DuplicateTokenEx error: ' + GLE);
      bError := True;
      end;
// Overwrite information for the FhUserTokenDup token (Adjust token privilege):
    if not SetTokenInformation(FhUserTokenDup,
TokenSessionId, // TOKEN_INFORMATION_CLASS enumeration type contains values that specify the type of information being assigned // TokenSessionId = You will receive a DWORD value that indicates the Terminal Services session identifier that is associated with the token
                               pointer(dwSessionId),                                sizeof(DWORD)) then
      begin
      { ERROR 998 Invalid access to memory location. }
      Write2Log('SetTokenInformation error: ' + GLE);
      bError := True;
      end;
// Now adjust the priviliges of the duplicated token with the settings in tp: if (not AdjustTokenPrivileges(FhUserTokenDup, FALSE, @tp, sizeof(TOKEN_PRIVILEGES), nil, nil)) then
      begin
      Write2Log('AdjustTokenPrivileges error: ' + GLE);
      bError := True;
      end;
    if (GetLastError() = ERROR_NOT_ALL_ASSIGNED) then begin
      Write2Log('xbwImpersonateLoggedOnUser error ERROR_NOT_ALL_ASSIGNED');
      bError := True;
      end;
    // Finally, do the impersonation:
    if not ImpersonateLoggedOnUser(FhUserTokenDup) then
      begin
      Write2Log('ImpersonateLoggedOnUser error: ' + GLE);
      bError := True;
      end;

    { perform all the close handles tasks... }     try       CloseHandle(hProcess);       CloseHandle(hUserToken);
// CloseHandle(FhUserTokenDup); { This is closed later in xbwRevertToSelf }
      CloseHandle(hPToken);
    except
      on E:Exception do
        Write2Log('xbwImpersonateLoggedOnUser error (1): ' + E.Message);
    end;
  except
    on E:Exception do begin
      Write2Log('xbwImpersonateLoggedOnUser error (2): ' + E.Message);
      bError := True;
    end;
  end;
  Result := not bError;
end; { xbwImpersonateLoggedOnUser }
FYI: Quoted text in a message is not indexed
 
 
Originally created by
Tamarack Associates
Mon, 20 May 2024 00:36:04 UTC
Copyright © 2009-2024
HREF Tools Corp.