ImpersonateLoggedOnUser function
Applies to: desktop apps only
The ImpersonateLoggedOnUser function lets the calling thread impersonate the security context of a logged-on user. The user is represented by a token handle.
Syntax
BOOL WINAPI ImpersonateLoggedOnUser( __in HANDLE hToken );
Parameters
- hToken [in]
-
A handle to a primary or impersonation access token that represents a logged-on user. This can be a token handle returned by a call to LogonUser, CreateRestrictedToken, DuplicateToken, DuplicateTokenEx, OpenProcessToken, or OpenThreadToken functions. If hToken is a handle to a primary token, the token must have TOKEN_QUERY and TOKEN_DUPLICATE access. If hToken is a handle to an impersonation token, the token must have TOKEN_QUERY and TOKEN_IMPERSONATE access.
Return value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.
Remarks
The impersonation lasts until the thread exits or until it calls RevertToSelf.
The calling thread does not need to have any particular privileges to call ImpersonateLoggedOnUser.
If the call to ImpersonateLoggedOnUser fails, the client connection is not impersonated and the client request is made in the security context of the process. If the process is running as a highly privileged account, such as LocalSystem, or as a member of an administrative group, the user may be able to perform actions they would otherwise be disallowed. Therefore, it is important to always check the return value of the call, and if it fails, raise an error; do not continue execution of the client request.
All impersonate functions, including ImpersonateLoggedOnUser allow the requested impersonation if one of the following is true:
- The requested impersonation level of the token is less than SecurityImpersonation, such as SecurityIdentification or SecurityAnonymous.
- The caller has the SeImpersonatePrivilege privilege.
- A process (or another process in the caller's logon session) created the token using explicit credentials through LogonUser or LsaLogonUser function.
- The authenticated identity is same as the caller.
Windows XP with SP1 and earlier: The SeImpersonatePrivilege privilege is not supported.
For more information about impersonation, see Client Impersonation.
Requirements
|
Minimum supported client | Windows XP |
|---|---|
|
Minimum supported server | Windows Server 2003 |
|
Header |
|
|
Library |
|
|
DLL |
|
See also
- Client/Server Access Control Overview
- Client/Server Access Control Functions
- CreateProcessAsUser
- CreateRestrictedToken
- DuplicateToken
- DuplicateTokenEx
- LogonUser
- OpenProcessToken
- OpenThreadToken
- RevertToSelf
Send comments about this topic to Microsoft
Build date: 3/7/2012
Yeah I got this stuff working. There's no need for any impersonation code inside the application's before opening the CFileDIalog. The impersonation code must be inside my Print Monitor DLL. And before launching my application EXE, the CreateEnvironmentBlock() must done properly so that the environment for the process that is going to be created is set correctly.
Here is the source that worked for me. The sample below shows the Notepad application being launched. The DLL in which I used this code runs under the Print Spooler service - basically it is a Print Monitor. You need to add your own validity checks if you decide to use this - what's listed below is bare-bones.
#include "userenv.h"
// Global Typedefs for function pointers in USERENV.DLL
typedef BOOL (STDMETHODCALLTYPE FAR * LPFNCREATEENVIRONMENTBLOCK) ( LPVOID *lpEnvironment,
HANDLE hToken,
BOOL bInherit );
typedef BOOL (STDMETHODCALLTYPE FAR * LPFNDESTROYENVIRONMENTBLOCK) ( LPVOID lpEnvironment );
void InvokeApp()
{
// Local Variable Declarations
HANDLE hToken = NULL;
HANDLE hTokenDup = NULL;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof( STARTUPINFO ) );
ZeroMemory( &pi, sizeof( PROCESS_INFORMATION ) );
si.cb = sizeof( STARTUPINFO );
si.lpDesktop = _T("Winsta0\\Default");
DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
LPVOID pEnvironment = NULL;
LPFNCREATEENVIRONMENTBLOCK lpfnCreateEnvironmentBlock = NULL;
LPFNDESTROYENVIRONMENTBLOCK lpfnDestroyEnvironmentBlock = NULL;
HMODULE hUserEnvLib = NULL;
hUserEnvLib = LoadLibrary( _T("userenv.dll") );
if ( NULL != hUserEnvLib ) {
lpfnCreateEnvironmentBlock = (LPFNCREATEENVIRONMENTBLOCK)
GetProcAddress( hUserEnvLib, "CreateEnvironmentBlock" );
lpfnDestroyEnvironmentBlock = (LPFNDESTROYENVIRONMENTBLOCK)
GetProcAddress( hUserEnvLib, "DestroyEnvironmentBlock" );
}
OpenThreadToken( GetCurrentThread(), TOKEN_DUPLICATE, TRUE, &hToken );
DuplicateTokenEx( hToken,
TOKEN_IMPERSONATE|TOKEN_READ|TOKEN_ASSIGN_PRIMARY|TOKEN_DUPLICATE,
NULL, SecurityImpersonation, TokenPrimary, &hTokenDup );
RevertToSelf( );
CloseHandle( hToken );
if ( NULL != lpfnCreateEnvironmentBlock ) {
if ( lpfnCreateEnvironmentBlock( &pEnvironment, hTokenDup, FALSE ) ) {
dwCreationFlag |= CREATE_UNICODE_ENVIRONMENT; // must specify
}
else {
pEnvironment = NULL;
OutputDebugString( _T(" CreateEnvironmentBlock() -- FAILED") );
}
}
else {
OutputDebugString(_T(" FAILED - GetProcAddress(CreateEnvironmentBlock)"));
}
CreateProcessAsUser( hTokenDup, NULL, _T("c:\\windows\\notepad.exe"),
NULL, NULL, FALSE, dwCreationFlag,
pEnvironment, NULL, &si, &pi );
if ( NULL != lpfnDestroyEnvironmentBlock )
lpfnDestroyEnvironmentBlock( &pEnvironment );
if ( NULL != hUserEnvLib ) FreeLibrary( hUserEnvLib );
CloseHandle( hTokenDup );
}
What got fixed? The issue I was facing was that the application I wanted my Print Monitor to launch using CreateProcessAsUser() was not getting the logged-on user's environment. The after-effect was that, because of this reason, when my application used to show the File Open common dialog box, it would behave strange while trying to browse to the Desktop in it. This was in Vista.
In Windows XP, the File Open dialog would let you browse to the Desktop folder but the object icons on the Desktop would not appear right in it.
Now it works.
- 4/26/2007
- ddaS-edEn
Security Context - The security attributes or rules that are currently in effect. For example, the current user logged on to the computer or the personal identification number entered by the smart card user. For SSPI, a security context is an opaque data structure that contains security data relevant to a connection, such as a session key or an indication of the duration of the session.
Security Descriptor - A structure and associated data that contains the security information for a securable object. A security descriptor identifies the object's owner and primary group. It can also contain a DACL that controls access to the object, and a SACL that controls the logging of attempts to access the object.
Security Identifier (SID) - A data structure of variable length that identifies user, group, and computer accounts. Every account on a network is issued a unique SID when the account is first created. Internal processes in Windows refer to an account's SID rather than the account's user or group name.
Access Token - An access token contains the security information for a logon session. The system creates an access token when a user logs on, and every process executed on behalf of the user has a copy of the token. The token identifies the user, the user's groups, and the user's privileges. The system uses the token to control access to securable objects and to control the ability of the user to perform various system-related operations on the local computer. There are two kinds of access token, primary and impersonation.
Primary Token - An access token that is typically created only by the Windows kernel. It may be assigned to a process to represent the default security information for that process.
Impersonation Token - An access token that has been created to capture the security information of a client process, allowing a server to "impersonate" the client process in security operations.
Impersonation - A mechanism that allows a server process to run by using the security credentials of the client or some other user using the credentials. When the server is impersonating the client, any operations performed by the server are performed by using the client's (impersonating user's) credentials. Impersonation does not allow the server to access remote resources on behalf of the client. This requires delegation.
- 3/30/2007
- ddaS-edEn