Launching an app under Vista with UAP enabled

Tech Tip: Click here to run a free scan for Windows Errors and optimize PC performance



Is it possible to launch an application from a print component under Windows
Vista while UAP (User Account Protection) is enabled?

We are developing a printer driver, print processor, and language monitor
for XP and Vista. Each component launches an executable at some point (e.g.
the driver launches an app for manual duplexing animations, the print
processor launches and app for previewing the job, the language monitor
launches an app for showing job status.)

The following "execute" function is used to launch an app using the active
user account's security level. It works perfectly under XP, even when Fast
User Switched to a Guest account with limited permissions. However, it
won't work under Windows Vista as long as UAP is enabled.

FYI - Input Parameters:
inCmdLine = the full path name of the app to launch
inOptions.bHideWindow = false
inOptions.bImpersonateActiveUser = true
inOptions.bWaitForStart = true
inOptions.bWaitForFinish = false
inOptions.bShowWaitCursor = false

bool execute(LPCTSTR inCmdLine, ExecuteOptions inOptions)
{
BOOL bSuccess = FALSE;
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInfo;
SECURITY_ATTRIBUTES attribs;
SECURITY_DESCRIPTOR sd;

// Init.
memset(&startupInfo, 0, sizeof(startupInfo));
memset(&processInfo, 0, sizeof(processInfo));
memset(&attribs, 0, sizeof(attribs));
memset(&sd, 0, sizeof(sd));

startupInfo.cb = sizeof(startupInfo);

if (inOptions.bHideWindow)
{
startupInfo.dwFlags = STARTF_USESHOWWINDOW;
startupInfo.wShowWindow = SW_HIDE;
}

// Need a security descriptor with a NULL DACL to allow launching
// applications without running into security problems.
attribs.nLength = sizeof(SECURITY_ATTRIBUTES);
attribs.lpSecurityDescriptor = &sd;
attribs.bInheritHandle = FALSE;

if (InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
{
// Add a NULL DACL to the security descriptor.
if (SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE))
{
// Execute the supplied command line either normally, or
// while impersonating the active user.
if (inOptions.bImpersonateActiveUser)
{
// Impersonate active user, then execute the command line.
SECURITY_IMPERSONATION_LEVEL impersonationLevel =
SecurityImpersonation;
HANDLE hThreadToken = 0;
HANDLE hToken = 0;

BOOL bTmp = ImpersonateSelf(impersonationLevel);
bSuccess = OpenThreadToken(
GetCurrentThread(), // ThreadHandle
TOKEN_ALL_ACCESS, // DesiredAccess
TRUE, // OpenAsSelf
&hThreadToken); // TokenHandle
bTmp = RevertToSelf();

if (bSuccess)
bSuccess = DuplicateTokenEx(
hThreadToken, // hExistingToken
MAXIMUM_ALLOWED, // dwDesiredAccess
&attribs, // lpTokenAttributes
impersonationLevel, //
ImpersonationLevel
TokenPrimary, // TokenType
&hToken); // phNewToken

if (hThreadToken)
CloseHandle(hThreadToken);

if (bSuccess)
bSuccess = CreateProcessAsUser(
hToken, // hToken
0, // lpApplicationName
(LPTSTR) inCmdLine, // lpCommandLine
&attribs, //
lpProcessAttributes
&attribs, //
lpThreadAttributes
FALSE, // bInheritHandles
DETACHED_PROCESS, // dwCreationFlags
0, // lpEnvironment
0, //
lpCurrentDirectory
&startupInfo, // lpStartupInfo
&processInfo); //
lpProcessInformation

if (hToken)
CloseHandle(hToken);
}
else
{
// Execute the command line without any impersonation.
bSuccess = CreateProcess(
0, // lpApplicationName
(LPTSTR) inCmdLine, // lpCommandLine
&attribs, //
lpProcessAttributes
&attribs, //
lpThreadAttributes
FALSE, // bInheritHandles
DETACHED_PROCESS, // dwCreationFlags
0, // lpEnvironment
0, //
lpCurrentDirectory
&startupInfo, // lpStartupInfo
&processInfo); //
lpProcessInformation
}

// If necessary, wait for the process to start/finish.
if (inOptions.bWaitForStart || inOptions.bWaitForFinish)
{
HCURSOR hWaitCursor = ::LoadCursor(NULL,
MAKEINTRESOURCE(IDC_WAIT));
HCURSOR hOldCursor = 0;

if (inOptions.bShowWaitCursor)
hOldCursor = SetCursor(hWaitCursor);

// Wait for the process to start running.
DWORD result = WaitForInputIdle(processInfo.hProcess,
30000);
if (result == WAIT_FAILED)
Sleep(100); // If WaitForInputIdle() fails, this sleep
gives the app a chance to launch.
else if (result == 0 && inOptions.bWaitForFinish)
{
// Wait for the process to terminate.
DWORD exitCode = 0;
MSG msg;

while (GetExitCodeThread(processInfo.hThread, &exitCode)
&& exitCode == STILL_ACTIVE)
{
if (inOptions.bShowWaitCursor)
SetCursor(hWaitCursor); // Restores the wait
cursor.
Sleep(500);

// Pump Window's messages while we wait.
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}

if (inOptions.bShowWaitCursor)
SetCursor(hOldCursor);
}
}
}

// Clean up.
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
return (bSuccess ? true : false);
} // execute

Regards,
Dan


.



Relevant Pages

  • Re: Launching an app under Vista with UAP enabled
    ... prompts the user for permission before running th e app. ... We really need a way to launch an app without user ... The following "execute" function is used to launch an app using the ... bSuccess = OpenThreadToken( ...
    (microsoft.public.development.device.drivers)
  • Re: More Before-The-Fact-Isms II, blocking viruses and spyware through NTFS
    ... > BUILTIN\Administrators Full Control ... > BUILTIN\CREATOR OWNER Special (Full Control except Execute) for Files ... but still can't launch any executables. ...
    (microsoft.public.security)
  • RE: How to prevent Office apps from launching executables
    ... we launch our own shell application at boot instead of Explorer. ... "I noticed that Word and other Office apps will allow a user to execute any ... file type. ...
    (microsoft.public.windowsxp.security_admin)
  • Re: Launch console app and wait for exit.
    ... > function I create a process and launch the executable, ... > 'Spawn Process to execute util and wait for it to finish ... myProcess is nothing there and you were never assigning it. ... is shared so the compiler was letting you run it on a Nothing reference. ...
    (microsoft.public.dotnet.languages.vb)
  • [SLE] Example of rc.local for Suse
    ... I was missing a rc.local in order to launch ... # commands to execute after system has booted (all services are already ...
    (SuSE)