Skip to content

Commit 9a9849b

Browse files
committed
Update RestartManager
1 parent 6b07a08 commit 9a9849b

2 files changed

Lines changed: 52 additions & 40 deletions

File tree

dev/DevWinUI.Base/Common/RestartManager/RestartManager.cs

Lines changed: 51 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,16 @@ private RestartManager(uint sessionHandle, string sessionKey)
1616
SessionKey = sessionKey;
1717
}
1818

19-
public unsafe static RestartManager CreateSession()
19+
public static RestartManager CreateSession()
2020
{
21-
var sessionKey = Guid.NewGuid().ToString();
22-
23-
uint sessionHandle;
24-
WIN32_ERROR result;
25-
fixed (char* pKey = sessionKey)
26-
{
27-
result = PInvoke.RmStartSession(
28-
&sessionHandle,
29-
0,
30-
(PWSTR)pKey
31-
);
32-
}
33-
34-
if (result != Windows.Win32.Foundation.WIN32_ERROR.ERROR_SUCCESS)
21+
Span<char> sessionKeyBuffer = stackalloc char[(int)PInvoke.CCH_RM_SESSION_KEY + 1];
22+
var result = StartSession(out var handle, sessionKeyBuffer);
23+
if (result != WIN32_ERROR.ERROR_SUCCESS)
3524
throw new Win32Exception((int)result, $"RmStartSession failed ({result})");
3625

37-
return new RestartManager(sessionHandle, sessionKey);
26+
var sessionKeyLength = sessionKeyBuffer.IndexOf('\0');
27+
var sessionKey = sessionKeyLength >= 0 ? new string(sessionKeyBuffer[..sessionKeyLength]) : new string(sessionKeyBuffer);
28+
return new RestartManager(handle, sessionKey);
3829
}
3930

4031
/// <summary>Joins an existing Restart Manager session using the specified session key.</summary>
@@ -54,21 +45,12 @@ public static RestartManager JoinSession(string sessionKey)
5445
/// <param name="path">The full path of the file to register.</param>
5546
/// <exception cref="ArgumentNullException">Thrown when <paramref name="path"/> is <see langword="null"/>.</exception>
5647
/// <exception cref="Win32Exception">Thrown when the registration fails.</exception>
57-
public unsafe void RegisterFile(string path)
48+
public void RegisterFile(string path)
5849
{
5950
ArgumentNullException.ThrowIfNull(path);
6051

6152
string[] resources = [path];
62-
WIN32_ERROR result;
63-
fixed (char* p0 = resources[0])
64-
{
65-
char** pcwstr = stackalloc char*[1];
66-
pcwstr[0] = p0;
67-
68-
PCWSTR* pResources = (PCWSTR*)pcwstr;
69-
result = PInvoke.RmRegisterResources(SessionHandle, (uint)resources.Length, pResources, 0, rgApplications: null, 0, rgsServiceNames: null);
70-
}
71-
53+
var result = RegisterResources(SessionHandle, resources);
7254
if (result != WIN32_ERROR.ERROR_SUCCESS)
7355
throw new Win32Exception((int)result, $"RmRegisterResources failed ({result})");
7456
}
@@ -77,22 +59,11 @@ public unsafe void RegisterFile(string path)
7759
/// <param name="paths">An array of full file paths to register.</param>
7860
/// <exception cref="ArgumentNullException">Thrown when <paramref name="paths"/> is <see langword="null"/>.</exception>
7961
/// <exception cref="Win32Exception">Thrown when the registration fails.</exception>
80-
public unsafe void RegisterFiles(string[] paths)
62+
public void RegisterFiles(string[] paths)
8163
{
8264
ArgumentNullException.ThrowIfNull(paths);
8365

84-
85-
WIN32_ERROR result;
86-
fixed (char* p0 = paths[0])
87-
{
88-
char** pcwstr = stackalloc char*[1];
89-
pcwstr[0] = p0;
90-
91-
PCWSTR* pPaths = (PCWSTR*)pcwstr;
92-
result = PInvoke.RmRegisterResources(SessionHandle, (uint)paths.LongLength, pPaths, 0, rgApplications: null, 0, rgsServiceNames: null);
93-
}
94-
95-
66+
var result = RegisterResources(SessionHandle, paths);
9667
if (result != WIN32_ERROR.ERROR_SUCCESS)
9768
throw new Win32Exception((int)result, $"RmRegisterResources failed ({result})");
9869
}
@@ -191,6 +162,46 @@ public unsafe void Restart(delegate* unmanaged[Stdcall]<uint, void> callback)
191162
throw new Win32Exception((int)result, $"RmRestart failed ({result})");
192163
}
193164

165+
private static unsafe WIN32_ERROR StartSession(out uint handle, Span<char> sessionKeyBuffer)
166+
{
167+
uint localHandle = 0;
168+
fixed (char* sessionKeyBufferPtr = sessionKeyBuffer)
169+
{
170+
var result = PInvoke.RmStartSession(&localHandle, 0, new PWSTR(sessionKeyBufferPtr));
171+
handle = localHandle;
172+
return result;
173+
}
174+
}
175+
176+
private static unsafe WIN32_ERROR RegisterResources(uint sessionHandle, string[] paths)
177+
{
178+
if (paths.Length == 0)
179+
return PInvoke.RmRegisterResources(sessionHandle, 0, (PCWSTR*)null, 0, (RM_UNIQUE_PROCESS*)null, 0, (PCWSTR*)null);
180+
181+
var handles = new GCHandle[paths.Length];
182+
try
183+
{
184+
var pathPointers = stackalloc PCWSTR[paths.Length];
185+
for (var i = 0; i < paths.Length; i++)
186+
{
187+
handles[i] = GCHandle.Alloc(paths[i], GCHandleType.Pinned);
188+
pathPointers[i] = new PCWSTR((char*)handles[i].AddrOfPinnedObject());
189+
}
190+
191+
return PInvoke.RmRegisterResources(sessionHandle, (uint)paths.Length, pathPointers, 0, (RM_UNIQUE_PROCESS*)null, 0, (PCWSTR*)null);
192+
}
193+
finally
194+
{
195+
foreach (var handle in handles)
196+
{
197+
if (handle.IsAllocated)
198+
{
199+
handle.Free();
200+
}
201+
}
202+
}
203+
}
204+
194205
/// <summary>Ends the Restart Manager session and releases all resources.</summary>
195206
/// <exception cref="Win32Exception">Thrown when ending the session fails.</exception>
196207
[SuppressMessage("Design", "CA1065:Do not raise exceptions in unexpected locations", Justification = "<Pending>")]

dev/DevWinUI.Base/NativeMethods.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,4 @@ WM_LBUTTONUP
101101
WM_RBUTTONUP
102102
WM_MBUTTONUP
103103
WINDOWS_HOOK_ID
104+
CCH_RM_SESSION_KEY

0 commit comments

Comments
 (0)