예제 #1
0
        private static string GetMessageFromModule(
            string modulePath, int errorNumber, CultureInfo culture)
        {
            const uint LOAD_LIBRARY_AS_DATAFILE = 2;
            const int  RT_RCDATA = 10;

            IntPtr msgModule = NativeMethods.LoadLibraryEx(
                modulePath, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);

            if (msgModule == IntPtr.Zero)
            {
                return(null);
            }

            try
            {
                // On pre-Vista systems, the messages are stored as RCDATA resources.

                int    lcid         = 0;
                IntPtr resourceInfo = NativeMethods.FindResourceEx(
                    msgModule,
                    new IntPtr(RT_RCDATA),
                    new IntPtr(errorNumber),
                    (ushort)lcid);
                if (resourceInfo != IntPtr.Zero)
                {
                    IntPtr resourceData = NativeMethods.LoadResource(
                        msgModule, resourceInfo);
                    IntPtr resourcePtr = NativeMethods.LockResource(resourceData);

                    if (lcid == 0)
                    {
                        string msg = Marshal.PtrToStringAnsi(resourcePtr);
                        return(msg);
                    }
                    else
                    {
                        int len = 0;
                        while (Marshal.ReadByte(resourcePtr, len) != 0)
                        {
                            len++;
                        }
                        byte[] msgBytes = new byte[len + 1];
                        Marshal.Copy(resourcePtr, msgBytes, 0, msgBytes.Length);
                        Encoding encoding = Encoding.ASCII;
                        string   msg      = encoding.GetString(msgBytes);
                        return(msg);
                    }
                }
                else
                {
                    // On Vista (and above?), the messages are stored in the module message table.
                    // They're actually in MUI files, and the redirection happens automatically here.

                    const uint FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
                    const uint FORMAT_MESSAGE_FROM_HMODULE   = 0x00000800;
                    const uint MESSAGE_OFFSET = 20000; // Not documented, but observed on Vista

                    StringBuilder buf         = new StringBuilder(1024);
                    uint          formatCount = NativeMethods.FormatMessage(
                        FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS,
                        msgModule,
                        (uint)errorNumber + MESSAGE_OFFSET,
                        (ushort)lcid,
                        buf,
                        (uint)buf.Capacity,
                        IntPtr.Zero);

                    return(formatCount != 0 ? buf.ToString().Trim() : null);
                }
            }
            finally
            {
                NativeMethods.FreeLibrary(msgModule);
            }
        }