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
FormatMessage lpBuffer not marked as ref/out #537
Comments
Formally, I believe there should be an overload taking a void* for that parameter. |
I don't think the emitted code is inaccurate, since it matches the headers for this function. And it's functional as is, as demonstrated by this (working) code: using System.ComponentModel;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.System.Diagnostics.Debug;
unsafe
{
PWSTR formattedMessage;
fixed (char* lpSource = "Hello, World!")
{
uint length = PInvoke.FormatMessage(
FORMAT_MESSAGE_OPTIONS.FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_OPTIONS.FORMAT_MESSAGE_FROM_STRING,
lpSource,
0,
0,
(PWSTR)(void*)&formattedMessage,
0,
null);
if (length == 0)
{
throw new Win32Exception();
}
try
{
Console.WriteLine($"Result: {formattedMessage}");
}
finally
{
PInvoke.LocalFree((nint)formattedMessage.Value);
}
}
} The cast on Now I'd like to show a sample of how to do something more interesting with |
I think #665 will be required to provide formatting args. |
It turns out that #665 is irrelevant, as that deals with unsafe
{
PWSTR formattedMessage;
Span<IntPtr> formattingArgs = stackalloc IntPtr[1];
fixed (char* lpSource = "Hello, %1%!")
fixed (char* lpWorld = "World")
fixed (IntPtr* pFormattingArgs = formattingArgs)
{
formattingArgs[0] = (IntPtr)lpWorld;
uint length = PInvoke.FormatMessage(
FORMAT_MESSAGE_OPTIONS.FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_OPTIONS.FORMAT_MESSAGE_FROM_STRING |
FORMAT_MESSAGE_OPTIONS.FORMAT_MESSAGE_ARGUMENT_ARRAY,
lpSource,
0,
0,
(PWSTR)(void*)&formattedMessage,
0,
(sbyte**)pFormattingArgs);
if (length == 0)
{
throw new Win32Exception();
}
try
{
Console.WriteLine($"Result: {formattedMessage}");
}
finally
{
PInvoke.LocalFree((nint)formattedMessage.Value);
}
}
} Presumably this should scale to multiple formatting args, but the documented spec for the |
Actual behavior
When generated, the lpBuffer parameter of FormatMessage is incorrectly generated as just a plain
LPTSTR
, this prevents the use ofFORMAT_MESSAGE_ALLOCATE_BUFFER
as the allocated buffer should be written to the lpBuffer param.Expected behavior
When the
FORMAT_MESSAGE_ALLOCATE_BUFFER
flag is specified in dwFlags, the lpBuffer param should receive the address of the allocated buffer - as it is not passed by ref / as an out, the function instead returns error 87 parameter incorrect.Repro steps
NativeMethods.txt
content:NativeMethods.json
content (if present):No content.
Any of your own code that should be shared?
The following code will reproduce the issue, originally found when trying to get an error from a return value from
NtQueryInformationProcess
- the status code below has been copied from that & the expected string result from theGetErrorMessage
function should be"The specified information record length does not match the length required for the specified information class."
Context
0.1.647-beta
net472
8
The text was updated successfully, but these errors were encountered: