dotnet/wpf · error · Win32Exception

win32Error (System.ComponentModel.Win32Exception)

Error message

win32Error (System.ComponentModel.Win32Exception)

What it means

TextFindEngine.FindNLSString wraps the native FindNLSStringEx Win32 API. When the native call fails (matchIndex == -1) and Marshal.GetLastWin32Error() is non-zero, the error code is surfaced as a System.ComponentModel.Win32Exception. This means the OS-level culture-aware string search itself failed.

Solutions

  1. Catch Win32Exception and fall back to a simple String.IndexOf comparison
  2. Verify the OS supports the FindNLSStringEx flags being requested (Windows Vista+)
  3. Check the exception's NativeErrorCode against Win32 error docs to identify the exact failure
  4. Normalize culture/locale arguments passed into the find call

Example fix

// before
int idx = TextFindEngine.FindNLSString(source, flags, value);

// after
int idx;
try { idx = TextFindEngine.FindNLSString(source, flags, value); }
catch (Win32Exception ex)
{
    Trace.TraceWarning("NLS find failed: {0}", ex.NativeErrorCode);
    idx = source.IndexOf(value, StringComparison.CurrentCulture);
}
Defensive patterns

Strategy: try-catch

Try / catch

try { idx = TextFindEngine.FindNLSString(source, flags, value); } catch (System.ComponentModel.Win32Exception ex) { log(ex.NativeErrorCode); idx = source.IndexOf(value, StringComparison.CurrentCulture); }

Prevention

When it happens

Trigger: FindNLSString invoked with flags/inputs the native API rejects (e.g., invalid find flag combinations such as Bidi/diacritics handling on unsupported data), causing the P/Invoke to return -1 with a Win32 error set.

Common situations: Searching text in RichTextBox/TextRange with unusual culture settings; exotic locale data on stripped-down Windows installs; calling find helpers with flags unsupported by the running OS version.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/23990b5b5a43012e. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextFindEngine.cs:582

                    }
                }
            }

            return matchIndex;
        }

        //  Fixing method signature to meet TAS security requirements.
        private static int FindNLSString(int locale, uint flags, string sourceString, string findString, out int found)
        {
            int matchIndex = UnsafeNativeMethods.FindNLSString(locale, flags,
                                sourceString, sourceString.Length, findString, findString.Length, out found);

            if (matchIndex == -1)
            {
                int win32Error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
                if (win32Error != 0)
                {
                    throw new System.ComponentModel.Win32Exception(win32Error);
                }
            }

            return matchIndex;
        }

        // Returns true iff two matching strings continue to match when kashida are considered.
        private static bool IsKashidaMatch(string text, string pattern, CompareInfo compareInfo)
        {
            const CompareOptions options = CompareOptions.IgnoreSymbols | CompareOptions.StringSort | CompareOptions.IgnoreNonSpace;

            // Relace the Kashida char with a non-symbolic, non-diacritic constant value.
            // Kashida is ignored with the CompareOptions we use during the search.
            // When called, it's ok if the constant value matches other chars in the find pattern.
            // We've already got a match ignoring kashida.

            text = text.Replace(UnicodeArabicKashida, '0');
            pattern = pattern.Replace(UnicodeArabicKashida, '0');

View on GitHub (pinned to 81131a70a4)