Skip to content

Commit 6af5565

Browse files
committed
Added Get-NtDesktop and Get-NtWindowStation commands.
1 parent 7187ca8 commit 6af5565

6 files changed

Lines changed: 301 additions & 16 deletions

File tree

NtApiDotNet/NtDesktop.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,20 @@ public static NtResult<NtDesktop> Open(ObjectAttributes object_attributes, Creat
6161
return new NtResult<NtDesktop>(NtStatus.STATUS_SUCCESS, new NtDesktop(handle));
6262
}
6363

64+
/// <summary>
65+
/// Open a desktop by name.
66+
/// </summary>
67+
/// <param name="object_attributes">The object attributes for opening.</param>
68+
/// <param name="flags">Flags for opening the desktop.</param>
69+
/// <param name="desired_access">Desired access.</param>
70+
/// <returns>The instance of the desktop.</returns>
71+
/// <exception cref="NtException">Thrown on error.</exception>
72+
public static NtDesktop Open(ObjectAttributes object_attributes, CreateDesktopFlags flags,
73+
DesktopAccessRights desired_access)
74+
{
75+
return Open(object_attributes, flags, desired_access, true).Result;
76+
}
77+
6478
/// <summary>
6579
/// Open a desktop by name.
6680
/// </summary>

NtApiDotNet/NtWindowStation.cs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,18 @@ public static NtResult<NtWindowStation> Open(ObjectAttributes object_attributes,
102102
return new NtResult<NtWindowStation>(NtStatus.STATUS_SUCCESS, new NtWindowStation(handle));
103103
}
104104

105+
/// <summary>
106+
/// Open a window station by name.
107+
/// </summary>
108+
/// <param name="object_attributes">The object attributes for opening.</param>
109+
/// <param name="desired_access">Desired access.</param>
110+
/// <returns>The instance of the window station</returns>
111+
/// <exception cref="NtException">Thrown on error.</exception>
112+
public static NtWindowStation Open(ObjectAttributes object_attributes, WindowStationAccessRights desired_access)
113+
{
114+
return Open(object_attributes, desired_access, true).Result;
115+
}
116+
105117
/// <summary>
106118
/// Open a window station by name.
107119
/// </summary>
@@ -216,7 +228,7 @@ public NtStatus CloseWindowStation(bool throw_on_error = true)
216228
{
217229
if (!NtSystemCalls.NtUserCloseWindowStation(Handle))
218230
{
219-
return NtObjectUtils.MapDosErrorToStatus();
231+
return NtObjectUtils.MapDosErrorToStatus().ToNtException(throw_on_error);
220232
}
221233
return NtStatus.STATUS_SUCCESS;
222234
}
@@ -256,5 +268,29 @@ public static NtResult<NtWindowStation> OpenCurrent(bool throw_on_error)
256268
/// Open the current process Window Station.
257269
/// </summary>
258270
public static NtWindowStation Current => OpenCurrent(true).Result;
271+
272+
/// <summary>
273+
/// Get the Window Station directory for a session.
274+
/// </summary>
275+
/// <param name="session_id">The session ID.</param>
276+
/// <returns>The path to the Window Station directory.</returns>
277+
public static string GetWindowStationDirectory(int session_id)
278+
{
279+
string ret = @"\Windows\WindowStations";
280+
if (session_id != 0)
281+
{
282+
ret = $@"\Sessions\{session_id}{ret}";
283+
}
284+
return ret;
285+
}
286+
287+
/// <summary>
288+
/// Get the Window Station directory for the current session.
289+
/// </summary>
290+
/// <returns>The path to the Window Station directory.</returns>
291+
public static string GetWindowStationDirectory()
292+
{
293+
return GetWindowStationDirectory(NtProcess.Current.SessionId);
294+
}
259295
}
260296
}

NtObjectManager/NtObjectCmdlets.cs

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,28 @@ private static string RemoveDrive(string path)
220220
return path.Substring(index + 2);
221221
}
222222

