Skip to content

Commit df60c2c

Browse files
committed
Added New-NtDesktop.
1 parent bfdac65 commit df60c2c

5 files changed

Lines changed: 213 additions & 6 deletions

File tree

NtApiDotNet/NtDesktop.cs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,12 @@ public static NtDesktop Open(string desktop_name)
113113
/// <param name="heap_size">Heap size.</param>
114114
/// <returns>An instance of NtDesktop.</returns>
115115
public static NtResult<NtDesktop> Create(ObjectAttributes object_attributes, string device,
116-
IntPtr dev_mode, CreateDesktopFlags flags, DesktopAccessRights desired_access, int heap_size,
116+
DEVMODE dev_mode, CreateDesktopFlags flags, DesktopAccessRights desired_access, int heap_size,
117117
bool throw_on_error)
118118
{
119119

120120
SafeKernelObjectHandle handle = NtSystemCalls.NtUserCreateDesktopEx(object_attributes,
121-
device == null ? null : new UnicodeString(device),
121+
string.IsNullOrEmpty(device) ? null : new UnicodeString(device),
122122
dev_mode, flags, desired_access, heap_size);
123123
if (handle.IsInvalid)
124124
{
@@ -127,6 +127,22 @@ public static NtResult<NtDesktop> Create(ObjectAttributes object_attributes, str
127127
return new NtResult<NtDesktop>(NtStatus.STATUS_SUCCESS, new NtDesktop(handle));
128128
}
129129

130+
/// <summary>
131+
/// Create a new desktop.
132+
/// </summary>
133+
/// <param name="object_attributes">The object attributes for opening.</param>
134+
/// <param name="flags">Flags for opening the desktop.</param>
135+
/// <param name="desired_access">Desired access.</param>
136+
/// <param name="device">Device name.</param>
137+
/// <param name="dev_mode">Device mode.</param>
138+
/// <param name="heap_size">Heap size.</param>
139+
/// <returns>An instance of NtDesktop.</returns>
140+
public static NtDesktop Create(ObjectAttributes object_attributes, string device,
141+
DEVMODE dev_mode, CreateDesktopFlags flags, DesktopAccessRights desired_access, int heap_size)
142+
{
143+
return Create(object_attributes, device, dev_mode, flags, desired_access, heap_size, true).Result;
144+
}
145+
130146
/// <summary>
131147
/// Create a new desktop.
132148
/// </summary>
@@ -137,7 +153,7 @@ public static NtDesktop Create(string desktop_name, NtObject root)
137153
{
138154
using (ObjectAttributes obj_attributes = new ObjectAttributes(desktop_name, AttributeFlags.CaseInsensitive, root))
139155
{
140-
return Create(obj_attributes, null, IntPtr.Zero, 0, DesktopAccessRights.MaximumAllowed, 0, true).Result;
156+
return Create(obj_attributes, null, null, 0, DesktopAccessRights.MaximumAllowed, 0, true).Result;
141157
}
142158
}
143159

@@ -186,5 +202,20 @@ public static NtDesktop GetThreadDesktop(int thread_id)
186202
/// Get list of top level Windows for this Desktop.
187203
/// </summary>
188204
public IEnumerable<NtWindow> Windows => NtWindow.GetWindows(this, NtWindow.Null, false, true, 0);
205+
206+
/// <summary>
207+
/// Close the Desktop. This is different from normal Close as it destroys the Desktop.
208+
/// </summary>
209+
/// <param name="throw_on_error">True to throw on error.</param>
210+
/// <returns>The NT status.</returns>
211+
public NtStatus CloseDesktop(bool throw_on_error = true)
212+
{
213+
if (!NtSystemCalls.NtUserCloseDesktop(Handle))
214+
{
215+
return NtObjectUtils.MapDosErrorToStatus().ToNtException(throw_on_error);
216+
}
217+
Handle.SetHandleAsInvalid();
218+
return NtStatus.STATUS_SUCCESS;
219+
}
189220
}
190221
}

NtApiDotNet/NtDesktopNative.cs

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,89 @@ public enum CreateDesktopFlags
5050
AllowOtherAccountHook = 1,
5151
}
5252

