Exemplo n.º 1
0
 internal static extern int LoadString(SafeLibraryHandle handle, int id, [Out] StringBuilder buffer, int bufferLength);
Exemplo n.º 2
0
        // FormatMessageW will AV if you don't pass in enough format strings.  If you call TryFormatMessage we ensure insertionStrings
        // is long enough.  You don't want to call this directly unless you're sure insertionStrings is long enough!
        internal static string UnsafeTryFormatMessage(SafeLibraryHandle hModule, uint messageNum, string[] insertionStrings) {
            string msg = null;

            int msgLen = 0;
            StringBuilder buf = new StringBuilder(1024);
            int flags = NativeMethods.FORMAT_MESSAGE_FROM_HMODULE | NativeMethods.FORMAT_MESSAGE_ARGUMENT_ARRAY;

            IntPtr[] addresses = new IntPtr[insertionStrings.Length];
            GCHandle[] handles = new GCHandle[insertionStrings.Length];
            GCHandle stringsRoot = GCHandle.Alloc(addresses, GCHandleType.Pinned);

            // Make sure that we don't try to pass in a zero length array of addresses.  If there are no insertion strings, 
            // we'll use the FORMAT_MESSAGE_IGNORE_INSERTS flag . 
            // If you change this behavior, make sure you look at TryFormatMessage which depends on this behavior!
            if (insertionStrings.Length == 0) {
                flags |= NativeMethods.FORMAT_MESSAGE_IGNORE_INSERTS;
            }
            
            try {
                for (int i=0; i<handles.Length; i++) {
                    handles[i] = GCHandle.Alloc(insertionStrings[i], GCHandleType.Pinned);
                    addresses[i] = handles[i].AddrOfPinnedObject();
                }
                int lastError = NativeMethods.ERROR_INSUFFICIENT_BUFFER;
                while (msgLen == 0 && lastError == NativeMethods.ERROR_INSUFFICIENT_BUFFER) {
                    msgLen = SafeNativeMethods.FormatMessage(
                        flags,
                        hModule,
                        messageNum,
                        0,
                        buf,
                        buf.Capacity,
                        addresses);

                    if (msgLen == 0) {
                        lastError = Marshal.GetLastWin32Error();
                        if (lastError == NativeMethods.ERROR_INSUFFICIENT_BUFFER)
                            buf.Capacity = buf.Capacity * 2;
                    }
                }
            }
            catch {
                msgLen = 0;              // return empty on failure
            }
            finally  {
                for (int i=0; i<handles.Length; i++) {
                    if (handles[i].IsAllocated) handles[i].Free();
                }
                stringsRoot.Free();
            }
            
            if (msgLen > 0) {
                msg = buf.ToString();
                // chop off a single CR/LF pair from the end if there is one. FormatMessage always appends one extra.
                if (msg.Length > 1 && msg[msg.Length-1] == '\n')
                    msg = msg.Substring(0, msg.Length-2);
            }

            return msg;
        }
Exemplo n.º 3
0
 public static unsafe extern int FormatMessage(int dwFlags, SafeLibraryHandle lpSource, uint dwMessageId,
                                               int dwLanguageId, StringBuilder lpBuffer, int nSize, IntPtr[] arguments);
Exemplo n.º 4
0
        // Format message in specific DLL. Return <null> on failure.
        internal static string TryFormatMessage(SafeLibraryHandle hModule, uint messageNum, string[] insertionStrings) {

            if (insertionStrings.Length == 0) {
                // UnsafeTryFromatMessage will set FORMAT_MESSAGE_IGNORE_INSERTS when calling into the OS 
                // when there are no insertion strings, in this case we don't have to guard against insertionStrings
                // not having enough data since it is unused when FORMAT_MESSAGE_IGNORE_INSERTS is specified
                return UnsafeTryFormatMessage(hModule, messageNum, insertionStrings);
            }

            // If you pass in an empty array UnsafeTryFormatMessage will just pull out the message.
            string formatString = UnsafeTryFormatMessage(hModule, messageNum, new string[0]);

            if (formatString == null) {
                return null;
            }

            int largestNumber = 0;

            for (int i = 0; i < formatString.Length; i++) {
                if (formatString[i] == '%') {
                    // See if a number follows this, if so, grab the number.
                    if(formatString.Length > i + 1) {
                        StringBuilder sb = new StringBuilder();
                        while (i + 1 < formatString.Length && Char.IsDigit(formatString[i + 1])) {
                            sb.Append(formatString[i + 1]);
                            i++;
                        }

                        // move over the non number character that broke us out of the loop
                        i++;

                        if (sb.Length > 0) {
                            int num = -1;
                            if (Int32.TryParse(sb.ToString(), NumberStyles.None, CultureInfo.InvariantCulture, out num)) {
                                largestNumber = Math.Max(largestNumber, num);
                            }
                        }
                    }
                }
            }

            // Replacement strings are 1 indexed.
            if (largestNumber > insertionStrings.Length) {
                string[] newStrings = new string[largestNumber];
                Array.Copy(insertionStrings, newStrings, insertionStrings.Length);
                for (int i = insertionStrings.Length; i < newStrings.Length; i++) {
                    newStrings[i] = "%" + (i + 1);
                }

                insertionStrings = newStrings;
            }

            return UnsafeTryFormatMessage(hModule, messageNum, insertionStrings);
        }
 internal static extern int LoadString(SafeLibraryHandle handle, int id, StringBuilder buffer, int bufferLength);