In my sample i'm trying to launch calc.exe, and in vista it works
well, problem appears only with the Windows XP.
Anyone else seen a similar issue, or know why this is happening? If it
helps, i can upload a sample to reproduce this behavior...
Thanks.
--
Andrew Solodovnikov
Hi there,
same problem for me, do you have any solution right now?
Greetings
(Sorry for my previous post)
I've debugged a little bit with the kernel debugger, and have found the
problem: CreateProcessAsUser uses internally, when creating a process in an
other session, the function CreateRemoteProcessW from ADVAPI32.DLL. This
function opens a pipe with the name
\\.\Pipe\TerminalServer\SystemExecSrvr\%d where %d is the SessionID and
sending the request over to csrss.exe. And now the problem. After logging off
from a session other than 0 csrss.exe does not create this pipe or
CreateRemoteProcessW is not able to read the pipe. CreateRemoteProcessW is
able to open the pipe and write to it. Is here anyone from MS listening and
can tell me what to do to get CreateProcessAsUser to work?
Thanks in advance
Thomas Graefenhain
Known Issues:
1.Only WinXP can use the function, Vista MUST not use
2.Session 0 can't use the function, consider service always run in
session 0, this problem is not a problem.
3.When u failed with 2 (ERROR_FILE_NOT_FOUND) then u should wait a
moment and try again, I consider this is WinXP bug:),
4.When second parameter is TRUE, then hToken won't be used to create
new process. If u call CreateProcessAsUser and failed with 233, then u
should set second parameter to TRUE
typedef BOOLEAN (WINAPI* pWinStationQueryInformationW)(
IN HANDLE hServer,
IN ULONG LogonId,
IN DWORD /*WINSTATIONINFOCLASS*/ WinStationInformationClass,
OUT PVOID pWinStationInformation,
IN ULONG WinStationInformationLength,
OUT PULONG pReturnLength
);
DWORD MarshallString(LPCWSTR pszText, LPVOID, DWORD dwMaxSize,LPBYTE*
ppNextBuf, DWORD* pdwUsedBytes)
{
DWORD dwOffset = *pdwUsedBytes;
if(!pszText)
return 0;
DWORD dwLen = (wcslen(pszText)+1)*sizeof(WCHAR);
if(*pdwUsedBytes + dwLen> dwMaxSize)
return 0;
memmove(*ppNextBuf, pszText , dwLen);
*pdwUsedBytes += dwLen;
*ppNextBuf += dwLen;
return dwOffset;
}
typedef struct _CPAU_PARAM{
DWORD cbSize;
DWORD dwProcessId;
BOOL bUseDefaultToken;
HANDLE hToken;
LPWSTR lpApplicationName;
LPWSTR lpCommandLine;
SECURITY_ATTRIBUTES ProcessAttributes;
SECURITY_ATTRIBUTES ThreadAttributes;
BOOL bInheritHandles;
DWORD dwCreationFlags;
LPVOID lpEnvironment;
LPWSTR lpCurrentDirectory;
STARTUPINFOW StartupInfo;
PROCESS_INFORMATION ProcessInformation;
}CPAU_PARAM;
typedef struct _CPAU_RET_PARAM{
DWORD cbSize;
BOOL bRetValue;
DWORD dwLastErr;
PROCESS_INFORMATION ProcInfo;
}CPAU_RET_PARAM;
BOOL CreateRemoteSessionProcessW(
IN DWORD dwSessionId,
IN BOOL bUseDefaultToken,
IN HANDLE hToken,
IN LPCWSTR lpApplicationName,
IN LPWSTR lpCommandLine,
IN LPSECURITY_ATTRIBUTES lpProcessAttributes,
IN LPSECURITY_ATTRIBUTES lpThreadAttributes,
IN BOOL bInheritHandles,
IN DWORD dwCreationFlags,
IN LPVOID lpEnvironment,
IN LPCWSTR lpCurrentDirectory,
IN LPSTARTUPINFOW lpStartupInfo,
OUT LPPROCESS_INFORMATION lpProcessInformation)
{
WCHAR szWinStaPath[MAX_PATH];
BOOL bGetNPName=FALSE;
WCHAR szNamedPipeName[MAX_PATH]=L"";
DWORD dwNameLen;
HINSTANCE hInstWinSta;
HANDLE hNamedPipe;
LPVOID pData=NULL;
BOOL bRet = FALSE;
DWORD cbReadBytes,cbWriteBytes;
DWORD dwEnvLen = 0;
union{
CPAU_PARAM cpauData;
BYTE bDump[0x2000];
};
CPAU_RET_PARAM cpauRetData;
DWORD dwUsedBytes = sizeof(cpauData);
LPBYTE pBuffer = (LPBYTE)(&cpauData+1);
GetSystemDirectoryW(szWinStaPath, MAX_PATH);
lstrcatW(szWinStaPath,L"\\winsta.dll");
hInstWinSta = LoadLibrary(szWinStaPath);
if(hInstWinSta)
{
pWinStationQueryInformationW
pfWinStationQueryInformationW=(pWinStationQueryInformationW)GetProcAddress(hInstWinSta,
"WinStationQueryInformationW");
if(pfWinStationQueryInformationW)
{
bGetNPName = pfWinStationQueryInformationW(0, dwSessionId, 0x21,
szNamedPipeName, sizeof(szNamedPipeName), &dwNameLen);
}
FreeLibrary(hInstWinSta);
}
if(!bGetNPName || szNamedPipeName[0] == '\0')
{
swprintf(szNamedPipeName, L"\\\\.\\Pipe\\TerminalServer\
\SystemExecSrvr\\%d", dwSessionId);
}
do{
hNamedPipe = CreateFile(szNamedPipeName, GENERIC_READ|GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, 0);
if(hNamedPipe == INVALID_HANDLE_VALUE)
{
if(GetLastError() == ERROR_PIPE_BUSY)
{
if(!WaitNamedPipe(szNamedPipeName, 30000))
return FALSE;
}
else
{
return FALSE;
}
}
}while(hNamedPipe == INVALID_HANDLE_VALUE);
memset(&cpauData, 0, sizeof(cpauData));
cpauData.bInheritHandles = bInheritHandles;
cpauData.bUseDefaultToken = bUseDefaultToken;
cpauData.dwCreationFlags = dwCreationFlags;
cpauData.dwProcessId = GetCurrentProcessId();
cpauData.hToken = hToken;
cpauData.lpApplicationName =
(LPWSTR)MarshallString(lpApplicationName, &cpauData, sizeof(bDump),
&pBuffer, &dwUsedBytes);
cpauData.lpCommandLine = (LPWSTR)MarshallString(lpCommandLine,
&cpauData, sizeof(bDump), &pBuffer, &dwUsedBytes);
cpauData.StartupInfo = *lpStartupInfo;
cpauData.StartupInfo.lpDesktop =
(LPWSTR)MarshallString(cpauData.StartupInfo.lpDesktop, &cpauData,
sizeof(bDump), &pBuffer, &dwUsedBytes);
cpauData.StartupInfo.lpTitle =
(LPWSTR)MarshallString(cpauData.StartupInfo.lpTitle, &cpauData,
sizeof(bDump), &pBuffer, &dwUsedBytes);
if(lpEnvironment)
{
if(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)
{
while((dwEnvLen+dwUsedBytes <= sizeof(bDump)))
{
if(((LPWSTR)lpEnvironment)[dwEnvLen/2]=='\0' &&
((LPWSTR)lpEnvironment)[dwEnvLen/2+1] == '\0')
{
dwEnvLen+=2*sizeof(WCHAR);
break;
}
dwEnvLen+=sizeof(WCHAR);
}
}
else
{
while(dwEnvLen+dwUsedBytes <= sizeof(bDump))
{
if(((LPSTR)lpEnvironment)[dwEnvLen]=='\0' && ((LPSTR)lpEnvironment)
[dwEnvLen+1]=='\0')
{
dwEnvLen+=2;
break;
}
dwEnvLen++;
}
}
if(dwEnvLen+dwUsedBytes <= sizeof(bDump))
{
memmove(pBuffer, lpEnvironment, dwEnvLen);
cpauData.lpEnvironment = (LPVOID)dwUsedBytes;
pBuffer += dwEnvLen;
dwUsedBytes += dwEnvLen;
}
else
{
cpauData.lpEnvironment = NULL;
}
}
else
{
cpauData.lpEnvironment = NULL;
}
cpauData.cbSize = dwUsedBytes;
if(WriteFile(hNamedPipe, &cpauData, cpauData.cbSize, &cbWriteBytes,
NULL) &&
ReadFile(hNamedPipe, & cpauRetData, sizeof(cpauRetData),
&cbReadBytes, NULL))
{
bRet = cpauRetData.bRetValue;
if(bRet)
{
*lpProcessInformation = cpauRetData.ProcInfo;
}
else
SetLastError(cpauRetData.dwLastErr);
}
else
bRet = FALSE;
CloseHandle(hNamedPipe);
return bRet;
}
On 11月2日, 下午8时19分, Thomas Graefenhain