I have a class that will let me close process handles in a given process. I have the fundamentals down, and it works flawlessly in Win7 x64, but when I run it in WinXP x86, it hangs and I can't understand why. I feel like I am missing something fairly obvious, here.
public static List<handleFinder.SYSTEM_HANDLE_INFORMATION>
GetHandles(Process process = null, string IN_strObjectTypeName = null, string IN_strObjectName = null)
{
int nLength = 0;
int nHandleInfoSize = 0x10000;
IntPtr ipHandle = IntPtr.Zero;
IntPtr ipHandlePointer = Marshal.AllocHGlobal(nHandleInfoSize);
uint nStatus;
while ((nStatus = handleFinder.NtQuerySystemInformation(CNST_SYSTEM_HANDLE_INFORMATION, ipHandlePointer,nHandleInfoSize, ref nLength)) == STATUS_INFO_LENGTH_MISMATCH)
{
nHandleInfoSize = nLength;
Marshal.FreeHGlobal(ipHandlePointer);
ipHandlePointer = Marshal.AllocHGlobal(nLength);
}
byte[] baTemp = new byte[nLength];
Marshal.Copy(ipHandlePointer, baTemp, 0, nLength);
long lHandleCount = 0;
if (Is64Bits())
{
lHandleCount = Marshal.ReadInt64(ipHandlePointer);
ipHandle = new IntPtr(ipHandlePointer.ToInt64() + 8);
}
else
{
lHandleCount = Marshal.ReadInt32(ipHandlePointer);
ipHandle = new IntPtr(ipHandlePointer.ToInt32() + 4);
}
handleFinder.SYSTEM_HANDLE_INFORMATION shHandle;
List<handleFinder.SYSTEM_HANDLE_INFORMATION> lstHandles = new List<handleFinder.SYSTEM_HANDLE_INFORMATION>();
for (long lIndex = 0; lIndex < lHandleCount; lIndex++)
{
shHandle = new handleFinder.SYSTEM_HANDLE_INFORMATION();
if (Is64Bits())
{
shHandle = (handleFinder.SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(ipHandle, shHandle.GetType());
ipHandle = new IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle) + 8);
}
else
{
ipHandle = new IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle));
shHandle = (handleFinder.SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(ipHandle, shHandle.GetType());
}
if (process != null)
{
if (shHandle.ProcessID != process.Id) continue;
}
string strObjectTypeName = "";
if (IN_strObjectTypeName != null)
{
strObjectTypeName = getObjectTypeName(shHandle, Process.GetProcessById(shHandle.ProcessID));
if (strObjectTypeName != IN_strObjectTypeName) continue;
}
string strObjectName = "";
if (IN_strObjectName != null)
{
strObjectName = getObjectName(shHandle, Process.GetProcessById(shHandle.ProcessID));
if (strObjectName != IN_strObjectName) continue;
}
lstHandles.Add(shHandle);
string strObjectTypeName2 = getObjectTypeName(shHandle, Process.GetProcessById(shHandle.ProcessID));
string strObjectName2 = getObjectName(shHandle, Process.GetProcessById(shHandle.ProcessID));
Console.WriteLine("{0} {1} {2}", shHandle.ProcessID, strObjectTypeName2, strObjectName2);
}
return lstHandles;
}
public static bool Is64Bits()
{
return Marshal.SizeOf(typeof(IntPtr)) == 8 ? true : false;
}
}
public class HandleKiller
{
public static void doMurderHandle()
{
String ProcessName = "xboxstat";
try
{
Process process = Process.GetProcessesByName(ProcessName)[0];
var handles = Win32Processes.GetHandles(process, "File");
if (handles.Count == 0) throw new System.ArgumentException("No handles found");
foreach (var handle in handles)
{
IntPtr ipHandle = IntPtr.Zero;
if (!handleFinder.DuplicateHandle(Process.GetProcessById(handle.ProcessID).Handle, handle.Handle, handleFinder.GetCurrentProcess(), out ipHandle, 0, false, handleFinder.DUPLICATE_CLOSE_SOURCE))
Console.WriteLine("DuplicateHandle() failed, error = {0}", Marshal.GetLastWin32Error());
Console.WriteLine("Handle Killed!");
}
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("The process name '{0}' is not currently running", ProcessName);
}
catch (ArgumentException)
{
Console.WriteLine("The Handle '{0}' was not found in the process '{1}'", "", ProcessName);
}
Console.ReadLine();
}
}
}
NtQuerySystemInformation
that's hanging, and not something else likeNtQueryObject
? – OrnamentedNtQueryObject
to e.g. get the name of the "wrong" object (typically, certain named pipes in the system), the entire system can hang. There is no way to avoid this deadlock (and only this deadlock) without using kernel-mode code. I've never heard ofNtQuerySystemInformation
hanging though. See this for more info: forum.sysinternals.com/… – Ornamented