@@ -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