-
Couldn't load subscription status.
- Fork 1.1k
CA1838 Avoid 'StringBuilder' parameters for P/Invokes #8113
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
Changes from 2 commits
496a47d
73ec2f9
b3860a2
199bfb5
26a3f15
84f87f2
4b51246
1af7290
fb238ea
09f3073
1a4999f
06ee405
01345e6
22c139e
3cd1ae7
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 |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
| // See the LICENSE file in the project root for more information. | ||
|
|
||
| using System.Buffers; | ||
| using System.Diagnostics; | ||
| using System.Runtime.InteropServices; | ||
|
|
||
| namespace Windows.Win32 | ||
| { | ||
| internal static partial class PInvoke | ||
| { | ||
| public static unsafe string GetModuleFileNameLongPath(HINSTANCE hModule) | ||
| { | ||
| const int INSUFFICIENT_BUFFER = 0x007A; | ||
| char[] buffer; | ||
|
|
||
| // Try increased buffer sizes if on longpath-enabled Windows | ||
| for (int bufferSize = MAX_PATH; bufferSize <= MaxPath; bufferSize *= 2) | ||
elachlan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| buffer = ArrayPool<char>.Shared.Rent(bufferSize); | ||
elachlan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| try | ||
elachlan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| uint pathLength; | ||
| fixed (char* lpFilename = buffer) | ||
| { | ||
| pathLength = GetModuleFileName(hModule, lpFilename, (uint)bufferSize); | ||
elachlan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| bool isBufferTooSmall = Marshal.GetLastWin32Error() == INSUFFICIENT_BUFFER; | ||
| if (pathLength != 0 && !isBufferTooSmall && bufferSize <= int.MaxValue) | ||
elachlan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
elachlan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
elachlan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return new string(buffer, 0, (int)pathLength); | ||
| } | ||
| } | ||
| finally | ||
| { | ||
| ArrayPool<char>.Shared.Return(buffer); | ||
| } | ||
|
|
||
| // Double check that the buffer is not insanely big | ||
| Debug.Assert(bufferSize <= int.MaxValue / 2, "Buffer size approaching int.MaxValue"); | ||
elachlan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| return string.Empty; | ||
elachlan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
| // See the LICENSE file in the project root for more information. | ||
|
|
||
| namespace Windows.Win32 | ||
| { | ||
| internal static partial class PInvoke | ||
| { | ||
| public const int MAX_CLASS_NAME = 256; | ||
elachlan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
elachlan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10584,7 +10584,7 @@ public void RichTextBox_CheckDefaultNativeControlVersions() | |
| using var control = new RichTextBox(); | ||
| control.CreateControl(); | ||
|
|
||
| Assert.Contains("RICHEDIT50W", GetClassName(control.Handle), StringComparison.InvariantCultureIgnoreCase); | ||
| Assert.Contains("RICHEDIT50W", GetClassName(control.HWND), StringComparison.InvariantCultureIgnoreCase); | ||
elachlan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| [WinFormsFact] | ||
|
|
@@ -10593,13 +10593,13 @@ public void RichTextBox_CheckRichEditWithVersionCanCreateOldVersions() | |
| using (var riched32 = new RichEdit()) | ||
| { | ||
| riched32.CreateControl(); | ||
| Assert.Contains(".RichEdit.", GetClassName(riched32.Handle), StringComparison.InvariantCultureIgnoreCase); | ||
| Assert.Contains(".RichEdit.", GetClassName(riched32.HWND), StringComparison.InvariantCultureIgnoreCase); | ||
| } | ||
|
|
||
| using (var riched20 = new RichEdit20W()) | ||
| { | ||
| riched20.CreateControl(); | ||
| Assert.Contains(".RichEdit20W.", GetClassName(riched20.Handle), StringComparison.InvariantCultureIgnoreCase); | ||
| Assert.Contains(".RichEdit20W.", GetClassName(riched20.HWND), StringComparison.InvariantCultureIgnoreCase); | ||
|
|
||
| string rtfString = @"{\rtf1\ansi{" + | ||
| @"The next line\par " + | ||
|
|
@@ -10791,12 +10791,15 @@ private class SubRichTextBox : RichTextBox | |
| public new void WndProc(ref Message m) => base.WndProc(ref m); | ||
| } | ||
|
|
||
| private static string GetClassName(IntPtr hWnd) | ||
| private static unsafe string GetClassName(HWND hWnd) | ||
|
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. should this move to the PInvoke namespace? 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. I believe there is another place where we call 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. I didn't move this because its a wrapper and isn't used in the other calls. I am happy to still move it. The other uses avoid string allocations. 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. If you think this is a dup, feel free to remove this. I can't recall exact reasons why I copied it here. 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. Since its a wrapper of the pinvoke and we don't reuse it, I think it can stay here. |
||
| { | ||
| const int MaxClassName = 256; | ||
| StringBuilder sb = new StringBuilder(MaxClassName); | ||
| UnsafeNativeMethods.GetClassName(new HandleRef(null, hWnd), sb, MaxClassName); | ||
| return sb.ToString(); | ||
| Span<char> buf = stackalloc char[PInvoke.MAX_CLASS_NAME]; | ||
elachlan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| fixed (char* lpClassName = buf) | ||
| { | ||
| _ = PInvoke.GetClassName(hWnd, lpClassName, buf.Length); | ||
elachlan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| return buf.SliceAtFirstNull().ToString(); | ||
| } | ||
|
|
||
| /// <summary> | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.