Start the agent in a new window station.
The intent is to avoid a problem on Windows XP. On that OS, sending a "Select All" command to freeze one console window also interrupts any "window activity" (e.g. moving/closing/scrolling/right-clicking/...) on all other console windows. My hope is that putting the console into a special window station will isolate it enough to avoid this problem. I noticed that the problem didn't happen when I ran the TestNetServer as a service, which ran both the TestNetServer and Agent processes with a special window station. Note that even though the Agent runs in a special window station, the shell and its children run in the normal window station.
This commit is contained in:
parent
9f1bdd43ab
commit
b7a9415a58
78
Misc/Win32Test3.cc
Normal file
78
Misc/Win32Test3.cc
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Creates a window station and starts a process under it. The new process
|
||||
* also gets a new console.
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOL success;
|
||||
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.bInheritHandle = TRUE;
|
||||
|
||||
HWINSTA originalStation = GetProcessWindowStation();
|
||||
printf("originalStation == 0x%x\n", originalStation);
|
||||
HWINSTA station = CreateWindowStation(NULL,
|
||||
0,
|
||||
WINSTA_ALL_ACCESS,
|
||||
&sa);
|
||||
printf("station == 0x%x\n", station);
|
||||
if (!SetProcessWindowStation(station))
|
||||
printf("SetWindowStation failed!\n");
|
||||
HDESK desktop = CreateDesktop("Default", NULL, NULL,
|
||||
/*dwFlags=*/0, GENERIC_ALL,
|
||||
&sa);
|
||||
printf("desktop = 0x%x\n", desktop);
|
||||
|
||||
char stationName[256];
|
||||
stationName[0] = '\0';
|
||||
success = GetUserObjectInformation(station, UOI_NAME,
|
||||
stationName, sizeof(stationName),
|
||||
NULL);
|
||||
printf("stationName = [%s]\n", stationName);
|
||||
|
||||
char startupDesktop[256];
|
||||
sprintf(startupDesktop, "%s\\Default", stationName);
|
||||
|
||||
STARTUPINFO sui;
|
||||
PROCESS_INFORMATION pi;
|
||||
memset(&sui, 0, sizeof(sui));
|
||||
memset(&pi, 0, sizeof(pi));
|
||||
sui.cb = sizeof(STARTUPINFO);
|
||||
sui.lpDesktop = startupDesktop;
|
||||
|
||||
// Start a cmd subprocess, and have it start its own cmd subprocess.
|
||||
// Both subprocesses will connect to the same non-interactive window
|
||||
// station.
|
||||
|
||||
const char program[] = "c:\\windows\\system32\\cmd.exe";
|
||||
char cmdline[256];
|
||||
sprintf(cmdline, "%s /c cmd", program);
|
||||
success = CreateProcess(program,
|
||||
cmdline,
|
||||
NULL,
|
||||
NULL,
|
||||
/*bInheritHandles=*/FALSE,
|
||||
/*dwCreationFlags=*/CREATE_NEW_CONSOLE,
|
||||
NULL, NULL,
|
||||
&sui,
|
||||
&pi);
|
||||
|
||||
printf("pid == %d\n", pi.dwProcessId);
|
||||
|
||||
// This sleep is necessary. We must give the child enough time to
|
||||
// connect to the specified window station.
|
||||
Sleep(5000);
|
||||
|
||||
SetProcessWindowStation(originalStation);
|
||||
CloseWindowStation(station);
|
||||
CloseDesktop(desktop);
|
||||
Sleep(5000);
|
||||
|
||||
return 0;
|
||||
}
|
@ -10,11 +10,15 @@
|
||||
#include "AgentMsg.h"
|
||||
|
||||
// TODO: Note that this counter makes AgentClient non-thread-safe.
|
||||
// TODO: So does the various API calls that change the process state.
|
||||
// TODO: (e.g. AttachConsole, FreeConsole)
|
||||
int AgentClient::m_counter = 0;
|
||||
|
||||
AgentClient::AgentClient(int initialCols, int initialRows, QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
BOOL success;
|
||||
|
||||
// Start a named pipe server.
|
||||
QLocalServer *socketServer = new QLocalServer(this);
|
||||
QString serverName =
|
||||
@ -49,13 +53,29 @@ AgentClient::AgentClient(int initialCols, int initialRows, QObject *parent) :
|
||||
|
||||
Trace("Starting Agent: [%s]", agentCmdLine.toStdString().c_str());
|
||||
|
||||
// Get a non-interactive window station for the agent.
|
||||
// TODO: review security w.r.t. windowstation and desktop.
|
||||
HWINSTA originalStation = GetProcessWindowStation();
|
||||
HWINSTA station = CreateWindowStation(NULL, 0, WINSTA_ALL_ACCESS, NULL);
|
||||
success = SetProcessWindowStation(station);
|
||||
Q_ASSERT(success);
|
||||
HDESK desktop = CreateDesktop(L"Default", NULL, NULL, 0, GENERIC_ALL, NULL);
|
||||
Q_ASSERT(originalStation != NULL);
|
||||
Q_ASSERT(station != NULL);
|
||||
Q_ASSERT(desktop != NULL);
|
||||
wchar_t stationNameWStr[256];
|
||||
success = GetUserObjectInformation(station, UOI_NAME,
|
||||
stationNameWStr, sizeof(stationNameWStr),
|
||||
NULL);
|
||||
Q_ASSERT(success);
|
||||
QString stationName = QString::fromWCharArray(stationNameWStr);
|
||||
QString startupDesktop = stationName + "\\Default";
|
||||
|
||||
// Start the agent.
|
||||
BOOL success;
|
||||
STARTUPINFO sui;
|
||||
memset(&sui, 0, sizeof(sui));
|
||||
sui.cb = sizeof(sui);
|
||||
sui.dwFlags = STARTF_USESHOWWINDOW;
|
||||
sui.wShowWindow = SW_HIDE; // TODO: change SW_SHOW to SW_HIDE
|
||||
sui.lpDesktop = (LPWSTR)startupDesktop.utf16();
|
||||
PROCESS_INFORMATION pi;
|
||||
memset(&pi, 0, sizeof(pi));
|
||||
m_agentProcess = new PROCESS_INFORMATION;
|
||||
@ -81,6 +101,14 @@ AgentClient::AgentClient(int initialCols, int initialRows, QObject *parent) :
|
||||
// TODO: security -- Do we need to verify that this pipe connection was
|
||||
// made by the right client? i.e. The Agent.exe process we just started?
|
||||
socketServer->close();
|
||||
|
||||
// Restore the original window station.
|
||||
success = SetProcessWindowStation(originalStation);
|
||||
Q_ASSERT(success);
|
||||
success = CloseDesktop(desktop);
|
||||
Q_ASSERT(success);
|
||||
success = CloseWindowStation(station);
|
||||
Q_ASSERT(success);
|
||||
}
|
||||
|
||||
void AgentClient::writeMsg(const AgentMsg &msg)
|
||||
|
Loading…
Reference in New Issue
Block a user