{"record":{"id":"3244191014e1ed27","repo":"HandyOrg/HandyControl","slug":"win32exception-interopmethods","errorCode":null,"errorMessage":"Win32Exception","messagePattern":"Win32Exception","errorType":"exception","errorClass":"Win32Exception","httpStatus":null,"severity":"error","filePath":"src/Shared/HandyControl_Shared/Tools/Interop/InteropMethods.cs","lineNumber":114,"sourceCode":"\n    [DllImport(InteropValues.ExternDll.User32)]\n    internal static extern bool InsertMenu(IntPtr hMenu, int wPosition, int wFlags, int wIDNewItem, string lpNewItem);\n\n    [DllImport(InteropValues.ExternDll.User32, ExactSpelling = true, EntryPoint = \"DestroyMenu\", CharSet = CharSet.Auto)]\n    [ResourceExposure(ResourceScope.None)]\n    internal static extern bool IntDestroyMenu(HandleRef hMenu);\n\n    [SecurityCritical]\n    [SuppressUnmanagedCodeSecurity]\n    [DllImport(InteropValues.ExternDll.User32, SetLastError = true, ExactSpelling = true, EntryPoint = nameof(GetDC),\n        CharSet = CharSet.Auto)]\n    internal static extern IntPtr IntGetDC(HandleRef hWnd);\n\n    [SecurityCritical]\n    internal static IntPtr GetDC(HandleRef hWnd)\n    {\n        var hDc = IntGetDC(hWnd);\n        if (hDc == IntPtr.Zero) throw new Win32Exception();\n\n        return HandleCollector.Add(hDc, CommonHandles.HDC);\n    }\n\n    [SecurityCritical]\n    [SuppressUnmanagedCodeSecurity]\n    [DllImport(InteropValues.ExternDll.User32, ExactSpelling = true, EntryPoint = nameof(ReleaseDC), CharSet = CharSet.Auto)]\n    internal static extern int IntReleaseDC(HandleRef hWnd, HandleRef hDC);\n\n    [SecurityCritical]\n    internal static int ReleaseDC(HandleRef hWnd, HandleRef hDC)\n    {\n        HandleCollector.Remove((IntPtr) hDC, CommonHandles.HDC);\n        return IntReleaseDC(hWnd, hDC);\n    }\n\n    [SecurityCritical]\n    [SuppressUnmanagedCodeSecurity]","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/HandyOrg/HandyControl/blob/2c0875ebd67326e0c67282967e3e809c69282fee/src/Shared/HandyControl_Shared/Tools/Interop/InteropMethods.cs#L96-L132","documentation":"InteropMethods.GetDC is the shared P/Invoke wrapper around user32 GetDC. It calls IntGetDC(hWnd) and throws Win32Exception (with Marshal.GetLastWin32Error() as the error code) whenever the native call returns a null HDC. A successful HDC is registered with HandleCollector under CommonHandles.HDC so it gets released later.","triggerScenarios":"Any HandyControl code path that acquires a device context — e.g. WindowHelper DPI detection, window rendering helpers — when GetDC fails: invalid window HandleRef, GDI object quota exhausted, or no desktop available for the calling session.","commonSituations":"Session 0 / headless execution, disconnected terminal sessions, GDI handle leaks reaching the 10,000-per-process default quota, passing a destroyed window's handle.","solutions":["Check the exception's ErrorCode/NativeErrorCode to identify the exact Win32 failure (e.g. ERROR_NO_SYSTEM_RESOURCES, ERROR_INVALID_WINDOW_HANDLE).","Fix GDI handle leaks in the application (pair every GetDC with ReleaseDC; watch the GDI Objects counter in Task Manager).","Only call DC-dependent APIs from a thread in an interactive desktop session.","Wrap calls in try-catch (Win32Exception) and degrade gracefully (assume 96 DPI or skip rendering work).","If triggered by a destroyed window handle, ensure the HWND is still alive (IsWindow) before requesting its DC."],"exampleFix":"// before\nvar dc = InteropMethods.GetDC(new HandleRef(null, hwnd)); // throws Win32Exception\n\n// after\nIntPtr dc;\ntry { dc = InteropMethods.GetDC(new HandleRef(null, hwnd)); }\ncatch (Win32Exception ex)\n{\n    Log.Warn($\"GetDC failed: {ex.NativeErrorCode}\");\n    return; // degrade gracefully\n}","handlingStrategy":"try-catch","validationCode":"// check GDI headroom and window validity where possible\nbool canUse = Environment.UserInteractive; // and verify hwnd via IsWindow when not IntPtr.Zero","typeGuard":"static bool IsValidHwnd(IntPtr hwnd) => hwnd == IntPtr.Zero || InteropMethods.IsWindow(hwnd);","tryCatchPattern":"try { hdc = InteropMethods.GetDC(new HandleRef(null, hwnd)); }\ncatch (Win32Exception ex) { Log.Warn($\"GetDC failed: {ex.NativeErrorCode}\"); hdc = IntPtr.Zero; /* skip DC work */ }","preventionTips":["Pair every GetDC with a ReleaseDC; audit for GDI leaks.","Verify window handles are alive (IsWindow) before requesting DCs.","Only acquire screen DCs from interactive desktop sessions.","Log ex.NativeErrorCode to distinguish quota vs invalid-handle causes."],"tags":["win32","gdi","native-interop","handle"],"backgroundTag":"win32-api-failed","analyzedSha":"2c0875ebd67326e0c67282967e3e809c69282fee","analyzedAt":"2026-09-14T14:45:29.754Z","contentChangedAt":"2026-09-14T14:45:29.754Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}