List <IScanItem> VerifyFilterClassID(string extension, string classID)
        {
            List <string> interfaces = new List <string>(new string[] {
                "{89BCB740-6119-101A-BCB7-00DD010655AF}" // IFilter
            });
            List <IScanItem> rv = new List <IScanItem>();

            int[] bitnessList = new int[] { 32, 64 };

            foreach (int bitness in bitnessList)
            {
                Dictionary <string, uint> verify = host.VerifyCOMClassID(classID, interfaces, bitness);
                if (verify["_exitcode"] != 0)
                {
                    IScanItem item = new DefaultScanItem(extension);
                    item.Properties["Severity"]    = "Critical";
                    item.Properties["Description"] = "There was an unexpected error checking filter class " + FormatClassID(classID) + ". Error code: " + verify["_exitcode"].ToString("x");
                    rv.Add(item);
                }
                else if (verify[classID] == 0x80040154)
                {
                    IScanItem item = new DefaultScanItem(extension);
                    item.Properties["Severity"]    = "Error";
                    item.Properties["Description"] = "Filter class " + FormatClassID(classID) + " is not registered for " + bitness + "bit applications.";
                    rv.Add(item);
                }
                else if (verify[classID] != 0)
                {
                    IScanItem item = new DefaultScanItem(extension);
                    item.Properties["Severity"]    = "Error";
                    item.Properties["Description"] = "Filter class " + FormatClassID(classID) + " is not correctly registered for " + bitness + "bit applications. Error code: " + FormatHResult(verify[classID]);
                    rv.Add(item);
                }
                else
                {
                    foreach (string intf in interfaces)
                    {
                        if (!verify.ContainsKey(intf))
                        {
                            IScanItem item = new DefaultScanItem(extension);
                            item.Properties["Severity"]    = "Critical";
                            item.Properties["Description"] = "There was an unexpected error checking filter class " + FormatClassID(classID) + " for interface " + FormatClassID(intf) + " for " + bitness + "bit applications.";
                            rv.Add(item);
                        }
                        else if (verify[intf] != 0)
                        {
                            IScanItem item = new DefaultScanItem(extension);
                            item.Properties["Severity"]    = "Error";
                            item.Properties["Description"] = "Filter class " + FormatClassID(classID) + " is not correctly registered for " + bitness + "bit applications. Error code for " + FormatClassID(intf) + ": " + FormatHResult(verify[intf]);
                            rv.Add(item);
                        }
                    }
                }
            }

            return(rv);
        }
        List <IScanItem> VerifyPersistentHandlerClassID(string extension, string classID)
        {
            List <IScanItem> rv = new List <IScanItem>();

            if (GetDefaultValueFromKey(@"SOFTWARE\Classes\CLSID\" + classID).Length == 0)
            {
                IScanItem item = new DefaultScanItem(extension);
                item.Properties["Severity"]    = "Error";
                item.Properties["Description"] = "Persistent handler class " + FormatClassID(classID) + " is not registered for " + host.Bitness + "bit applications.";
                rv.Add(item);
            }

            return(rv);
        }
        public List <IScanItem> Process()
        {
            List <IScanItem> rv        = new List <IScanItem>();
            string           extension = extensions.Dequeue();
            DefaultScanItem  item;

            current++;

            if ((current == 1) && (disabledExtensions == null))
            {
                item = new DefaultScanItem("Windows Search Service");
                item.Properties["Severity"]    = "Warning";
                item.Properties["Description"] = "Administrator rights are required to read the enabled extension list. All extensions will be assumed to be enabled.";
                rv.Add(item);
            }

            ProcessExtensionFor(extension, rv);

            return(rv);
        }
        public List <IScanItem> Process()
        {
            var             rv        = new List <IScanItem>();
            var             action    = actions.Dequeue();
            var             extension = action as DirectShowExtension;
            var             codec     = action as DirectShowCodec;
            DefaultScanItem item;

            current++;

            if (extension != null)
            {
                if (extension.Extension.StartsWith("."))
                {
                    using (var key = Microsoft.Win32.Registry.ClassesRoot) {
                        foreach (var prefix in prefixes)
                        {
                            using (var filterKey = key.OpenSubKey(prefix.Value + @"CLSID\" + extension.SourceFilter)) {
                                if (filterKey == null)
                                {
                                    item = new DefaultScanItem(extension.Extension);
                                    item.Properties["Severity"]    = "Warning";
                                    item.Properties["Description"] = "Associated DirectShow source filter " + FormatClassID(extension.SourceFilter) + " is not registered for " + prefix.Key + "bit applications.";
                                    rv.Add(item);
                                }
                            }
                        }
                    }
                }
                else
                {
                    item = new DefaultScanItem(extension.Extension);
                    item.Properties["Severity"]    = "Warning";
                    item.Properties["Description"] = "Association with DirectShow source filter " + FormatClassID(extension.SourceFilter) + @" is incorrect. The registration at <HKCR\Media Type\Extensions> has no preceeding '.'.";
                    rv.Add(item);
                }
            }
            if (codec != null)
            {
                using (var key = Microsoft.Win32.Registry.ClassesRoot) {
                    foreach (var prefix in prefixes)
                    {
                        using (var filterKey = key.OpenSubKey(prefix.Value + @"CLSID\" + codec.ClassId)) {
                            item = new DefaultScanItem("DirectShowFilter");
                            item.Properties["Name"]    = codec.Name;
                            item.Properties["ClassID"] = codec.ClassId;
                            var categoryCodec = codec as DirectShowCategoryCodec;
                            if (categoryCodec != null)
                            {
                                item.Properties["CategoryName"]    = categoryCodec.CategoryName;
                                item.Properties["CategoryClassID"] = categoryCodec.CategoryClassId;
                            }
                            var preferredCodec = codec as DirectShowPreferredCodec;
                            if (preferredCodec != null)
                            {
                                item.Properties["Type"] = preferredCodec.Type;
                            }
                            item.Properties["Bitness"] = prefix.Key + "bit";

                            if (filterKey == null)
                            {
                                item.Properties["ItemIssue"] = "Unregistered";
                                rv.Add(item);
                            }
                            else
                            {
                                using (var filterInprocKey = filterKey.OpenSubKey("InprocServer32")) {
                                    var path = filterInprocKey.GetValue(null, null);
                                    if (path == null)
                                    {
                                        item.Properties["ItemIssue"] = "RegisteredWithoutServer";
                                        rv.Add(item);
                                        continue;
                                    }
                                    if (!File.Exists(path.ToString()))
                                    {
                                        item.Properties["ItemIssue"] = "RegisteredServerNotOnDisk";
                                        item.Properties["ItemPath"]  = path.ToString();
                                        rv.Add(item);
                                        continue;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(rv);
        }
        List <IScanItem> VerifyPropertyClassID(string extension, string classID, long bitness)
        {
            Dictionary <string, string> interfaces = new Dictionary <string, string>();

            interfaces.Add("IPropertyStore", "{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}");        // Windows Vista
            //interfaces.Add("IShellExtInit", "{000214E8-0000-0000-C000-000000000046}"); // Windows XP
            interfaces.Add("IInitializeWithFile", "{B7D14566-0509-4CCE-A71F-0A554233BD9B}");   // Windows Vista
            interfaces.Add("IInitializeWithItem", "{7F73BE3F-FB79-493C-A6C7-7EE14E245841}");   // Windows Vista
            interfaces.Add("IInitializeWithStream", "{B824B49D-22AC-4161-AC8A-9916E8FA3F7F}"); // Windows Vista
            List <IScanItem> rv = new List <IScanItem>();

            classID = classID.ToUpper();

            Dictionary <string, uint> verify = host.VerifyCOMClassID(classID, new List <string>(interfaces.Values), bitness);

            // Check for the entire verify failing for some reason (e.g. COM Checker is missing).
            if (verify["_exitcode"] != 0)
            {
                IScanItem item = new DefaultScanItem(extension);
                item.Properties["Severity"]    = "Critical";
                item.Properties["Description"] = "There was an unexpected error checking property handler class " + FormatClassID(classID) + ". Error code: " + FormatHResult(verify["_exitcode"]);
                rv.Add(item);
                return(rv);
            }

            // Map verify data to our list of interfaces.
            interfaces.Add("class", classID);
            Dictionary <string, uint> resultCodes = new Dictionary <string, uint>();

            foreach (KeyValuePair <string, string> intf in interfaces)
            {
                if (verify.ContainsKey(intf.Value))
                {
                    resultCodes[intf.Key] = verify[intf.Value];
                }
                else
                {
                    resultCodes[intf.Key] = 0xFFFFFFFF;
                }
            }

            // Check for unregistered classes specially.
            if (resultCodes["class"] == 0x80040154)
            {
                IScanItem item = new DefaultScanItem(extension);
                item.Properties["Severity"]    = "Error";
                item.Properties["Description"] = "Property handler class " + FormatClassID(classID) + " is not registered for " + bitness + "bit applications.";
                rv.Add(item);
                return(rv);
            }

            // Other error with instanciating the class.
            if (resultCodes["class"] != 0x00000000)
            {
                IScanItem item = new DefaultScanItem(extension);
                item.Properties["Severity"]    = "Error";
                item.Properties["Description"] = "There was an error checking property handler class " + FormatClassID(classID) + ". Error code: " + FormatHResult(resultCodes["class"]);
                rv.Add(item);
                return(rv);
            }

            // Check each interface was successfully checked and report any errors with checking or with QI.
            foreach (KeyValuePair <string, string> intf in interfaces)
            {
                if (!verify.ContainsKey(intf.Value))
                {
                    IScanItem item = new DefaultScanItem(extension);
                    item.Properties["Severity"]    = "Critical";
                    item.Properties["Description"] = "There was an unexpected error checking property handler class " + FormatClassID(classID) + " for interface " + FormatClassID(intf.Value) + " for " + bitness + "bit applications.";
                    rv.Add(item);
                }
                if ((intf.Key != "class") && (resultCodes[intf.Key] != 0x00000000) && (resultCodes[intf.Key] != 0x80004002))
                {
                    IScanItem item = new DefaultScanItem(extension);
                    item.Properties["Severity"]    = "Error";
                    item.Properties["Description"] = "Property handler class " + FormatClassID(classID) + " fails when QIed to '" + intf.Key + "' (" + FormatHResult(resultCodes[intf.Key]) + ") for " + bitness + "bit applications.";
                    rv.Add(item);
                }
            }

            // All the verify work succeeded, check the class implements what it is supposed to.
            if (resultCodes["IPropertyStore"] != 0)
            {
                IScanItem item = new DefaultScanItem(extension);
                item.Properties["Severity"]    = "Error";
                item.Properties["Description"] = "Property handler class " + FormatClassID(classID) + " does not implement 'IPropertyStore' (" + FormatHResult(resultCodes["IPropertyStore"]) + ") for " + bitness + "bit applications.";
                rv.Add(item);
            }
            else
            {
                bool initOK = (resultCodes["IInitializeWithFile"] == 0) || (resultCodes["IInitializeWithItem"] == 0) || (resultCodes["IInitializeWithStream"] == 0);
                if (!initOK)
                {
                    IScanItem item = new DefaultScanItem(extension);
                    item.Properties["Severity"]    = "Error";
                    item.Properties["Description"] = "Property handler class " + FormatClassID(classID) + " does not implement 'IInitializeWithFile', 'IInitializeWithItem' or 'IInitializeWithStream' for " + bitness + "bit applications.";
                    rv.Add(item);
                }
            }

            return(rv);
        }
        void ProcessExtensionFor(string extension, List <IScanItem> rv)
        {
            DefaultScanItem item;

            //string prefix = "";
            //if (disabledExtensions != null) {
            //	if (disabledExtensions.Contains(extension)) {
            //		prefix = "[Off] ";
            //	} else {
            //		prefix = "[On] ";
            //	}
            //}

            while (true)
            {
                {
                    string persistHandler = GetPersistentHandler(extension);
                    if (persistHandler.Length > 0)
                    {
                        rv.AddRange(VerifyPersistentHandlerClassID(extension, persistHandler));
                    }
                    string iFilterClass = GetIFilterFromPersistentHandler(persistHandler);
                    if (iFilterClass.Length > 0)
                    {
                        rv.AddRange(VerifyFilterClassID(extension, iFilterClass));
                        break;
                    }
                }
                {
                    string contentType    = GetValueFromKey(@"SOFTWARE\Classes\" + extension, "Content Type");
                    string classID        = GetValueFromKey(@"SOFTWARE\Classes\MIME\Database\Content Type\" + contentType, "CLSID");
                    string persistHandler = GetPersistentHandler(classID);
                    if (persistHandler.Length > 0)
                    {
                        rv.AddRange(VerifyPersistentHandlerClassID(extension, persistHandler));
                    }
                    string iFilterClass = GetIFilterFromPersistentHandler(persistHandler);
                    if (iFilterClass.Length > 0)
                    {
                        rv.AddRange(VerifyFilterClassID(extension, iFilterClass));
                        break;
                    }
                }
                {
                    string handlerName    = GetDefaultValueFromKey(@"SOFTWARE\Classes\" + extension);
                    string classID        = GetDefaultValueFromKey(@"SOFTWARE\Classes\" + handlerName + @"\CLSID");
                    string persistHandler = GetPersistentHandler(classID);
                    if (persistHandler.Length > 0)
                    {
                        rv.AddRange(VerifyPersistentHandlerClassID(extension, persistHandler));
                    }
                    string iFilterClass = GetIFilterFromPersistentHandler(persistHandler);
                    if (iFilterClass.Length > 0)
                    {
                        rv.AddRange(VerifyFilterClassID(extension, iFilterClass));
                        break;
                    }
                }

                break;
            }

            if (host.Bitness < 64)
            {
                string propertyHandler32 = GetDefaultValueFromKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\PropertySystem\PropertyHandlers\" + extension);
                if (propertyHandler32 != "")
                {
                    rv.AddRange(VerifyPropertyClassID(extension, propertyHandler32, 32));
                }
            }
            else
            {
                string propertyHandler64 = GetDefaultValueFromKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\PropertySystem\PropertyHandlers\" + extension);
                string propertyHandler32 = GetDefaultValueFromKey(@"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\PropertySystem\PropertyHandlers\" + extension);
                if ((propertyHandler64 != "") && (propertyHandler32 != "") && (propertyHandler64 != propertyHandler32))
                {
                    item = new DefaultScanItem(extension);
                    item.Properties["Severity"]    = "Warning";
                    item.Properties["Description"] = "Property handle for 64bit (" + FormatClassID(propertyHandler64) + ") is different from 32bit (" + FormatClassID(propertyHandler32) + ").";
                    rv.Add(item);
                }
                if (propertyHandler64 != "")
                {
                    rv.AddRange(VerifyPropertyClassID(extension, propertyHandler64, 64));
                }
                if (propertyHandler32 != "")
                {
                    rv.AddRange(VerifyPropertyClassID(extension, propertyHandler32, 32));
                }
            }
        }