{"record":{"id":"258f92b9968c1c37","repo":"dotnet/wpf","slug":"win32exception-hwndwrapper","errorCode":null,"errorMessage":"Win32Exception","messagePattern":"Win32Exception","errorType":"exception","errorClass":"Win32Exception","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HwndWrapper.cs","lineNumber":61,"sourceCode":"                }\n            }\n\n\n            _wndProc = new HwndWrapperHook(WndProc);\n\n            // We create the HwndSubclass object so that we can use its\n            // window proc directly.  We will not be \"subclassing\" the\n            // window we create.\n            HwndSubclass hwndSubclass = new(_wndProc);\n            \n            // Register a unique window class for this instance.\n            NativeMethods.WNDCLASSEX_D wc_d = new NativeMethods.WNDCLASSEX_D();\n\n            IntPtr hNullBrush = UnsafeNativeMethods.CriticalGetStockObject(NativeMethods.NULL_BRUSH);\n\n            if (hNullBrush == IntPtr.Zero)\n            {\n                throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());\n            }\n\n            IntPtr hInstance = UnsafeNativeMethods.GetModuleHandle( null );\n\n            // We need to keep the Delegate object alive through the call to CreateWindowEx().\n            // Subclass.WndProc will install a better delegate (to the same function) when it\n            // processes the first message.\n            // But this first delegate needs be held alive until then.\n            NativeMethods.WndProc initialWndProc = new NativeMethods.WndProc(hwndSubclass.SubclassWndProc);\n\n            // The class name is a concat of AppName, ThreadName, and RandomNumber.\n            // Register will fail if the string gets over 255 in length.\n            // So limit each part to a reasonable amount.\n            string appName;\n            string currentDomainFriendlyName = AppDomain.CurrentDomain.FriendlyName;\n            if (null != currentDomainFriendlyName && 128 <= currentDomainFriendlyName.Length)\n                appName = currentDomainFriendlyName[..128];\n            else","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HwndWrapper.cs#L43-L79","documentation":"During HwndWrapper construction the class registers a window class, first fetching the NULL_BRUSH stock object via CriticalGetStockObject. If that Win32 call returns a null handle, the wrapper throws a Win32Exception carrying the last Win32 error, since it cannot proceed to register the class without a valid brush handle.","triggerScenarios":"CriticalGetStockObject(NULL_BRUSH) returning IntPtr.Zero during HwndWrapper's constructor — an OS-level GDI failure such as GDI handle exhaustion or an uninitialized/invalid GDI environment.","commonSituations":"Processes that leaked thousands of GDI handles hitting the per-process 10,000 GDI object limit; running in stripped-down/remote/session environments where stock objects are unavailable.","solutions":["Check GDI handle usage (Task Manager > GDI Objects) and fix leaks of brushes/bitmaps/DCs in the process","Restart the process to release exhausted GDI handles","Inspect Marshal.GetLastWin32Error in the exception for the specific OS error code","Reduce GDI resource consumption (dispose HBRUSH/HBITMAP/HDC deterministically)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { var wrapper = new MyHwndWrapper(...); } catch (Win32Exception ex) { log(ex.NativeErrorCode); /* surface GDI-exhaustion to user, suggest restart */ }","preventionTips":["Monitor GDI object count (10,000 per-process limit) and fix brush/DC/bitmap leaks","Dispose GDI handles deterministically (DeleteObject/DeleteDC)","Watch for this failure after long-running sessions with heavy graphics usage"],"tags":["wpf","win32","gdi","resource-exhaustion"],"backgroundTag":"api-error-response","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}