Why CreateProcessAsUser fail on Vista?
Following is the code segment
if ( !CreateProcessAsUser(
hToken,// obtained from LogonUser
NULL,
( char * )pszCmd,
NULL,
NULL,
FALSE,
dwCreationFlag,
pEnv,//obtained from CreateEnvironmentBlock
NULL,
&si,
&pi
) )
{
//error;
}
GetLastError gives error code 183
[363 byte] By [
Ganeshm] at [2007-12-22]
BOOL StartSDProcess(CString csProcessPath, CString csCommandLineParam)
{
// WritePrivateProfileString("Info","10","start >> " + csProcessPath,CSystemInfo::m_strAppPath + "info.ini");
OutputDebugString("Start SD Process");
HANDLE hToken = NULL;
TOKEN_USER oUser[16];
DWORD u32Needed;
TCHAR sUserName[256], domainName[256];
DWORD userNameSize, domainNameSize;
SID_NAME_USE sidType;
ZeroMemory(oUser,sizeof(oUser));
OpenProcessToken(GetExplorerProcessHandle(), TOKEN_ALL_ACCESS, &hToken);
OutputDebugString("get exp token");
if(hToken == NULL)
return FALSE;
GetTokenInformation(hToken,TokenUser,&oUser[0], sizeof(oUser), &u32Needed);
userNameSize = sizeof (sUserName) - 1;
domainNameSize = sizeof (domainName) - 1;
LookupAccountSid (NULL, oUser[0].User.Sid, sUserName, &userNameSize, domainName, &domainNameSize, &sidType);
HDESK hdesk = NULL;
HWINSTA hwinsta = NULL, hwinstaSave = NULL;
PROCESS_INFORMATION pi;
PSID pSid = NULL;
STARTUPINFO si;
BOOL bResult = FALSE;
CString csErr;
OutputDebugString("GetProcessWindowStation");
// Save a handle to the caller's current window station.
if ( (hwinstaSave = GetProcessWindowStation() ) == NULL)
{
CloseHandle(hToken);
return FALSE;
}
// Get a handle to the interactive window station.
hwinsta = OpenWindowStation(
"winsta0", // the interactive window station
FALSE, // handle is not inheritable
READ_CONTROL | WRITE_DAC); // rights to read/write the DACL
OutputDebugString("OpenWindowStation");
if (hwinsta == NULL)
{
SetProcessWindowStation (hwinstaSave);
CloseHandle(hToken);
return FALSE;
}
// To get the correct default desktop, set the caller's
// window station to the interactive window station.
OutputDebugString("SetProcessWindowStation");
if (!SetProcessWindowStation(hwinsta))
{
SetProcessWindowStation (hwinstaSave);
CloseWindowStation(hwinsta);
CloseHandle(hToken);
return FALSE;
}
// Get a handle to the interactive desktop.
hdesk = OpenDesktop(
"default", // the interactive window station
0, // no interaction with other desktop processes
FALSE, // handle is not inheritable
READ_CONTROL | // request the rights to read and write the DACL
WRITE_DAC |
DESKTOP_WRITEOBJECTS |
DESKTOP_READOBJECTS);
OutputDebugString("OpenDesktop");
if (hdesk == NULL)
{
SetProcessWindowStation (hwinstaSave);
CloseWindowStation(hwinsta);
CloseHandle(hToken);
return FALSE;
}
OutputDebugString("SetProcessWindowStation");
// Restore the caller's window station.
if (!SetProcessWindowStation(hwinstaSave))
{
SetProcessWindowStation (hwinstaSave);
CloseWindowStation(hwinsta);
CloseDesktop(hdesk);
CloseHandle(hToken);
return FALSE;
}
// Impersonate client to ensure access to executable file.
OutputDebugString("ImpersonateLoggedOnUser");
if (! ImpersonateLoggedOnUser(hToken) )
{
SetProcessWindowStation (hwinstaSave);
CloseWindowStation(hwinsta);
CloseDesktop(hdesk);
CloseHandle(hToken);
return FALSE;
}
// Initialize the STARTUPINFO structure.
// Specify that the process runs in the interactive desktop.
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb= sizeof(STARTUPINFO);
si.lpDesktop = TEXT("winsta0\\default");
char csCmdParam[MAX_PATH];
DWORD dwSize = MAX_PATH;
strcpy(csCmdParam, csCommandLineParam);
OutputDebugString("CreateProcessAsUser");
bResult = CreateProcessAsUser(
hToken, // client's access token
csProcessPath, // file to execute
csCmdParam, // command line
NULL, // pointer to process SECURITY_ATTRIBUTES
NULL, // pointer to thread SECURITY_ATTRIBUTES
FALSE, // handles are not inheritable
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE, // creation flags
NULL, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&pi // receives information about new process
);
if(!bResult)
{
DWORD dw = GetLastError();
CString csStr;
csStr.Format("CreateProcessAsUser failed %d",dw);
OutputDebugString(csStr);
}
SetProcessWindowStation (hwinstaSave);
CloseWindowStation(hwinsta);
CloseDesktop(hdesk);
CloseHandle(hToken);
// End impersonation of client.
RevertToSelf();
return bResult ;
}
I have code that launches my application from a service that works on XP SP2. I have a call to NetUserGetInfo(NULL,username,4, (LPBYTE*) &userInfo4) and then LoadUserProfile.
My problem is that userInfo4.usri4_profile is NULL, as are all the fields except usri4_name.
Is there some other way that I can LoadUserProfile?
My full code is as follows:
DWORD sessionId = WTSGetActiveConsoleSessionId();
HANDLE hToken;
if (!WTSQueryUserToken(sessionId, &hToken))
{
// need Query Information permission
ReportError(_T("WTSQueryUserToken failed"));
return;
}
LPVOID environment = NULL;
if (!CreateEnvironmentBlock (&environment, hToken, FALSE))
{
ReportError(_T("Unable to CreateEnvironmentBlock."));
return;
}
LPTSTR username;
DWORD size = 0;
if (!WTSQuerySessionInformation (WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, &username, &size))
{
ReportError(_T("Unable to WTSQuerySessionInformation."));
return;
}
USER_INFO_4 userInfo4;
ZeroMemory (&userInfo4, sizeof (userInfo4));
if (NERR_Success != NetUserGetInfo (NULL, username, 4, (LPBYTE*) &userInfo4))
{
ReportError (_T("NetUserGetInfo failed"));
return;
}
else if (userInfo4.usri4_profile == NULL)
{
WriteToLog (_T("NetUserGetInfo failed to get usri4_profile"));
return;
}
PROFILEINFO profileInfo;
memset (&profileInfo, 0 , sizeof(profileInfo));
profileInfo.dwSize = sizeof(profileInfo);
profileInfo.lpUserName = username;
profileInfo.lpProfilePath = userInfo4.usri4_profile; // <- this is NULL under Vista (RTM)
if (!LoadUserProfile (hToken, &profileInfo))
{
ReportError(_T("Unable to LoadUserProfile."));
return;
}
WTSFreeMemory (username);
if ( !::CreateProcessAsUser(
hToken,
NULL, // program
controlCenterPath, // command line
NULL, // process handle not inheritable
NULL, // thread handle not inheritable
FALSE, // set handle inheritance to false
CREATE_UNICODE_ENVIRONMENT, // creation flags
environment, // environment block
NULL, // use parent's starting directory
&si, // address to startup info
&pi)) // address to process information
{
ReportError(_T("Unable to launch Control Center as user."));
WriteToLog(controlCenterPath);
}
UnloadUserProfile (hToken, profileInfo.hProfile);
if (environment != NULL)
DestroyEnvironmentBlock (environment);
NetApiBufferFree (&userInfo4);
CloseHandle (hToken);