Skip to content

Commit 8a216d1

Browse files
committed
Set up P/Invoke source code generation via CsWin32 and update Microsoft.Dism
1 parent bfdc747 commit 8a216d1

File tree

5 files changed

+44
-80
lines changed

5 files changed

+44
-80
lines changed

src/NativeMethods.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"$schema": "https://aka.ms/CsWin32.schema.json",
3+
"className": "WinAPI"
4+
}

src/NativeMethods.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
AdjustTokenPrivileges
2+
GetCurrentProcess
3+
OpenProcessToken
4+
LookupPrivilegeValue
5+
FindWindow
6+
PostMessage
7+
WIN32_ERROR

src/Utils/OS.cs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using System.Diagnostics;
22
using System.IO;
3-
using System.Runtime.InteropServices;
43
using System.Threading;
4+
using Windows.Win32;
55
using Microsoft.Win32;
66
using Win10BloatRemover.UI;
77

@@ -50,10 +50,10 @@ public static void CloseExplorer()
5050
{
5151
// This is the same as doing Ctrl+Shift+Right click on the system tray -> Exit Explorer
5252
// Solution found at https://stackoverflow.com/a/5705965
53-
IntPtr trayWindow = FindWindow("Shell_TrayWnd", null);
53+
var trayWindow = WinAPI.FindWindow("Shell_TrayWnd");
5454
if (trayWindow != IntPtr.Zero)
5555
{
56-
PostMessage(trayWindow, 0x5B4, IntPtr.Zero, IntPtr.Zero);
56+
WinAPI.PostMessage(trayWindow, 0x5B4, 0, 0);
5757
Thread.Sleep(TimeSpan.FromSeconds(2)); // wait for the process to gracefully exit
5858
}
5959
// If the Explorer option "Launch folder windows in a separate process" is enabled, that separate process
@@ -152,12 +152,4 @@ public static bool IsWindows10()
152152
var windowsVersion = Environment.OSVersion.Version;
153153
return windowsVersion.Major == 10 && windowsVersion.Build < 21996;
154154
}
155-
156-
[DllImport("user32.dll", SetLastError = true)]
157-
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
158-
private static extern IntPtr FindWindow(string? className, string? windowName);
159-
160-
[DllImport("user32.dll", SetLastError = true)]
161-
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
162-
private static extern bool PostMessage(IntPtr windowHandle, uint message, IntPtr wParam, IntPtr lParam);
163155
}

src/Utils/TokenPrivilege.cs

Lines changed: 26 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
using System.Runtime.InteropServices;
22
using System.Security;
3+
using Windows.Win32;
4+
using Windows.Win32.Foundation;
5+
using Windows.Win32.Security;
36

47
namespace Win10BloatRemover.Utils;
58

@@ -8,91 +11,46 @@ namespace Win10BloatRemover.Utils;
811
*/
912
class TokenPrivilege : IDisposable
1013
{
11-
private enum PrivilegeAction : uint
12-
{
13-
Disable = 0x0,
14-
Enable = 0x2
15-
}
16-
1714
public static TokenPrivilege TakeOwnership => new TokenPrivilege("SeTakeOwnershipPrivilege");
1815

1916
private readonly string privilegeName;
2017

2118
private TokenPrivilege(string privilegeName)
2219
{
2320
this.privilegeName = privilegeName;
24-
Apply(PrivilegeAction.Enable);
25-
}
26-
27-
private void Apply(PrivilegeAction action)
28-
{
29-
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out IntPtr tokenHandle);
30-
LookupPrivilegeValue(null, privilegeName, out Luid luid);
31-
var tokenPrivilege = new TokenPrivileges(luid, (uint) action);
32-
UpdateTokenPrivileges(tokenHandle, tokenPrivilege);
33-
}
34-
35-
private void UpdateTokenPrivileges(IntPtr tokenHandle, TokenPrivileges privilegeInfo)
36-
{
37-
bool successful = AdjustTokenPrivileges(tokenHandle, false, ref privilegeInfo, 0, IntPtr.Zero, IntPtr.Zero);
38-
if (!successful || Marshal.GetLastWin32Error() == ERROR_NOT_ALL_ASSIGNED)
39-
throw new SecurityException($"Can't adjust token privilege {privilegeName}");
21+
TogglePrivilege(Action.Enable);
4022
}
41-
23+
4224
public void Dispose()
4325
{
44-
Apply(PrivilegeAction.Disable);
26+
TogglePrivilege(Action.Disable);
4527
}
46-
47-
#region P/Invoke structs and methods
48-
private const int ERROR_NOT_ALL_ASSIGNED = 1300;
49-
50-
[StructLayout(LayoutKind.Sequential)]
51-
private struct TokenPrivileges(Luid luid, uint attributes)
28+
29+
private enum Action : uint
5230
{
53-
// We can use this struct only with one privilege since CLR doesn't support marshalling dynamic-sized arrays
54-
private uint Count = 1;
55-
56-
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
57-
private LuidAndAttributes[] Privileges = [new LuidAndAttributes(luid, attributes)];
31+
Disable = 0x0,
32+
Enable = 0x2
5833
}
5934

