Re: LogonUser / CreateProcessAsUser - Behaves differently from different calling applications
From: Richard Ward (richardw_at_delete-yellow-dogs.com)
Date: 05/05/04
- Next message: Carl Daniel [VC++ MVP]: "Re: Consumption of CPU cycles by GetMessage"
- Previous message: Richard Ward: "Re: SetThreadDesktop fails even if I try to associate it with current desktop"
- Messages sorted by: [ date ] [ thread ]
Date: Wed, 5 May 2004 02:05:12 -0700
Since you're not supplying a lpDesktop field in the startup info,
the new process will be in a non-interactive desktop and session.
Different runtimes may handle that differently.
"Colin" <anonymous@discussions.microsoft.com> wrote in message
news:B24EAA42-526F-4B9C-BB6A-3807618DD887@microsoft.com...
>I have written a small win32 DLL that will switch the user context for an
>application and execute a simple command. I accomplish this using
>LogonUser, ImpersonateLoggedOnUser, and DuplicateTokenEx and then call
>CreateProcessAsUser to execute the command.
>
> I am experiencing some odd behaviour. Calling the DLL from another win32
> console application compiled under visual studio and the DLL works fine
> and executes the command as the new user. However, if I call the DLL from
> a win32 console application compiled using Watcom C++ (an old compiler
> originally meant for WINNT 4.0) I get a security violation "Access Is
> Denied" when I try to execute the command. However, if use the
> administrator account as the new user, it executes fine.
>
> I have tried giving my test user the exact same priveliges as the
> administrator in the local policy settings but I still get the access
> denied violation.
>
> Why do two applications using the same DLL behave differently just because
> they are compiled under different compilers'
>
> p.s. I have to get this working using watcom as our products are legacy
> products and use the watcom compiler for now.
>
> The code for the DLL is below:
>
>
> /*------------------- OBJECT DEFINITIONS -------------------*/
>
> /*
> * This object maintains data for the Authentication and Process
> * control methods in this DLL library.
> */
> typedef struct _ProcessState
> {
> DWORD dwExitCode; // Exit code of the last executed process
> command
> } ProcessState;
>
>
> /*------------------- PROTOTYPES -------------------*/
> void reportError();
> LPVOID appendToEnvironmentBlock( LPSTR asExtraVars[] );
> BOOL freeEnvironmentBlock( LPVOID pLocalEnv );
>
>
>
> /*------------------- MEMBERS -------------------*/
>
> static ProcessState mProcessState; // state object for
> Authentication & Process control functions
>
>
>
>
> /**
> * Main entry point for DLL. Initialization and Destruction
> * code should be inserted here.
> *
> * @param hModule DLL Handle
> * @param ul_reason_for_call
> * Reason for call e.g. Init, Unload, etc
> * @param lpReserved Reserver
> *
> * @return True on success
> */
> BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID
> lpReserved )
> {
>
> switch ( ul_reason_for_call )
> {
> case DLL_PROCESS_ATTACH:
> memset( &mProcessState, 0, sizeof( mProcessState ) );
> break;
> case DLL_THREAD_ATTACH:
> break;
> case DLL_THREAD_DETACH:
> break;
> case DLL_PROCESS_DETACH:
> break;
> }
>
> return (TRUE);
> }
>
>
>
> /**
> * Authenticate a user using the provided credentials. If authentication
> * is successful. Switch the current process credentials and
> * impersonate the user. This is used to apply user domain security
> * for a remote service. Return a system handle the caller can use
> * in other calls to win32 that require a user context token.
> *
> * @param sUser user name
> * @param sPassword user password (Clear Text)
> * @param sDomain Domain to authenticate against
> *
> * @return Non null on success
> * Null if the authentication failed. If null is returned, the
> * caller should call GetLastError() to find the specific error
> * which occurred.
> */
> HANDLE _stdcall switchUser( LPCSTR sUser, LPCSTR sPassword, LPCSTR
> sDomain )
> {
> HANDLE hLogonToken, hImpersonationToken;
> BOOL bSuccess;
>
> /*----------------------*/
>
> try
> {
>
> hLogonToken = 0;
> bSuccess = LogonUser( sUser, sDomain, sPassword,
> LOGON32_LOGON_NETWORK_CLEARTEXT,
> LOGON32_PROVIDER_WINNT50, &hLogonToken );
>
> if ( !bSuccess )
> throw "Logon User failed\n";
>
> bSuccess = ImpersonateLoggedOnUser( hLogonToken );
>
> if ( !bSuccess )
> throw "Impersonation failed\n";
>
> bSuccess = DuplicateTokenEx( hLogonToken, MAXIMUM_ALLOWED, 0,
> SecurityImpersonation, TokenPrimary, &hImpersonationToken );
>
> if ( !bSuccess )
> throw "Duplicate token failed\n";
>
> }
> catch ( char * sErr )
> {
> std::cout << sErr;
> reportError();
> }
>
> return (hImpersonationToken);
>
> }
>
>
> /**
> * Execute a command in it's own thread. This call is blocking while
> * the command executes. This function requires a handle to the current
> * authentication token to spawn the thread in the same user context.
> * This is useful for remote services providing domain security access,
> * the thread is spawned as the user with their security access.
> *
> * @param hUserToken Handle for a user token
> * @param sCommandLine
> * command line to execute e.g. "cmd.exe /C dir >
> dir.txt"
> * @param asExtraEnvironmentVars
> * Array of string pointers to custom environment
> variables.
> * These variable will be appended to the current
> environment
> * for the executing child process.
> * @param iTimeOut integer time out value in milliseconds. Time to wait
> for
> * command to complete
> *
> * @return True on success
> * False if the process can not be successfully spawned. Callers
> * should call GetLastError to find the precise error if the
> function
> * fails.
> *
> * If the function succeeds, it does not mean the command was
> successful,
> * only that the thread was spawned and the command ran to
> completion
> * To get the exit code of the command, call getCommandExitCode().
> This
> * will return the exit code of the last executed command.
> */
> BOOL _stdcall execCommand( HANDLE hUserToken, LPCSTR sCommandLine, LPSTR
> asExtraEnvironmentVars[], INT iTimeOut )
> {
> BOOL bSuccess;
> DWORD dwStatus, dwExitCode;
> LPVOID sUserEnv;
>
> STARTUPINFO startupInfo;
> PROCESS_INFORMATION processInfo;
>
> /*----------------------*/
>
> try
> {
> memset( &startupInfo, 0, sizeof( startupInfo ) );
> memset( &processInfo, 0, sizeof( processInfo ) );
> sUserEnv = NULL;
>
> if ( asExtraEnvironmentVars != NULL )
> {
> // Create new environment block with local vars added
> sUserEnv = appendToEnvironmentBlock( asExtraEnvironmentVars );
> }
>
> bSuccess = CreateProcessAsUser( hUserToken, 0, (LPSTR )sCommandLine,
> 0, 0, 0, 0, sUserEnv, 0, &startupInfo, &processInfo );
>
> if ( !bSuccess )
> throw "CreateProcessAsUser failed\n";
>
>
> CloseHandle( processInfo.hThread ); // close pipe handle -
> child's instance
> dwStatus = WaitForSingleObject( processInfo.hProcess, iTimeOut );
> std::cout << "WaitForSingleObject rc = " << dwStatus << endl;
>
> switch ( dwStatus )
> {
> case WAIT_ABANDONED:
> std::cout << "Wait abandoned" << endl;
> break;
>
> case WAIT_OBJECT_0:
> std::cout << "Object signaled" << endl;
> break;
>
> case WAIT_TIMEOUT:
> std::cout << "Timeout" << endl;
> break;
>
> default:
> std::cout << "Unknown result" << endl;
> break;
> }
>
> bSuccess = GetExitCodeProcess( processInfo.hProcess, &dwExitCode );
> CloseHandle( processInfo.hProcess ); // close process handle or
> it won't die
>
> if ( !bSuccess )
> throw "Get exit code failed\n";
>
> std::cout << "Exit Code: " << dwExitCode << endl;
>
> mProcessState.dwExitCode = dwExitCode;
> return bSuccess;
> }
> catch ( char * sErr )
> {
> std::cout << sErr;
> reportError();
> mProcessState.dwExitCode = -1;
> return false;
> }
> }
>
>
> /**
> * Get the exit code of the last command executed using one
> * of the process control commands (e.g. execCommand() )
> *
> * @return DWORD value of the exit code
> */
> DWORD _stdcall getCommandExitCode()
> {
> return mProcessState.dwExitCode;
> }
>
>
>
- Next message: Carl Daniel [VC++ MVP]: "Re: Consumption of CPU cycles by GetMessage"
- Previous message: Richard Ward: "Re: SetThreadDesktop fails even if I try to associate it with current desktop"
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|