Hi, I was wondering if anyone could explain why my c# code is not working as expected.
See the inline comment for my particular problem, which occurs immediately after the call to FormatMessage:
/// <summary>
/// Gets the last error that occured on the calling thread. If the last error is a system error,
/// the string returned contains the error number and the formatted message, otherwise
/// <see cref="LastErrorNumber" /> is returned as a string.
/// </summary>
public static string LastError
{
get
{
int max_length = 64000;
IntPtr ptr = Marshal.AllocHGlobal(max_length);
try
{
FormatMessageFlags flags = FormatMessageFlags.FORMAT_MESSAGE_FROM_SYSTEM;
int e = GetLastError();
object source = null;
int lang = 0;
object args = null;
int c = FormatMessage(ref flags, ref source, ref e, ref lang, ptr, ref max_length, ref args);
/*
'c', the return value, is always 0.
If GetLastError() is called at this point, it will return 1812, which seems strange since I'm passing in
FORMAT_MESSAGE_FROM_SYSTEM
*/
StringBuilder sb = new StringBuilder();
sb.Append(e);
if (c != 0)
sb.AppendFormat(": {0}", Marshal.PtrToStringAnsi(ptr));
return sb.ToString();
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
}
Here is my external definition for FormatMessage:
[DllImport("Kernel32.dll")]
private static extern int FormatMessage(
[MarshalAs(UnmanagedType.I4)] ref FormatMessageFlags dwFlags, ref object lpSource, ref int dwMessageId,
ref int dwLanguageId, IntPtr msg, ref int nSize, ref object Arguments);
... And my flags enumeration:
/// <summary>
/// Flags for the FormatMessage kernel32 function.
/// </summary>
[Flags()]
public enum FormatMessageFlags
{
/// <summary>The lpBuffer parameter is a pointer to a PVOID pointer, and that the nSize parameter specifies the minimum number of
TCHARs to allocate for an output message buffer. The function allocates a buffer large enough to hold the formatted message, and
places a pointer to the allocated buffer at the address specified by lpBuffer. The caller should use the LocalFree function to free
the buffer when it is no longer needed.</summary>
FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100,
/// <summary>Insert sequences in the message definition are to be ignored and passed through to the output buffer unchanged. This
flag is useful for fetching a message for later formatting. If this flag is set, the Arguments parameter is ignored.</summary>
FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200,
/// <summary>The lpSource parameter is a pointer to a null-terminated message definition. The message definition may contain insert
sequences, just as the message text in a message table resource may. Cannot be used with FORMAT_MESSAGE_FROM_HMODULE or
FORMAT_MESSAGE_FROM_SYSTEM.</summary>
FORMAT_MESSAGE_FROM_STRING = 0x00000400,
/// <summary>The lpSource parameter is a module handle containing the message-table resource(s) to search. If this lpSource handle
is NULL, the current process's application image file will be searched. Cannot be used with FORMAT_MESSAGE_FROM_STRING.</summary>
FORMAT_MESSAGE_FROM_HMODULE = 0x00000800,
/// <summary>The function should search the system message-table resource(s) for the requested message. If this flag is specified
with FORMAT_MESSAGE_FROM_HMODULE, the function searches the system message table if the message is not found in the module specified
by lpSource. Cannot be used with FORMAT_MESSAGE_FROM_STRING.
/// If this flag is specified, an application can pass the result of the GetLastError function to retrieve the message text for a
system-defined error.</summary>
FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000,
/// <summary>The Arguments parameter is not a va_list structure, but is a pointer to an array of values that represent the
arguments.
/// This flag cannot be used with 64-bit argument values. If you are using 64-bit values, you must use the va_list
structure.</summary>
FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000,
/// <summary>The low-order byte of dwFlags can specify the maximum width of a formatted output line. Use the
FORMAT_MESSAGE_MAX_WIDTH_MASK constant and bitwise Boolean operations to set and retrieve this maximum width value.</summary>
FORMAT_MESSAGE_MAX_WIDTH_MASK = 0x000000FF
}

Signature
Dave Sexton
dave@www..jwaonline..com
-----------------------------------------------------------------------
Dave - 22 Mar 2005 04:44 GMT
In case this will help someone else out, I found my answer here (watch for wrapping):
http://groups-beta.google.com/group/microsoft.public.dotnet.framework.interop/br
owse_frm/thread/9e3a44a0181e4ea5/7c2e1af6a4970e0a?q=dotnet+FORMAT_MESSAGE_ALLOCA
TE_BUFFER#7c2e1af6a4970e0a

Signature
Dave Sexton
dave@www..jwaonline..com
-----------------------------------------------------------------------
> Hi, I was wondering if anyone could explain why my c# code is not working as expected.
>
[quoted text clipped - 82 lines]
> FORMAT_MESSAGE_MAX_WIDTH_MASK = 0x000000FF
> }