60-
[StructLayout(LayoutKind.Sequential)]
61-
private readonly struct LuidAndAttributes(Luid luid, uint attributes)
35+
private void TogglePrivilege(Action privilegeAction)
6236
{
63-
private readonly Luid Luid = luid;
64-
private readonly uint Attributes = attributes;
37+
using var currentProcessHandle = WinAPI.GetCurrentProcess_SafeHandle();
38+
WinAPI.OpenProcessToken(currentProcessHandle,
39+
TOKEN_ACCESS_MASK.TOKEN_ADJUST_PRIVILEGES | TOKEN_ACCESS_MASK.TOKEN_QUERY, out var tokenHandle);
40+
WinAPI.LookupPrivilegeValue(null, privilegeName, out var privilegeLuid);
41+
UpdateTokenPrivileges(tokenHandle, privilegeLuid, privilegeAction);
6542
}
6643

67-
[StructLayout(LayoutKind.Sequential)]
68-
private readonly struct Luid
44+
private unsafe void UpdateTokenPrivileges(SafeHandle tokenHandle, LUID privilegeLuid, Action privilegeAction)
6945
{
70-
private readonly uint LowPart;
71-
private readonly int HighPart;
46+
var updatedPrivileges = new TOKEN_PRIVILEGES {
47+
PrivilegeCount = 1,
48+
Privileges = new VariableLengthInlineArray<LUID_AND_ATTRIBUTES> {
49+
[0] = new LUID_AND_ATTRIBUTES { Luid = privilegeLuid, Attributes = (TOKEN_PRIVILEGES_ATTRIBUTES) privilegeAction }
50+
}
51+
};
52+
bool successful = WinAPI.AdjustTokenPrivileges(tokenHandle, false, &updatedPrivileges, null);
53+
if (!successful || Marshal.GetLastWin32Error() == (int) WIN32_ERROR.ERROR_NOT_ALL_ASSIGNED)
54+
throw new SecurityException($"Can't adjust token privilege {privilegeName}");
7255
}
73-
74-
private const int TOKEN_QUERY = 0x8;
75-
private const int TOKEN_ADJUST_PRIVILEGES = 0x20;
76-
77-
[DllImport("advapi32.dll", SetLastError = true)]
78-
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
79-
private static extern bool AdjustTokenPrivileges(IntPtr tokenHandle,
80-
bool disableAllPrivileges,
81-
ref TokenPrivileges newState,
82-
int bufferLength,
83-
IntPtr previousState,
84-
IntPtr returnLength);
85-
86-
[DllImport("kernel32.dll")]
87-
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
88-
private static extern IntPtr GetCurrentProcess();
89-
90-
[DllImport("advapi32.dll", SetLastError = true)]
91-
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
92-
private static extern bool OpenProcessToken(IntPtr processHandle, int desiredAccess, out IntPtr tokenHandle);
93-
94-
[DllImport("advapi32.dll", SetLastError = true)]
95-
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
96-
private static extern bool LookupPrivilegeValue(string? systemName, string privilegeName, out Luid privilegeLuid);
97-
#endregion
9856
}

src/Win10BloatRemover.csproj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@
2121
<Using Include="System.Linq" />
2222
</ItemGroup>
2323
<ItemGroup>
24-
<PackageReference Include="Microsoft.Dism" Version="3.1.0" />
24+
<PackageReference Include="Microsoft.Dism" Version="4.0.7" />
25+
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.264" />
2526
</ItemGroup>
2627
<PropertyGroup>
28+
<CsWin32RunAsBuildTask>true</CsWin32RunAsBuildTask>
29+
<DisableRuntimeMarshalling>true</DisableRuntimeMarshalling>
2730
<InvariantGlobalization>true</InvariantGlobalization>
2831
<EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding>
2932
<EventSourceSupport>false</EventSourceSupport>

0 commit comments

Comments
 (0)