223+
/// <summary>
224+
/// Get the Win32 path for a specified path.
225+
/// </summary>
226+
/// <param name="path">The path component.</param>
227+
/// <returns>The full NT path.</returns>
228+
protected virtual string GetWin32Path(string path)
229+
{
230+
List<string> ret = new List<string>();
231+
int session_id = NtProcess.Current.SessionId;
232+
if (session_id != 0)
233+
{
234+
ret.Add("Sessions");
235+
ret.Add(session_id.ToString());
236+
}
237+
ret.Add("BaseNamedObjects");
238+
if (!string.IsNullOrEmpty(path))
239+
{
240+
ret.AddRange(Path.Split('\\'));
241+
}
242+
return $@"\{string.Join(@"\", ret)}";
243+
}
244+
223245
/// <summary>
224246
/// Virtual method to resolve the value of the Path variable.
225247
/// </summary>
@@ -238,19 +260,7 @@ protected virtual string ResolvePath()
238260
throw new ArgumentException("Win32 paths can't start with a path separator");
239261
}
240262

241-
List<string> ret = new List<string>();
242-
int session_id = NtProcess.Current.SessionId;
243-
if (session_id != 0)
244-
{
245-
ret.Add("Sessions");
246-
ret.Add(session_id.ToString());
247-
}
248-
ret.Add("BaseNamedObjects");
249-
if (!string.IsNullOrEmpty(Path))
250-
{
251-
ret.AddRange(Path.Split('\\'));
252-
}
253-
return $@"\{string.Join(@"\", ret)}";
263+
return GetWin32Path(Path);
254264
}
255265