53+
[StructLayout(LayoutKind.Sequential)]
54+
public struct DEVMODE_S1
55+
{
56+
public short dmOrientation;
57+
public short dmPaperSize;
58+
public short dmPaperLength;
59+
public short dmPaperWidth;
60+
public short dmScale;
61+
public short dmCopies;
62+
public short dmDefaultSource;
63+
public short dmPrintQuality;
64+
}
65+
66+
[StructLayout(LayoutKind.Sequential)]
67+
public struct POINTL
68+
{
69+
public int x;
70+
public int y;
71+
}
72+
73+
[StructLayout(LayoutKind.Sequential)]
74+
public struct DEVMODE_S2
75+
{
76+
public POINTL dmPosition;
77+
public int dmDisplayOrientation;
78+
public int dmDisplayFixedOutput;
79+
}
80+
81+
[StructLayout(LayoutKind.Explicit)]
82+
public struct DEVMODE_UNION1
83+
{
84+
[FieldOffset(0)]
85+
public DEVMODE_S1 s1;
86+
[FieldOffset(0)]
87+
public DEVMODE_S2 s2;
88+
}
89+
90+
[StructLayout(LayoutKind.Explicit)]
91+
public struct DEVMODE_UNION2
92+
{
93+
[FieldOffset(0)]
94+
public int dmDisplayFlags;
95+
[FieldOffset(0)]
96+
public int dmNup;
97+
}
98+
99+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
100+
public class DEVMODE
101+
{
102+
public const int CCHDEVICENAME = 32;
103+
public const int CCHFORMNAME = 32;
104+
105+
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
106+
public string dmDeviceName;
107+
public short dmSpecVersion;
108+
public short dmDriverVersion;
109+
public short dmSize;
110+
public short dmDriverExtra;
111+
public int dmFields;
112+
public DEVMODE_UNION1 u1;
113+
public short dmColor;
114+
public short dmDuplex;
115+
public short dmYResolution;
116+
public short dmTTOption;
117+
public short dmCollate;
118+
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)]
119+
public string dmFormName;
120+
public short dmLogPixels;
121+
public int dmBitsPerPel;
122+
public int dmPelsWidth;
123+
public int dmPelsHeight;
124+
public DEVMODE_UNION2 u2;
125+
public int dmDisplayFrequency;
126+
public int dmICMMethod;
127+
public int dmICMIntent;
128+
public int dmMediaType;
129+
public int dmDitherType;
130+
public int dmReserved1;
131+
public int dmReserved2;
132+
public int dmPanningWidth;
133+
public int dmPanningHeight;
134+
}
135+
53136
public static partial class NtSystemCalls
54137
{
55138
[DllImport("win32u.dll", SetLastError = true)]
@@ -60,12 +143,16 @@ public static extern SafeKernelObjectHandle NtUserOpenDesktop(
60143
[DllImport("win32u.dll", SetLastError = true)]
61144
public static extern SafeKernelObjectHandle NtUserCreateDesktopEx(
62145
ObjectAttributes ObjectAttributes, UnicodeString Device,
63-
IntPtr DevMode, CreateDesktopFlags Flags,
146+
DEVMODE DevMode, CreateDesktopFlags Flags,
64147
DesktopAccessRights DesiredAccess,
65148
int HeapSize);
66149

67150
[DllImport("win32u.dll", SetLastError = true)]
68151
public static extern IntPtr NtUserGetThreadDesktop(int dwThreadId);
152+
153+
[DllImport("win32u.dll", SetLastError = true)]
154+
[return: MarshalAs(UnmanagedType.Bool)]
155+
public static extern bool NtUserCloseDesktop(SafeKernelObjectHandle handle);
69156
}
70157

71158
#pragma warning restore

NtApiDotNet/NtWindowStation.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ public NtStatus CloseWindowStation(bool throw_on_error = true)
323323
{
324324
return NtObjectUtils.MapDosErrorToStatus().ToNtException(throw_on_error);
325325
}
326+
Handle.SetHandleAsInvalid();
326327
return NtStatus.STATUS_SUCCESS;
327328
}
328329

NtObjectManager/NtObjectManager.psd1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ CmdletsToExport = 'Add-NtKey', 'Get-NtDirectory', 'Get-NtEvent', 'Get-NtFile',
102102
'Remove-NtTokenSecurityAttribute', 'Get-AccessibleEventTrace',
103103
'Test-NtToken', 'Get-AccessibleToken', 'Set-NtProcessJob',
104104
'Get-AccessibleWnf', 'Get-AccessibleWindowStation', 'Get-NtProcessJob',
105-
'Get-NtWindowStation', 'Get-NtDesktop', 'New-NtWindowStation'
105+
'Get-NtWindowStation', 'Get-NtDesktop', 'New-NtWindowStation',
106+
'New-NtDesktop'
106107

107108
# 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.
108109
AliasesToExport = @()

