Start the agent's child process on the libwinpty client's desktop.

If I run a GUI program inside mintty using winpty, the GUI's window should
appear on the same desktop as mintty, not on the hidden desktop containing
the winpty console.

Even though STARTUPINFO.lpDesktop's type is LPTSTR (instead of LPCTSTR),
the documentation doesn't say anything about CreateProcess modifying the
lpDesktop string, so I didn't bother making a copy of desktop.c_str().
This commit is contained in:
Ryan Prichard 2012-03-31 00:55:49 -07:00
parent 68e32a2bde
commit 80d005e33e
2 changed files with 35 additions and 6 deletions

View File

@ -199,6 +199,7 @@ int Agent::handleStartProcessPacket(ReadBuffer &packet)
std::wstring cmdline = packet.getWString();
std::wstring cwd = packet.getWString();
std::wstring env = packet.getWString();
std::wstring desktop = packet.getWString();
ASSERT(packet.eof());
LPCWSTR programArg = program.empty() ? NULL : program.c_str();
@ -212,11 +213,13 @@ int Agent::handleStartProcessPacket(ReadBuffer &packet)
}
LPCWSTR cwdArg = cwd.empty() ? NULL : cwd.c_str();
LPCWSTR envArg = env.empty() ? NULL : env.data();
STARTUPINFO sui;
PROCESS_INFORMATION pi;
memset(&sui, 0, sizeof(sui));
memset(&pi, 0, sizeof(pi));
sui.cb = sizeof(STARTUPINFO);
sui.lpDesktop = desktop.empty() ? NULL : (LPWSTR)desktop.c_str();
success = CreateProcess(programArg, cmdlineArg, NULL, NULL,
/*bInheritHandles=*/FALSE,

View File

@ -156,6 +156,24 @@ struct BackgroundDesktop {
std::wstring desktopName;
};
static std::wstring getObjectName(HANDLE object)
{
BOOL success;
DWORD lengthNeeded = 0;
GetUserObjectInformation(object, UOI_NAME,
NULL, 0,
&lengthNeeded);
assert(lengthNeeded % sizeof(wchar_t) == 0);
wchar_t *tmp = new wchar_t[lengthNeeded / 2];
success = GetUserObjectInformation(object, UOI_NAME,
tmp, lengthNeeded,
NULL);
assert(success);
std::wstring ret = tmp;
delete [] tmp;
return ret;
}
// Get a non-interactive window station for the agent.
// TODO: review security w.r.t. windowstation and desktop.
static BackgroundDesktop setupBackgroundDesktop()
@ -169,12 +187,8 @@ static BackgroundDesktop setupBackgroundDesktop()
assert(ret.originalStation != NULL);
assert(ret.station != NULL);
assert(ret.desktop != NULL);
wchar_t stationNameWStr[256];
success = GetUserObjectInformation(ret.station, UOI_NAME,
stationNameWStr, sizeof(stationNameWStr),
NULL);
assert(success);
ret.desktopName = std::wstring(stationNameWStr) + L"\\Default";
ret.desktopName =
getObjectName(ret.station) + L"\\" + getObjectName(ret.desktop);
return ret;
}
@ -185,6 +199,17 @@ static void restoreOriginalDesktop(const BackgroundDesktop &desktop)
CloseWindowStation(desktop.station);
}
static std::wstring getDesktopFullName()
{
// MSDN says that the handle returned by GetThreadDesktop does not need
// to be passed to CloseDesktop.
HWINSTA station = GetProcessWindowStation();
HDESK desktop = GetThreadDesktop(GetCurrentThreadId());
assert(station != NULL);
assert(desktop != NULL);
return getObjectName(station) + L"\\" + getObjectName(desktop);
}
static void startAgentProcess(const BackgroundDesktop &desktop,
std::wstring &controlPipeName,
std::wstring &dataPipeName,
@ -356,6 +381,7 @@ WINPTY_API int winpty_start_process(winpty_t *pc,
envStr.push_back(L'\0');
}
packet.putWString(envStr);
packet.putWString(getDesktopFullName());
writePacket(pc, packet);
return readInt32(pc);
}