-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Support long module path #57335
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support long module path #57335
Changes from 13 commits
638594b
ff306e0
20187cf
ed89f18
0b1c57e
969b96b
c3db3e6
e26b516
d2469a8
c2cfde0
46965ed
b1e9b11
93414f6
e391f71
6b4f2bc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -131,7 +131,13 @@ private static ProcessModuleCollection GetModules(int processId, bool firstModul | |
|
|
||
| var modules = new ProcessModuleCollection(firstModuleOnly ? 1 : modulesCount); | ||
|
|
||
| char[] chars = ArrayPool<char>.Shared.Rent(1024); | ||
| const int startLength = | ||
| #if DEBUG | ||
| 1; // in debug, validate ArrayPool growth | ||
| #else | ||
| Interop.Kernel32.MAX_PATH; | ||
| #endif | ||
| char[]? chars = ArrayPool<char>.Shared.Rent(startLength); | ||
| try | ||
| { | ||
| for (int i = 0; i < modulesCount; i++) | ||
|
|
@@ -151,7 +157,7 @@ private static ProcessModuleCollection GetModules(int processId, bool firstModul | |
| Interop.Kernel32.NtModuleInfo ntModuleInfo; | ||
| if (!Interop.Kernel32.GetModuleInformation(processHandle, moduleHandle, out ntModuleInfo)) | ||
| { | ||
| HandleLastWin32Error(); | ||
| HandleLastWin32Error(null); | ||
| continue; | ||
| } | ||
|
|
||
|
|
@@ -162,25 +168,40 @@ private static ProcessModuleCollection GetModules(int processId, bool firstModul | |
| BaseAddress = ntModuleInfo.BaseOfDll | ||
| }; | ||
|
|
||
| int length = Interop.Kernel32.GetModuleBaseName(processHandle, moduleHandle, chars, chars.Length); | ||
| int length = 0; | ||
| while ((length = Interop.Kernel32.GetModuleBaseName(processHandle, moduleHandle, chars, chars.Length)) == chars.Length) | ||
| { | ||
| ArrayPool<char>.Shared.Return(chars); | ||
| chars = ArrayPool<char>.Shared.Rent(length * 2); | ||
adamsitnik marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is it better to rent a new array first before returning the old one?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The order of renting and returning doesn't matter. But what does matter is the array being returned isn't referenced by the variable used for returning in the finally block. If it is, and the Return call throws after having stored the array, it could double return. |
||
| } | ||
|
|
||
| if (length == 0) | ||
| { | ||
| HandleLastWin32Error(); | ||
| HandleLastWin32Error(module); | ||
| continue; | ||
| } | ||
|
|
||
| module.ModuleName = new string(chars, 0, length); | ||
|
|
||
| length = Interop.Kernel32.GetModuleFileNameEx(processHandle, moduleHandle, chars, chars.Length); | ||
| while ((length = Interop.Kernel32.GetModuleFileNameEx(processHandle, moduleHandle, chars, chars.Length)) == chars.Length) | ||
| { | ||
| ArrayPool<char>.Shared.Return(chars); | ||
| chars = ArrayPool<char>.Shared.Rent(length * 2); | ||
adamsitnik marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| if (length == 0) | ||
| { | ||
| HandleLastWin32Error(); | ||
| HandleLastWin32Error(module); | ||
| continue; | ||
| } | ||
|
|
||
| module.FileName = (length >= 4 && chars[0] == '\\' && chars[1] == '\\' && chars[2] == '?' && chars[3] == '\\') ? | ||
| new string(chars, 4, length - 4) : | ||
| new string(chars, 0, length); | ||
| const string NtPathPrefix = @"\\?\"; | ||
| ReadOnlySpan<char> charsSpan = chars.AsSpan(0, length); | ||
| if (charsSpan.StartsWith(NtPathPrefix)) | ||
| { | ||
| charsSpan = charsSpan.Slice(NtPathPrefix.Length); | ||
| } | ||
| module.FileName = charsSpan.ToString(); | ||
|
|
||
| modules.Add(module); | ||
| } | ||
|
|
@@ -223,7 +244,7 @@ private static void EnumProcessModulesUntilSuccess(SafeProcessHandle processHand | |
| } | ||
| } | ||
|
|
||
| private static void HandleLastWin32Error() | ||
| private static void HandleLastWin32Error(ProcessModule? processModule) | ||
| { | ||
| int lastError = Marshal.GetLastWin32Error(); | ||
| switch (lastError) | ||
|
|
@@ -235,6 +256,7 @@ private static void HandleLastWin32Error() | |
| // move on. | ||
| break; | ||
| default: | ||
| processModule?.Dispose(); | ||
| throw new Win32Exception(lastError); | ||
| } | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.