256266
if (Path.StartsWith(@"\") || Root != null)
@@ -335,7 +345,7 @@ private IEnumerable<NtObject> CreateDirectoriesAndObject()
335345
/// <summary>
336346
/// Overridden ProcessRecord method.
337347
/// </summary>
338-
protected sealed override void ProcessRecord()
348+
protected override void ProcessRecord()
339349
{
340350
VerifyParameters();
341351
try

NtObjectManager/NtObjectManager.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
<Compile Include="NtResourceManagerCmdlets.cs" />
6565
<Compile Include="NtTransactionCmdlets.cs" />
6666
<Compile Include="NtTransactionManagerCmdlets.cs" />
67+
<Compile Include="NtWin32Cmdlets.cs" />
6768
<Compile Include="PSUtils.cs" />
6869
<Compile Include="RpcServerCmdlets.cs" />
6970
<Compile Include="RpcServerNameCmdlets.cs" />

NtObjectManager/NtObjectManager.psd1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ CmdletsToExport = 'Add-NtKey', 'Get-NtDirectory', 'Get-NtEvent', 'Get-NtFile',
101101
'Compare-RpcServer', 'Select-RpcServer', 'Add-NtTokenSecurityAttribute',
102102
'Remove-NtTokenSecurityAttribute', 'Get-AccessibleEventTrace',
103103
'Test-NtToken', 'Get-AccessibleToken', 'Set-NtProcessJob',
104-
'Get-AccessibleWnf', 'Get-AccessibleWindowStation', 'Get-NtProcessJob'
104+
'Get-AccessibleWnf', 'Get-AccessibleWindowStation', 'Get-NtProcessJob',
105+
'Get-NtWindowStation', 'Get-NtDesktop'
105106

106107
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
107108
AliasesToExport = @()

NtObjectManager/NtWin32Cmdlets.cs

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
// Copyright 2020 Google Inc. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using NtApiDotNet;
16+
using System.Management.Automation;
17+
18+
namespace NtObjectManager
19+
{
20+
/// <summary>
21+
/// <para type="synopsis">Open a Window Station object by path.</para>
22+
/// <para type="description">This cmdlet opens an existing Window Station object. The absolute path to the object in the NT object manager name space must be specified.
23+
/// It's also possible to create the object relative to an existing object by specified the -Root parameter.</para>
24+
/// </summary>
25+
/// <example>
26+
/// <code>$obj = Get-NtWindowStation</code>
27+
/// <para>Get all accessible Window Stations.</para>
28+
/// </example>
29+
/// <example>
30+
/// <code>$obj = Get-NtWindowStation \Windows\WindowStations\WinSta0</code>
31+
/// <para>Get an Window Station object with an absolute path.</para>
32+
/// </example>
33+
/// <example>
34+
/// <code>$root = Get-NtDirectory \Windows\WindowStations&#x0A;$obj = Get-NtWindowStation ABC -Root $root</code>
35+
/// <para>Get an Window Station object with a relative path.
36+
/// </para>
37+
/// </example>
38+
/// <example>
39+
/// <code>$obj = Get-NtWindowStation -Path WinSta0 -Win32Path</code>
40+
/// <para>Get an Window Station object from Win32 path.</para>
41+
/// </example>
42+
/// <para type="link">about_ManagingNtObjectLifetime</para>
43+
[Cmdlet(VerbsCommon.Get, "NtWindowStation", DefaultParameterSetName = "All")]
44+
[OutputType(typeof(NtWindowStation))]
45+
public sealed class GetNtWindowStationCmdlet : NtObjectBaseCmdletWithAccess<WindowStationAccessRights>
46+
{
47+
/// <summary>
48+
/// Determine if the cmdlet can create objects.
49+
/// </summary>
50+
/// <returns>True if objects can be created.</returns>
51+
protected override bool CanCreateDirectories()
52+
{
53+
return false;
54+
}
55+
56+
/// <summary>
57+
/// <para type="description">The NT object manager path to the object to use.</para>
58+
/// </summary>
59+
[Parameter(Position = 0, Mandatory = true, ParameterSetName = "FromPath")]
60+
public override string Path { get; set; }
61+
62+
/// <summary>
63+
/// <para type="description">The current Window Station.</para>
64+
/// </summary>
65+
[Parameter(Mandatory = true, ParameterSetName = "FromCurrent")]
66+
public SwitchParameter Current { get; set; }
67+
68+
/// <summary>
69+
/// Get the Win32 path for a specified path.
70+
/// </summary>
71+
/// <param name="path">The path component.</param>
72+
/// <returns>The full NT path.</returns>
73+
protected override string GetWin32Path(string path)
74+
{
75+
return $@"{NtWindowStation.GetWindowStationDirectory()}\{path}";
76+
}
77+
78+
/// <summary>
79+
/// Method to create an object from a set of object attributes.
80+
/// </summary>
81+
/// <param name="obj_attributes">The object attributes to create/open from.</param>
82+
/// <returns>The newly created object.</returns>
83+
protected override object CreateObject(ObjectAttributes obj_attributes)
84+
{
85+
return NtWindowStation.Open(obj_attributes, Access);
86+
}
87+
88+
/// <summary>
89+
/// Overridden ProcessRecord method.
90+
/// </summary>
91+
protected override void ProcessRecord()
92+
{
93+
switch (ParameterSetName)
94+
{
95+
case "All":
96+
WriteObject(NtWindowStation.GetAccessibleWindowStations(Access), true);
97+
break;
98+
case "FromCurrent":
99+
{
100+
var winsta = NtWindowStation.Current;
101+
if (Access.HasFlag(WindowStationAccessRights.MaximumAllowed))
102+
{
103+
WriteObject(winsta);
104+
}
105+
else
106+
{
107+
WriteObject(winsta.Duplicate(Access));
108+
}
109+
}
110+
break;
111+
default:
112+
base.ProcessRecord();
113+
break;
114+
}
115+
}
116+
}
117+
118+
/// <summary>
119+
/// <para type="synopsis">Open a Desktop object by path.</para>
120+
/// <para type="description">This cmdlet opens an existing Desktop object. The absolute path to the object in the NT object manager name space must be specified.
121+
/// It's also possible to create the object relative to an existing object by specified the -Root parameter.</para>
122+
/// </summary>
123+
/// <example>
124+
/// <code>$obj = Get-NtDesktop</code>
125+
/// <para>Get all accessible Desktops.</para>
126+
/// </example>
127+
/// <example>
128+
/// <code>$obj = Get-NtDesktop \Windows\WindowStations\WinSta0\Default</code>
129+
/// <para>Get an desktop object with an absolute path.</para>
130+
/// </example>
131+
/// <example>
132+
/// <code>$winsta = Get-NtWindowStation -Current&#x0A;$obj = Get-NtDesktop ABC -Root $root</code>
133+
/// <para>Get an Desktop object with a relative path.
134+
/// </para>
135+
/// </example>
136+
/// <example>
137+
/// <code>$obj = Get-NtDesktop -Path Default -Win32Path</code>
138+
/// <para>Get the Default Desktop object in current Window Station.</para>
139+
/// </example>
140+
/// <example>
141+
/// <code>$obj = Get-NtDesktop -Path blah\Default -Win32Path</code>
142+
/// <para>Get the Default Desktop object in blah Window Station.</para>
143+
/// </example>
144+
/// <para type="link">about_ManagingNtObjectLifetime</para>
145+
[Cmdlet(VerbsCommon.Get, "NtDesktop", DefaultParameterSetName = "All")]
146+
[OutputType(typeof(NtDesktop))]
147+
public sealed class GetNtDesktopCmdlet : NtObjectBaseCmdletWithAccess<DesktopAccessRights>
148+
{
149+
/// <summary>
150+
/// Determine if the cmdlet can create objects.
151+
/// </summary>
152+
/// <returns>True if objects can be created.</returns>
153+
protected override bool CanCreateDirectories()
154+
{
155+
return false;
156+
}
157+
158+
/// <summary>
159+
/// <para type="description">The NT object manager path to the object to use.</para>
160+
/// </summary>
161+
[Parameter(Position = 0, Mandatory = true, ParameterSetName = "FromPath")]
162+
public override string Path { get; set; }
163+
164+
/// <summary>
165+
/// <para type="description">The current Desktop.</para>
166+
/// </summary>
167+
[Parameter(Mandatory = true, ParameterSetName = "FromCurrent")]
168+
public SwitchParameter Current { get; set; }
169+
170+
/// <summary>
171+
/// Get the Win32 path for a specified path.
172+
/// </summary>
173+
/// <param name="path">The path component.</param>
174+
/// <returns>The full NT path.</returns>
175+
protected override string GetWin32Path(string path)
176+
{
177+
if (!path.Contains(@"\"))
178+
{
179+
return $@"{NtWindowStation.Current.FullPath}\{path}";
180+
}
181+
return $@"{NtWindowStation.GetWindowStationDirectory()}\{path}";
182+
}
183+
184+
/// <summary>
185+
/// Method to create an object from a set of object attributes.
186+
/// </summary>
187+
/// <param name="obj_attributes">The object attributes to create/open from.</param>
188+
/// <returns>The newly created object.</returns>
189+
protected override object CreateObject(ObjectAttributes obj_attributes)
190+
{
191+
return NtDesktop.Open(obj_attributes, CreateDesktopFlags.None, Access);
192+
}
193+
194+
/// <summary>
195+
/// Overridden ProcessRecord method.
196+
/// </summary>
197+
protected override void ProcessRecord()
198+
{
199+
switch (ParameterSetName)
200+
{
201+
case "All":
202+
WriteObject(NtWindowStation.Current.GetAccessibleDesktops(Access), true);
203+
break;
204+
case "FromCurrent":
205+
{
206+
var desktop = NtDesktop.Current;
207+
if (Access.HasFlag(DesktopAccessRights.MaximumAllowed))
208+
{
209+
WriteObject(desktop);
210+
}
211+
else
212+
{
213+
WriteObject(desktop.Duplicate(Access));
214+
}
215+
}
216+
break;
217+
default:
218+
base.ProcessRecord();
219+
break;
220+
}
221+
}
222+
}
223+
}

0 commit comments

Comments
 (0)