{"record":{"id":"ac03366ea8a4f930","repo":"BCUninstaller/Bulk-Crap-Uninstaller","slug":"icon-handle-must-not-be-zero","errorCode":null,"errorMessage":"Icon handle must not be zero","messagePattern":"Icon handle must not be zero","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"source/KlocTools/Tools/DrawingTools.cs","lineNumber":65,"sourceCode":"\n                var iconPath = new StringBuilder(260);\n                iconPath.Append(filePath);\n                \n                var index = 0;\n                var handle = SafeNativeMethods.ExtractAssociatedIcon(new HandleRef(null, IntPtr.Zero), iconPath, ref index);\n                if (handle != IntPtr.Zero)\n                    return CreateOwnedIconFromHandle(handle);\n            }\n            return null;\n        }\n\n        /// <summary>\n        /// Clone an icon handle into a managed icon instance and release the original native handle.\n        /// </summary>\n        public static Icon CreateOwnedIconFromHandle(IntPtr handle)\n        {\n            if (handle == IntPtr.Zero)\n                throw new ArgumentException(\"Icon handle must not be zero\", nameof(handle));\n\n            try\n            {\n                using (var temporaryIcon = Icon.FromHandle(handle))\n                {\n                    return (Icon)temporaryIcon.Clone();\n                }\n            }\n            finally\n            {\n                SafeNativeMethods.DestroyIcon(handle);\n            }\n        }\n\n\n        /// <summary>\n        /// This class suppresses stack walks for unmanaged code permission. \n        /// (System.Security.SuppressUnmanagedCodeSecurityAttribute is applied to this class.) ","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/BCUninstaller/Bulk-Crap-Uninstaller/blob/608321de98e92297377b1eb69029af55c25504a1/source/KlocTools/Tools/DrawingTools.cs#L47-L83","documentation":"Thrown by DrawingTools.CreateOwnedIconFromHandle(IntPtr handle) when handle == IntPtr.Zero. The method clones the native icon into a managed Icon and then always calls DestroyIcon on the handle in a finally block, so passing zero would both be meaningless and would leak/destroy an invalid handle; it fails fast with ArgumentException(nameof(handle)).","triggerScenarios":"Passing IntPtr.Zero (a sentinel for 'no icon') into CreateOwnedIconFromHandle instead of checking first. Common after ExtractIcon/LoadImage return zero on failure.","commonSituations":"Calling the API after a native icon-extraction call that returned zero (file has no associated icon, missing resource, wrong type), or forwarding an uninitialised IntPtr.","solutions":["Check for IntPtr.Zero before calling and skip/null-return instead.","Use the calling code's own guard (the snippet already shows the caller does `if (handle != IntPtr.Zero) return CreateOwnedIconFromHandle(handle);`).","Log why the source extraction returned zero (bad file path, missing resource) and handle upstream."],"exampleFix":"// before\nvar icon = DrawingTools.CreateOwnedIconFromHandle(h); // h may be Zero\n\n// after\nIcon icon = h == IntPtr.Zero ? null : DrawingTools.CreateOwnedIconFromHandle(h);","handlingStrategy":"validation","validationCode":"Icon icon = handle == IntPtr.Zero ? null : DrawingTools.CreateOwnedIconFromHandle(handle);","typeGuard":"static bool IsValidIconHandle(IntPtr h) => h != IntPtr.Zero;","tryCatchPattern":null,"preventionTips":["Always test native icon-extraction results for IntPtr.Zero before forwarding.","Treat zero as 'no icon' and return null upstream rather than throwing.","Log the source of zero handles (missing file/resource) for diagnosis."],"tags":["interop","drawing","icons","validation","csharp","kloctools"],"backgroundTag":null,"analyzedSha":"608321de98e92297377b1eb69029af55c25504a1","analyzedAt":"2026-08-13T12:17:35.389Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}