public static ProcessModuleWow64Safe[] ModulesWow64Safe(this Process p)
        {
            if (ModuleCache.Count > 100)
            {
                ModuleCache.Clear();
            }

            const int LIST_MODULES_ALL = 3;
            const int MAX_PATH         = 260;

            var hModules = new IntPtr[1024];

            uint cb = (uint)IntPtr.Size * (uint)hModules.Length;
            uint cbNeeded;

            if (!WinAPI.EnumProcessModulesEx(p.Handle, hModules, cb, out cbNeeded, LIST_MODULES_ALL))
            {
                throw new Win32Exception();
            }
            uint numMods = cbNeeded / (uint)IntPtr.Size;

            int hash = p.StartTime.GetHashCode() + p.Id + (int)numMods;

            if (ModuleCache.ContainsKey(hash))
            {
                return(ModuleCache[hash]);
            }

            var ret = new List <ProcessModuleWow64Safe>();

            // everything below is fairly expensive, which is why we cache!
            var sb = new StringBuilder(MAX_PATH);

            for (int i = 0; i < numMods; i++)
            {
                sb.Clear();
                if (WinAPI.GetModuleFileNameEx(p.Handle, hModules[i], sb, (uint)sb.Capacity) == 0)
                {
                    throw new Win32Exception();
                }
                string fileName = sb.ToString();

                sb.Clear();
                if (WinAPI.GetModuleBaseName(p.Handle, hModules[i], sb, (uint)sb.Capacity) == 0)
                {
                    throw new Win32Exception();
                }
                string baseName = sb.ToString();

                var moduleInfo = new WinAPI.MODULEINFO();
                if (!WinAPI.GetModuleInformation(p.Handle, hModules[i], out moduleInfo, (uint)Marshal.SizeOf(moduleInfo)))
                {
                    throw new Win32Exception();
                }

                ret.Add(new ProcessModuleWow64Safe()
                {
                    FileName          = fileName,
                    BaseAddress       = moduleInfo.lpBaseOfDll,
                    ModuleMemorySize  = (int)moduleInfo.SizeOfImage,
                    EntryPointAddress = moduleInfo.EntryPoint,
                    ModuleName        = baseName
                });
            }

            ModuleCache.Add(hash, ret.ToArray());

            return(ret.ToArray());
        }