Mine was the same senerio, calling CreateProcessAsUser from service.
I followed the steps given by you, and it really worked for me thanks
HANDLE hTokenNew = NULL, hTokenDup = NULL;
HMODULE hmod = LoadLibrary("kernel32.dll");
WTSGETACTIVECONSOLESESSIONID lpfnWTSGetActiveConsoleSessionId = (WTSGETACTIVECONSOLESESSIONID)GetProcAddress(hmod,"WTSGetActiveConsoleSessionId");
DWORD dwSessionId = lpfnWTSGetActiveConsoleSessionId();
WTSQueryUserToken(dwSessionId, &hToken);
DuplicateTokenEx(hTokenNew,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hTokenDup);
//
WriteToLog("Calling lpfnCreateEnvironmentBlock");
ZeroMemory( &si, sizeof( STARTUPINFO ) );
si.cb = sizeof( STARTUPINFO );
si.lpDesktop = "winsta0//default";
LPVOID pEnv = NULL;
DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
HMODULE hModule = LoadLibrary("Userenv.dll");
if(hModule )
{
LPFN_CreateEnvironmentBlock lpfnCreateEnvironmentBlock = (LPFN_CreateEnvironmentBlock)GetProcAddress( hModule, "CreateEnvironmentBlock" );
if( lpfnCreateEnvironmentBlock != NULL )
{
if(lpfnCreateEnvironmentBlock(&pEnv, hTokenDup, FALSE))
{
WriteToLog("CreateEnvironmentBlock Ok");
dwCreationFlag |= CREATE_UNICODE_ENVIRONMENT;
}
else
{
pEnv = NULL;
}
}
}
//
ZeroMemory( &pi,sizeof(pi));
if ( !CreateProcessAsUser(
hTokenDup,
NULL,
( char * )pszCmd,
NULL,
NULL,
FALSE,
dwCreationFlag,
pEnv,
NULL,
&si,
&pi
) )
{
goto RESTORE;
}