Skip to content

Commit

Permalink
Fix 32-bit process module enumeration on 64-bit Windows (#70370) (#71218
Browse files Browse the repository at this point in the history
)

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Co-authored-by: Stephen Toub <stoub@microsoft.com>
  • Loading branch information
3 people authored Jun 24, 2022
1 parent b869f40 commit 911da68
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ internal static partial class Interop
{
internal static partial class Kernel32
{
[LibraryImport(Libraries.Kernel32, EntryPoint = "K32EnumProcessModules", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
internal const int LIST_MODULES_ALL = 0x00000003;

[LibraryImport(Libraries.Kernel32, EntryPoint = "K32EnumProcessModulesEx", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static partial bool EnumProcessModules(SafeProcessHandle handle, IntPtr[]? modules, int size, out int needed);
internal static partial bool EnumProcessModulesEx(SafeProcessHandle handle, IntPtr[]? modules, int size, out int needed, int filterFlag);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
Link="Common\System\Collections\Generic\ArrayBuilder.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'windows'">
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.EnumProcessModules.cs"
Link="Common\Interop\Windows\Kernel32\Interop.EnumProcessModules.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.EnumProcessModulesEx.cs"
Link="Common\Interop\Windows\Kernel32\Interop.EnumProcessModulesEx.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.FormatMessage.cs"
Link="Common\Interop\Windows\Kernel32\Interop.FormatMessage.cs" />
<Compile Include="$(CommonPath)Interop\Windows\NtDll\Interop.NtQueryInformationProcess.cs"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ private static ProcessModuleCollection GetModules(int processId, bool firstModul
{
processHandle = ProcessManager.OpenProcess(processId, Interop.Advapi32.ProcessOptions.PROCESS_QUERY_INFORMATION | Interop.Advapi32.ProcessOptions.PROCESS_VM_READ, true);

bool succeeded = Interop.Kernel32.EnumProcessModules(processHandle, null, 0, out int needed);
bool succeeded = Interop.Kernel32.EnumProcessModulesEx(processHandle, null, 0, out int needed, Interop.Kernel32.LIST_MODULES_ALL);

// The API we need to use to enumerate process modules differs on two factors:
// 1) If our process is running in WOW64.
Expand Down Expand Up @@ -108,15 +108,15 @@ private static ProcessModuleCollection GetModules(int processId, bool firstModul
throw new Win32Exception(Interop.Errors.ERROR_PARTIAL_COPY, SR.EnumProcessModuleFailedDueToWow);
}

EnumProcessModulesUntilSuccess(processHandle, null, 0, out needed);
EnumProcessModulesUntilSuccess(processHandle, null, 0, out needed, Interop.Kernel32.LIST_MODULES_ALL);
}

int modulesCount = needed / IntPtr.Size;
IntPtr[] moduleHandles = new IntPtr[modulesCount];
while (true)
{
int size = needed;
EnumProcessModulesUntilSuccess(processHandle, moduleHandles, size, out needed);
EnumProcessModulesUntilSuccess(processHandle, moduleHandles, size, out needed, Interop.Kernel32.LIST_MODULES_ALL);
if (size == needed)
{
break;
Expand Down Expand Up @@ -221,15 +221,15 @@ private static ProcessModuleCollection GetModules(int processId, bool firstModul
}
}

private static void EnumProcessModulesUntilSuccess(SafeProcessHandle processHandle, IntPtr[]? modules, int size, out int needed)
private static void EnumProcessModulesUntilSuccess(SafeProcessHandle processHandle, IntPtr[]? modules, int size, out int needed, int filterFlag)
{
// When called on a running process, EnumProcessModules may fail with ERROR_PARTIAL_COPY
// if the target process is not yet initialized or if the module list changes during the function call.
// We just try to avoid the race by retring 50 (an arbitrary number) times.
int i = 0;
while (true)
{
if (Interop.Kernel32.EnumProcessModules(processHandle, modules, size, out needed))
if (Interop.Kernel32.EnumProcessModulesEx(processHandle, modules, size, out needed, filterFlag))
{
return;
}
Expand Down

0 comments on commit 911da68

Please sign in to comment.