private unsafe void OnGetTypeConverterAndTypeEditor(Com2PropertyDescriptor sender, GetTypeConverterAndTypeEditorEvent gveevent)
        {
            if (sender.TargetObject is Ole32.IPerPropertyBrowsing ppb)
            {
                bool hasStrings = false;

                // check for enums
                var caStrings = new Ole32.CA_STRUCT();
                var caCookies = new Ole32.CA_STRUCT();

                HRESULT hr = HRESULT.S_OK;
                try
                {
                    hr = ppb.GetPredefinedStrings(sender.DISPID, &caStrings, &caCookies);
                }
                catch (ExternalException ex)
                {
                    hr = (HRESULT)ex.ErrorCode;
                    Debug.Fail("An exception occurred inside IPerPropertyBrowsing::GetPredefinedStrings(dispid=" + sender.DISPID + "), object type=" + new ComNativeDescriptor().GetClassName(ppb) + ".  This is caused by an exception (usually an AV) inside the object being browsed, and is not a problem in the properties window.");
                }

                // Terminate the existing editor if we created the current one
                // so if the items have disappeared, we don't hold onto the old
                // items.
                if (gveevent.TypeConverter is Com2IPerPropertyEnumConverter)
                {
                    gveevent.TypeConverter = null;
                }

                if (hr != HRESULT.S_OK)
                {
                    hasStrings = false;
                }
                else
                {
                    hasStrings = true;
                }

                if (hasStrings)
                {
                    OleStrCAMarshaler stringMarshaler = new OleStrCAMarshaler(caStrings);
                    Int32CAMarshaler  intMarshaler    = new Int32CAMarshaler(caCookies);

                    if (stringMarshaler.Count > 0 && intMarshaler.Count > 0)
                    {
                        gveevent.TypeConverter = new Com2IPerPropertyEnumConverter(new Com2IPerPropertyBrowsingEnum(sender, this, stringMarshaler, intMarshaler, true));
                    }
                    else
                    {
                        //hasStrings = false;
                    }
                }

                // if we didn't get any strings, try the proppage edtior
                //
                if (!hasStrings)
                {
                    // this is a _bit_ of a backwards-compat work around...
                    // many older ActiveX controls will show a property page
                    // for all properties since the old grid would only put up the
                    // [...] button for "(Custom)".  If we have a conversion editor,
                    // don't allow this to override it...
                    //
                    if (sender.ConvertingNativeType)
                    {
                        return;
                    }

                    Guid g = GetPropertyPageGuid(ppb, sender.DISPID);

                    if (!Guid.Empty.Equals(g))
                    {
                        gveevent.TypeEditor = new Com2PropertyPageUITypeEditor(sender, g, (UITypeEditor)gveevent.TypeEditor);
                    }
                }
            }
        }
            /// <summary>
            ///  Called externally to update the editor or type converter.
            ///  This simply sets flags so this will happen, it doesn't actually to the update...
            ///  we wait and do that on-demand for perf.
            /// </summary>
            internal unsafe void UpdateTypeConverterAndTypeEditorInternal(bool force, Ole32.DispatchID dispid)
            {
                // check to see if we're being forced here or if the work really
                // needs to be done.
                //
                if (GetFlag(FlagUpdatedEditorAndConverter) && !force)
                {
                    return;
                }

                if (owner.GetOcx() == null)
                {
                    return;
                }

                try
                {
                    Ole32.IPerPropertyBrowsing ppb = owner.GetPerPropertyBrowsing();

                    if (ppb != null)
                    {
                        bool hasStrings = false;

                        // check for enums
                        var caStrings = new Ole32.CA_STRUCT();
                        var caCookies = new Ole32.CA_STRUCT();

                        HRESULT hr = HRESULT.S_OK;
                        try
                        {
                            hr = ppb.GetPredefinedStrings(dispid, &caStrings, &caCookies);
                        }
                        catch (ExternalException ex)
                        {
                            hr = (HRESULT)ex.ErrorCode;
                            Debug.Fail("An exception occurred inside IPerPropertyBrowsing::GetPredefinedStrings(dispid=" +
                                       dispid + "), object type=" + new ComNativeDescriptor().GetClassName(ppb));
                        }

                        if (hr != HRESULT.S_OK)
                        {
                            hasStrings = false;
                            // Destroy the existing editor if we created the current one
                            // so if the items have disappeared, we don't hold onto the old
                            // items.
                            if (converter is Com2EnumConverter)
                            {
                                converter = null;
                            }
                        }
                        else
                        {
                            hasStrings = true;
                        }

                        if (hasStrings)
                        {
                            OleStrCAMarshaler stringMarshaler = new OleStrCAMarshaler(caStrings);
                            Int32CAMarshaler  intMarshaler    = new Int32CAMarshaler(caCookies);

                            if (stringMarshaler.Count > 0 && intMarshaler.Count > 0)
                            {
                                if (converter == null)
                                {
                                    converter = new AxEnumConverter(this, new AxPerPropertyBrowsingEnum(this, owner, stringMarshaler, intMarshaler, true));
                                }
                                else if (converter is AxEnumConverter)
                                {
                                    ((AxEnumConverter)converter).RefreshValues();
                                    if (((AxEnumConverter)converter).com2Enum is AxPerPropertyBrowsingEnum axEnum)
                                    {
                                        axEnum.RefreshArrays(stringMarshaler, intMarshaler);
                                    }
                                }
                            }
                            else
                            {
                                //hasStrings = false;
                            }
                        }
                        else
                        {
                            // if we didn't get any strings, try the proppage edtior
                            //
                            // Check to see if this is a property that we have already massaged to be a
                            // .Net type. If it is, don't bother with custom property pages. We already
                            // have a .Net Editor for this type.
                            //
                            ComAliasNameAttribute comAlias = (ComAliasNameAttribute)baseProp.Attributes[typeof(ComAliasNameAttribute)];
                            if (comAlias == null)
                            {
                                Guid g = GetPropertyPage(dispid);

                                if (!Guid.Empty.Equals(g))
                                {
                                    editor = new AxPropertyTypeEditor(this, g);

                                    // Show any non-browsable property that has an editor through a
                                    // property page.
                                    //
                                    if (!IsBrowsable)
                                    {
                                        Debug.WriteLineIf(AxPropTraceSwitch.TraceVerbose, "Making property: " + Name + " browsable because we found an editor.");
                                        AddAttribute(new BrowsableAttribute(true));
                                    }
                                }
                            }
                        }
                    }

                    SetFlag(FlagUpdatedEditorAndConverter, true);
                }
                catch (Exception e)
                {
                    Debug.WriteLineIf(AxPropTraceSwitch.TraceVerbose, "could not get the type editor for property: " + Name + " Exception: " + e);
                }
            }