Microsoft KB Archive/257193

{|
 * width="100%"|

HOWTO: Start a Process in a Different Terminal Server Session

 * }

Q257193

-

The information in this article applies to:


 * Microsoft Win32 Application Programming Interface (API), used with:
 * the operating system: Microsoft Windows 2000

-

SUMMARY
On Windows 2000 Terminal Server, a process can be started in a remote session by first calling the SetTokenInformation function to associate a process token with the session ID of the remote session. Then, call the CreateProcessAsUserW function to create a process in that session.

MORE INFORMATION
When SetTokenInformation is called with the TokenSessionId class, the caller must have the SE_TCB_NAME ("Act As Part of the Operating System") privilege. Also, this privilege must be enabled. If the caller does not possess the TCB Name privilege or if this privilege is not enabled, SetTokenInformation fails with error code 1314 (ERROR_PRIVILEGE_NOT_HELD).

There is a bug in the CreateProcessAsUserA function, which is the ANSI version of the CreateProcessAsUser function, that causes CreateProcessAsUserA to fail with error code 2 (ERROR_FILE_NOT_FOUND) or 3 (ERROR_PATH_NOT_FOUND). Therefore, you must use CreateProcessAsUserW, which is the Unicode version of the function, to start the process.

Sample Code
The following sample code demonstrates how to launch a process in another session. This command-line utility starts a specified executable file within a specified session under the current user's account. In addition to the SE_TCB_NAME privilege, the caller must have the SE_INCREASE_QUOTA_NAME and SE_ASSIGNPRIMARYTOKEN_NAME privileges, which are required by CreateProcessAsUser. This sample code does not verify that the session ID assigned by the token is valid.

#include 
 * 1) include 

void DisplayError(WCHAR* szAPI) {

LPWSTR szErrorMsg; DWORD dwErrorCode = GetLastError;

// Format the error message. FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER         | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErrorCode,         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR) &szErrorMsg,         0, NULL);

// Display the error message. wprintf(L"%s failed with error %d: %s", szAPI, dwErrorCode,         szErrorMsg);

// Free the buffer allocated by the FormatMessage function. LocalFree(szErrorMsg); }

void wmain(int argc, WCHAR* argv[]) {

DWORD dwSessionId; HANDLE hToken = NULL;

TOKEN_PRIVILEGES   tp; PROCESS_INFORMATION pi; STARTUPINFOW       si;

// Initialize structures. ZeroMemory(&tp, sizeof(tp)); ZeroMemory(&pi, sizeof(pi)); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si);

// Validate the command-line parameters. if (argc != 3) { wprintf(L"Usage: %s  \n"           L"  where  is a path to an executable file\n"            L"  and  indicates the session in which to "            L"run the process\n", argv[0]); return; }

// Convert the second parameter to an integer value. dwSessionId = wcstoul(argv[2], NULL, 10);

__try {

// Retrieve a handle to the process token with the proper access. if (!OpenProcessToken(GetCurrentProcess, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_SESSIONID | TOKEN_ADJUST_DEFAULT | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE, &hToken)) {

DisplayError(L"OpenProcessToken"); __leave; }

// Look up the LUID for the TCB Name privilege. if (!LookupPrivilegeValue(NULL, SE_TCB_NAME, &tp.Privileges[0].Luid)) {

DisplayError(L"LookupPrivilegeValue"); __leave; }

// Enable the TCB Name privilege in the process token. tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, 0)        || GetLastError != ERROR_SUCCESS) {

DisplayError(L"AdjustTokenPrivileges"); __leave; }

// Set the token's session ID. if (!SetTokenInformation(hToken, TokenSessionId, &dwSessionId, sizeof(DWORD))) {

DisplayError(L"SetTokenInformation"); __leave; }

// Start the process with CreateProcessAsUserW. if (!CreateProcessAsUserW(hToken, NULL, argv[1], NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) {

DisplayError(L"CreateProcessAsUserW"); __leave; }

} __finally {

// Close the opened handles. if (hToken) CloseHandle(hToken); if (pi.hProcess) CloseHandle(pi.hProcess); if (pi.hThread) CloseHandle(pi.hThread); } } Additional query words:

Keywords : kbDSupport

Issue type : kbhowto

Technology : kbAudDeveloper kbWin32sSearch kbWin32API