NtObjectManager/NtWin32Cmdlets.cs

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ protected override void ProcessRecord()
223223

224224
/// <summary>
225225
/// <para type="synopsis">Creates a Window Station object by path.</para>
226-
/// <para type="description">This cmdlet creates an new Window Station object. The absolute path to the object in the NT object manager name space must be specified.
226+
/// <para type="description">This cmdlet creates a new Window Station object. The absolute path to the object in the NT object manager name space must be specified.
227227
/// It's also possible to create the object relative to an existing object by specified the -Root parameter.</para>
228228
/// </summary>
229229
/// <example>
@@ -299,4 +299,91 @@ protected override object CreateObject(ObjectAttributes obj_attributes)
299299
LanguageId ?? 0x409, KeyboardLocale ?? 0x4090409);
300300
}
301301
}
302+
303+
/// <summary>
304+
/// <para type="synopsis">Creates a Desktop object by path.</para>
305+
/// <para type="description">This cmdlet creates a new Desktop object. The absolute path to the object in the NT object manager name space must be specified.
306+
/// It's also possible to create the object relative to an existing object by specified the -Root parameter.</para>
307+
/// </summary>
308+
/// <example>
309+
/// <code>$obj = New-NtDesktop \Windows\WindowStations\WinSta0\ABC</code>
310+
/// <para>Create a Desktop object with an absolute path.</para>
311+
/// </example>
312+
/// <example>
313+
/// <code>$root = Get-NtNtWindowStation \Windows\WindowStations\WinSta0&#x0A;$obj = New-NtDesktop ABC -Root $root</code>
314+
/// <para>Create a desktop object with a relative path.
315+
/// </para>
316+
/// </example>
317+
/// <example>
318+
/// <code>$obj = New-NtDesktop -Path ABC -Win32Path</code>
319+
/// <para>Create a desktop object from Win32 path in current Window Station.</para>
320+
/// </example>
321+
/// <para type="link">about_ManagingNtObjectLifetime</para>
322+
[Cmdlet(VerbsCommon.New, "NtDesktop")]
323+
[OutputType(typeof(NtDesktop))]
324+
public sealed class NewNtDesktopCmdlet : NtObjectBaseCmdletWithAccess<DesktopAccessRights>
325+
{
326+
/// <summary>
327+
/// <para type="description">The NT object manager path to the object to use.</para>
328+
/// </summary>
329+
[Parameter(Position = 0, Mandatory = true)]
330+
public override string Path { get; set; }
331+
332+
/// <summary>
333+
/// <para type="description">The device for the desktop.</para>
334+
/// </summary>
335+
[Parameter]
336+
public string Device { get; set; }
337+
338+
/// <summary>
339+
/// <para type="description">The device mode for the desktop.</para>
340+
/// </summary>
341+
[Parameter]
342+
public DEVMODE DeviceMode { get; set; }
343+
344+
/// <summary>
345+
/// <para type="description">The flags for the desktop.</para>
346+
/// </summary>
347+
[Parameter]
348+
public CreateDesktopFlags Flags { get; set; }
349+
350+
/// <summary>
351+
/// <para type="description">The heap size for the desktop.</para>
352+
/// </summary>
353+
[Parameter]
354+
public int HeapSize { get; set; }
355+
356+
/// <summary>
357+
/// Determine if the cmdlet can create objects.
358+
/// </summary>
359+
/// <returns>True if objects can be created.</returns>
360+
protected override bool CanCreateDirectories()
361+
{
362+
return true;
363+
}
364+
365+
/// <summary>
366+
/// Get the Win32 path for a specified path.
367+
/// </summary>
368+
/// <param name="path">The path component.</param>
369+
/// <returns>The full NT path.</returns>
370+
protected override string GetWin32Path(string path)
371+
{
372+
if (!path.Contains(@"\"))
373+
{
374+
return $@"{NtWindowStation.Current.FullPath}\{path}";
375+
}
376+
return $@"{NtWindowStation.GetWindowStationDirectory()}\{path}";
377+
}
378+
379+
/// <summary>
380+
/// Method to create an object from a set of object attributes.
381+
/// </summary>
382+
/// <param name="obj_attributes">The object attributes to create/open from.</param>
383+
/// <returns>The newly created object.</returns>
384+
protected override object CreateObject(ObjectAttributes obj_attributes)
385+
{
386+
return NtDesktop.Create(obj_attributes, Device, DeviceMode, Flags, Access, HeapSize);
387+
}
388+
}
302389
}

0 commit comments

Comments
 (0)