private static string GetFilenameOfRemoteHandle(SYSTEM_HANDLE_INFORMATION_EX systemHandleInformation, bool useCache = true)
        {
            IntPtr fileHandle        = IntPtr.Zero;
            IntPtr openProcessHandle = IntPtr.Zero;

            if (OBJECT_TYPE_FILE != -1 && systemHandleInformation.ObjectType != OBJECT_TYPE_FILE)
            {
                // this is not even a file
                return(null);
            }

            if (useCache)
            {
                // maybe it's already in the cache
                if (filenamesCache.ContainsKey(systemHandleInformation))
                {
                    return(filenamesCache[systemHandleInformation]);
                }
            }

            string filename = null;

            try
            {
                openProcessHandle = OpenProcess(PROCESS_ACCESS_FLAGS.DupHandle, true, (int)systemHandleInformation.ProcessID);
                if (!DuplicateHandle(openProcessHandle, systemHandleInformation.HandleValue, GetCurrentProcess(), out fileHandle, 0, false,
                                     DuplicateHandleOptions.DUPLICATE_SAME_ACCESS))
                {
                    return(null);
                }

                FileType fileType = GetFileType(fileHandle);
                if (fileType != FileType.FileTypeDisk && fileType != FileType.FileTypePipe)
                {
                    return(null);
                }

                // We know what the type of File is
                OBJECT_TYPE_FILE = systemHandleInformation.ObjectType;

                GetFileNameOfRemoteHandle(systemHandleInformation.HandleValue, (int)systemHandleInformation.ProcessID, out filename);
                return(filename);
            }
            finally
            {
                filenamesCache[systemHandleInformation] = filename;

                CloseHandle(fileHandle);
                CloseHandle(openProcessHandle);
            }
        }
        public static IEnumerable <SYSTEM_HANDLE_INFORMATION_EX> GetAllHandles()
        {
            List <SYSTEM_HANDLE_INFORMATION_EX> handles = new List <SYSTEM_HANDLE_INFORMATION_EX>();
            int    handlesInfoSize = Marshal.SizeOf(new SYSTEM_HANDLE_INFORMATION_EX()) * 20000;
            IntPtr ptrHandleData   = IntPtr.Zero;

            try
            {
                ptrHandleData = Marshal.AllocHGlobal(handlesInfoSize);
                int length = 0;

                while (NtQuerySystemInformation(CNST_SYSTEM_HANDLE_INFORMATION_EX, ptrHandleData, handlesInfoSize, ref length) == STATUS_INFO_LENGTH_MISMATCH)
                {
                    handlesInfoSize = length;
                    Marshal.FreeHGlobal(ptrHandleData);
                    ptrHandleData = Marshal.AllocHGlobal(length);
                }

                long   handleCount   = Marshal.ReadIntPtr(ptrHandleData).ToInt64();
                IntPtr ptrHandleItem = ptrHandleData + Marshal.SizeOf(ptrHandleData) + Marshal.SizeOf(new IntPtr());

                for (long i = 0; i < handleCount; i++)
                {
                    SYSTEM_HANDLE_INFORMATION_EX oSystemHandleInfo = Marshal.PtrToStructure <SYSTEM_HANDLE_INFORMATION_EX>(ptrHandleItem);
                    ptrHandleItem += Marshal.SizeOf(new SYSTEM_HANDLE_INFORMATION_EX());

                    handles.Add(oSystemHandleInfo);
                }
            }
            finally
            {
                Marshal.FreeHGlobal(ptrHandleData);
            }

            handlesCache = handles.ToArray();
            return(handles);
        }