Skip to content

Commit e69fa4d

Browse files
authored
Merge pull request #924 from immense/feature/show-consent-winlogon
Allow remote control consent and chat on Windows Login screen.
2 parents 8417df7 + 232ab26 commit e69fa4d

File tree

3 files changed

+52
-29
lines changed

3 files changed

+52
-29
lines changed

Agent/Services/Windows/AppLauncherWin.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@ public async Task<int> LaunchChatService(string pipeName, string userConnectionI
4949
$" --org-name \"{orgName}\"" +
5050
$" --org-id \"{orgId}\"",
5151
targetSessionId: -1,
52-
forceConsoleSession: false,
53-
desktopName: "default",
5452
hiddenWindow: false,
5553
out var procInfo);
5654
if (!result)
@@ -122,8 +120,6 @@ await hubConnection.SendAsync("DisplayMessage",
122120
$" --session-id \"{sessionId}\"" +
123121
$" --access-key \"{accessKey}\"",
124122
targetSessionId: targetSessionId,
125-
forceConsoleSession: Shlwapi.IsOS(OsType.OS_ANYSERVER) && targetSessionId == -1,
126-
desktopName: "default",
127123
hiddenWindow: false,
128124
out _);
129125
if (!result)
@@ -180,8 +176,6 @@ public async Task RestartScreenCaster(string[] viewerIds, string sessionId, stri
180176
$" --viewers {string.Join(",", viewerIds)}",
181177

182178
targetSessionId: targetSessionID,
183-
forceConsoleSession: Shlwapi.IsOS(OsType.OS_ANYSERVER) && targetSessionID == -1,
184-
desktopName: "default",
185179
hiddenWindow: false,
186180
out _);
187181

Desktop.Native/Windows/Win32Interop.cs

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,9 @@ public static nint OpenInputDesktop()
104104

105105
public static bool CreateInteractiveSystemProcess(
106106
string commandLine,
107-
int targetSessionId,
108-
bool forceConsoleSession,
109-
string desktopName,
110-
bool hiddenWindow,
111-
out PROCESS_INFORMATION procInfo)
107+
int targetSessionId,
108+
bool hiddenWindow,
109+
out PROCESS_INFORMATION procInfo)
112110
{
113111
uint winlogonPid = 0;
114112
var hUserTokenDup = nint.Zero;
@@ -117,21 +115,7 @@ public static bool CreateInteractiveSystemProcess(
117115

118116
procInfo = new PROCESS_INFORMATION();
119117

120-
// If not force console, find target session. If not present,
121-
// use last active session.
122-
var dwSessionId = Kernel32.WTSGetActiveConsoleSessionId();
123-
if (!forceConsoleSession)
124-
{
125-
var activeSessions = GetActiveSessions();
126-
if (activeSessions.Any(x => x.Id == targetSessionId))
127-
{
128-
dwSessionId = (uint)targetSessionId;
129-
}
130-
else
131-
{
132-
dwSessionId = activeSessions.Last().Id;
133-
}
134-
}
118+
var dwSessionId = ResolveWindowsSession(targetSessionId);
135119

136120
// Obtain the process ID of the winlogon process that is running within the currently active session.
137121
var processes = Process.GetProcessesByName("winlogon");
@@ -171,7 +155,7 @@ public static bool CreateInteractiveSystemProcess(
171155
// interaction with the new process.
172156
var si = new STARTUPINFO();
173157
si.cb = Marshal.SizeOf(si);
174-
si.lpDesktop = @"winsta0\" + desktopName;
158+
si.lpDesktop = @"winsta0\" + ResolveDesktopName(dwSessionId);
175159

176160
// Flags that specify the priority and creation method of the process.
177161
uint dwCreationFlags;
@@ -208,6 +192,53 @@ public static bool CreateInteractiveSystemProcess(
208192
return result;
209193
}
210194

195+
public static string ResolveDesktopName(uint targetSessionId)
196+
{
197+
var winDir = Environment.GetFolderPath(Environment.SpecialFolder.Windows);
198+
var logonUiPath = Path.Combine(winDir, "System32", "LogonUI.exe");
199+
var consentPath = Path.Combine(winDir, "System32", "consent.exe");
200+
201+
var isLogonScreenVisible = Process
202+
.GetProcessesByName("LogonUI")
203+
.Any(x => x.SessionId == targetSessionId && x.MainModule?.FileName.Equals(logonUiPath, StringComparison.OrdinalIgnoreCase) == true);
204+
205+
var isSecureDesktopVisible = Process
206+
.GetProcessesByName("consent")
207+
.Any(x => x.SessionId == targetSessionId && x.MainModule?.FileName.Equals(consentPath, StringComparison.OrdinalIgnoreCase) == true);
208+
209+
if (isLogonScreenVisible || isSecureDesktopVisible)
210+
{
211+
return "Winlogon";
212+
}
213+
214+
return "Default";
215+
}
216+
217+
public static uint ResolveWindowsSession(int targetSessionId)
218+
{
219+
var activeSessions = GetActiveSessions();
220+
if (activeSessions.Any(x => x.Id == targetSessionId))
221+
{
222+
// If exact match is found, return that session.
223+
return (uint)targetSessionId;
224+
}
225+
226+
if (Shlwapi.IsOS(OsType.OS_ANYSERVER))
227+
{
228+
// If Windows Server, default to console session.
229+
return Kernel32.WTSGetActiveConsoleSessionId();
230+
}
231+
232+
// If consumer version and there's an RDP session active, return that.
233+
if (activeSessions.Find(x => x.Type == WindowsSessionType.RDP) is { } rdSession)
234+
{
235+
return rdSession.Id;
236+
}
237+
238+
// Otherwise, return the console session.
239+
return Kernel32.WTSGetActiveConsoleSessionId();
240+
}
241+
211242
public static void SetMonitorState(MonitorState state)
212243
{
213244
SendMessage(0xFFFF, 0x112, 0xF170, (int)state);

Desktop.Shared/Startup/IServiceProviderExtensions.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,6 @@ private static void RelaunchElevated()
154154
commandLine,
155155
-1,
156156
false,
157-
"default",
158-
true,
159157
out var procInfo);
160158
Console.WriteLine($"Elevate result: {result}. Process ID: {procInfo.dwProcessId}.");
161159
Environment.Exit(0);

0 commit comments

Comments
 (0)