Skip to content

Commit 0e2083a

Browse files
committed
refactor: handle System process id issues; move GetFullProcessImageName
1 parent f0763ab commit 0e2083a

File tree

1 file changed

+62
-52
lines changed

1 file changed

+62
-52
lines changed

deadlock-dotnet-sdk/Domain/SafeHandleEx.cs

Lines changed: 62 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public SafeHandleEx(SafeHandleEx safeHandleEx) : this(safeHandleEx.SysHandleEx)
2929
internal SafeHandleEx(NativeMethods.SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX sysHandleEx) : base(false)
3030
{
3131
SysHandleEx = sysHandleEx;
32+
3233
try
3334
{
3435
HandleObjectType = SysHandleEx.GetHandleObjectType();
@@ -37,15 +38,20 @@ internal SafeHandleEx(NativeMethods.SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX sysHandleE
3738
{
3839
ExceptionLog.Add(e);
3940
}
41+
42+
// Get additional details from the handle's owner process
4043
try
4144
{
42-
//Process.EnterDebugMode(); Best practice: only call this once.
43-
4445
/** Open handle for process */
4546
// PROCESS_QUERY_LIMITED_INFORMATION is necessary for QueryFullProcessImageName
4647
// PROCESS_QUERY_LIMITED_INFORMATION + PROCESS_VM_READ for reading PEB from the process's memory space.
4748
// if we need to duplicate a handle later, we'll use PROCESS_DUP_HANDLE
4849

50+
if (ProcessId == 4)
51+
{
52+
ProcessName = "System";
53+
}
54+
4955
HANDLE rawHandle = OpenProcess(
5056
dwDesiredAccess: PROCESS_ACCESS_RIGHTS.PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_ACCESS_RIGHTS.PROCESS_VM_READ,
5157
bInheritHandle: (BOOL)false,
@@ -149,6 +155,58 @@ public void UnlockSystemHandle()
149155
}
150156
}
151157

158+
/// <summary>
159+
/// A wrapper for QueryFullProcessImageName, a system function that circumvents 32-bit process limitations when permitted the PROCESS_QUERY_LIMITED_INFORMATION right.
160+
/// </summary>
161+
/// <param name="hProcess">A SafeProcessHandle opened with <see cref="PROCESS_ACCESS_RIGHTS.PROCESS_QUERY_LIMITED_INFORMATION"/></param>
162+
/// <returns>The path to the executable image.</returns>
163+
/// <exception cref="ArgumentException">The process handle <paramref name="hProcess"/> is invalid</exception>
164+
/// <exception cref="Win32Exception">QueryFullProcessImageName failed. See Exception message for details.</exception>
165+
private unsafe static string GetFullProcessImageName(SafeProcessHandle hProcess)
166+
{
167+
if (hProcess.IsInvalid)
168+
throw new ArgumentException("The process handle is invalid", nameof(hProcess));
169+
170+
uint size = 260 + 1;
171+
uint bufferLength = size;
172+
string retVal = "";
173+
174+
using PWSTR buffer = new((char*)Marshal.AllocHGlobal((int)bufferLength));
175+
if (QueryFullProcessImageName(
176+
hProcess: hProcess,
177+
dwFlags: PROCESS_NAME_FORMAT.PROCESS_NAME_WIN32,
178+
lpExeName: buffer,
179+
lpdwSize: ref size))
180+
{
181+
retVal = buffer.ToString();
182+
}
183+
else if (bufferLength < size)
184+
{
185+
using PWSTR newBuffer = Marshal.ReAllocHGlobal((IntPtr)buffer.Value, (IntPtr)size);
186+
if (QueryFullProcessImageName(
187+
hProcess,
188+
PROCESS_NAME_FORMAT.PROCESS_NAME_WIN32,
189+
newBuffer,
190+
ref size))
191+
{
192+
retVal = newBuffer.ToString();
193+
}
194+
else
195+
{
196+
// this constructor calls Marshal.GetLastPInvokeError() and Marshal.GetPInvokeErrorMessage(int)
197+
throw new Win32Exception();
198+
}
199+
}
200+
else
201+
{
202+
// this constructor calls Marshal.GetLastPInvokeError() and Marshal.GetPInvokeErrorMessage(int)
203+
throw new Win32Exception();
204+
}
205+
206+
// PWSTR instances are freed by their using blocks' finalizers
207+
return retVal;
208+
}
209+
152210
/// <summary>
153211
/// Try to get a process's command line from its PEB
154212
/// </summary>
@@ -208,57 +266,9 @@ private unsafe static string GetProcessCommandLine(SafeProcessHandle hProcess)
208266
}
209267

210268
/// <summary>
211-
/// A wrapper for QueryFullProcessImageName
269+
/// Release all resources owned by the current process that are associated with this handle.
212270
/// </summary>
213-
/// <param name="hProcess">A SafeProcessHandle opened with <see cref="PROCESS_ACCESS_RIGHTS.PROCESS_QUERY_LIMITED_INFORMATION"/></param>
214-
/// <returns>The path to the executable image.</returns>
215-
/// <exception cref="ArgumentException">The process handle <paramref name="hProcess"/> is invalid</exception>
216-
/// <exception cref="Win32Exception">QueryFullProcessImageName failed. See Exception message for details.</exception>
217-
private unsafe static string GetFullProcessImageName(SafeProcessHandle hProcess)
218-
{
219-
if (hProcess.IsInvalid)
220-
throw new ArgumentException("The process handle is invalid", nameof(hProcess));
221-
222-
uint size = 260 + 1;
223-
uint bufferLength = size;
224-
string retVal = "";
225-
226-
using PWSTR buffer = new((char*)Marshal.AllocHGlobal((int)bufferLength));
227-
if (QueryFullProcessImageName(
228-
hProcess: hProcess,
229-
dwFlags: PROCESS_NAME_FORMAT.PROCESS_NAME_WIN32,
230-
lpExeName: buffer,
231-
lpdwSize: ref size))
232-
{
233-
retVal = buffer.ToString();
234-
}
235-
else if (bufferLength < size)
236-
{
237-
using PWSTR newBuffer = Marshal.ReAllocHGlobal((IntPtr)buffer.Value, (IntPtr)size);
238-
if (QueryFullProcessImageName(
239-
hProcess,
240-
PROCESS_NAME_FORMAT.PROCESS_NAME_WIN32,
241-
newBuffer,
242-
ref size))
243-
{
244-
retVal = newBuffer.ToString();
245-
}
246-
else
247-
{
248-
// this constructor calls Marshal.GetLastPInvokeError() and Marshal.GetPInvokeErrorMessage(int)
249-
throw new Win32Exception();
250-
}
251-
}
252-
else
253-
{
254-
// this constructor calls Marshal.GetLastPInvokeError() and Marshal.GetPInvokeErrorMessage(int)
255-
throw new Win32Exception();
256-
}
257-
258-
// PWSTR instances are freed by their using blocks' finalizers
259-
return retVal;
260-
}
261-
271+
/// <returns></returns>
262272
protected override bool ReleaseHandle()
263273
{
264274
Close();

0 commit comments

Comments
 (0)