Marcar controles ActiveX de MFC como seguros para scripting e inicialización

En este artículo se describe cómo marcar los controles ActiveX de MFC como Seguros para scripting e inicialización.

Versión original del producto: Controles ActiveX de MFC
Número de KB original: 161873

Resumen

De forma predeterminada, los controles ActiveX de MFC no se marcan como Seguros para scripting y Seguros para la inicialización. Esto se hace evidente cuando el control se ejecuta en Internet Explorer con el nivel de seguridad establecido en medio o alto. En cualquiera de estos modos, se pueden mostrar advertencias de que los datos del control no son seguros o que es posible que el control no sea seguro para que se usen scripts.

Hay dos métodos que un control puede usar para eliminar estos errores. El primero implica el control que implementa la IObjectSafety interfaz y es útil para los controles que desean cambiar su comportamiento y volverse seguros si se ejecutan en el contexto de un explorador de Internet. El segundo implica modificar la función del DllRegisterServer control para marcar el control seguro en el Registro. En este artículo se trata el segundo de estos métodos. El primer método, implementar la IObjectSafety interfaz, se trata en el SDK de cliente de Internet.

Tenga en cuenta que un control solo debe marcarse como seguro si, de hecho, es seguro. Consulte la documentación del SDK de cliente de Internet para obtener una descripción de esto. Consulte Inicialización segura y scripting para controles ActiveX en la sección Desarrollo de componentes.

Nota:

En este artículo no se explica cómo marcar un control seguro para su descarga. Para obtener más información sobre la descarga de código y la firma de código, consulte el SDK de cliente de Internet.

Más información

Siga estos pasos para marcar el control ActiveX de MFC como Seguro para scripting y Seguro para inicializar:

  1. Implemente las CreateComponentCategory funciones auxiliares y RegisterCLSIDInCategory agregando los siguientes archivos cathelp.h y cathelp.cpp al proyecto.

    • Cathelp.h

      #include "comcat.h"
      
      // Helper function to create a component category and associated
      // description
      HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription);
      
      // Helper function to register a CLSID as belonging to a component
      // category
      HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid);
      
    • Cathelp.cpp

      #include "comcat.h"
      
      // Helper function to create a component category and associated
      // description
      HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription)
      {
          ICatRegister* pcr = NULL ;
          HRESULT hr = S_OK ;
      
          hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
          NULL,
          CLSCTX_INPROC_SERVER,
          IID_ICatRegister,
          (void**)&pcr);
          if (FAILED(hr))
          return hr;
      
          // Make sure the HKCR\Component Categories\{..catid...}
          // key is registered
          CATEGORYINFO catinfo;
          catinfo.catid = catid;
          catinfo.lcid = 0x0409 ; // english
      
          // Make sure the provided description is not too long.
          // Only copy the first 127 characters if it is
          int len = wcslen(catDescription);
          if (len>127)
          len = 127;
          wcsncpy(catinfo.szDescription, catDescription, len);
          // Make sure the description is null terminated
          catinfo.szDescription[len] = '\0';
      
          hr = pcr->RegisterCategories(1, &catinfo);
          pcr->Release();
      
          return hr;
      }
      
      // Helper function to register a CLSID as belonging to a component
      // category
      HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
      {
          // Register your component categories information.
          ICatRegister* pcr = NULL ;
          HRESULT hr = S_OK ;
          hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
          NULL,
          CLSCTX_INPROC_SERVER,
          IID_ICatRegister,
          (void**)&pcr);
          if (SUCCEEDED(hr))
          {
              // Register this category as being "implemented" by
              // the class.
              CATID rgcatid[1] ;
              rgcatid[0] = catid;
              hr = pcr->RegisterClassImplCategories(clsid, 1, rgcatid);
          }
      
          if (pcr != NULL)
          pcr->Release();
      
          return hr;
      }
      
  2. Modifique para DllRegisterServer marcar el control como seguro. Busque la implementación de DllRegisterServer en un archivo .cpp en el proyecto. Tendrá que agregar varias cosas a este archivo de .cpp. Incluya el archivo que implementa CreateComponentCategory y RegisterCLSIDInCategory:

    #include "CatHelp.h"
    

    Defina el GUID asociado a las categorías de componentes de seguridad:

    const CATID CATID_SafeForScripting =
    {0x7dd95801,0x9882,0x11cf,{0x9f,0xa9,0x00,0xaa,0x00,0x6c,0x42,0xc4 }} ;
    const CATID CATID_SafeForInitializing =
    {0x7dd95802,0x9882,0x11cf,{0x9f,0xa9,0x00,0xaa,0x00,0x6c,0x42,0xc4 }} ;
    

    Defina el GUID asociado al control. Por motivos de simplicidad, puede tomar prestado el GUID de la IMPLEMENT_OLECREATE_EX macro en el archivo de .cpp principal para el control. Ajuste ligeramente el formato para que tenga un aspecto similar al siguiente:

    const GUID CDECL BASED_CODE _ctlid =
    { 0x43bd9e45, 0x328f, 0x11d0,
    { 0xa6, 0xb9, 0x0, 0xaa, 0x0, 0xa7, 0xf, 0xc2 } };
    

    Para marcar el control como Seguro para scripting e inicialización, modifique la función de la DllRegisterServer siguiente manera:

    STDAPI DllRegisterServer(void)
    {
        AFX_MANAGE_STATE(_afxModuleAddrThis);
    
        if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))
        return ResultFromScode(SELFREG_E_TYPELIB);
    
        if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
        return ResultFromScode(SELFREG_E_CLASS);
    
        if (FAILED( CreateComponentCategory(
        CATID_SafeForScripting,
        L"Controls that are safely scriptable")))
        return ResultFromScode(SELFREG_E_CLASS);
    
        if (FAILED( CreateComponentCategory(
        CATID_SafeForInitializing,
        L"Controls safely initializable from persistent data")))
        return ResultFromScode(SELFREG_E_CLASS);
    
        if (FAILED( RegisterCLSIDInCategory(
        _ctlid, CATID_SafeForScripting)))
        return ResultFromScode(SELFREG_E_CLASS);
    
        if (FAILED( RegisterCLSIDInCategory(
        _ctlid, CATID_SafeForInitializing)))
        return ResultFromScode(SELFREG_E_CLASS);
    
        return NOERROR;
    }
    

    Normalmente no modificaría la DllUnregisterServer función por estas dos razones:

    • No le gustaría quitar una categoría de componente porque otros controles pueden estar utilizándola.

    • Aunque hay una UnRegisterCLSIDInCategory función definida, de forma predeterminada DllUnregisterServer quita por completo la entrada del control del registro. Por lo tanto, la eliminación de la categoría del registro del control es de poco uso.

    Después de compilar y registrar el control, debe encontrar las siguientes entradas en el Registro:

    • HKEY_CLASSES_ROOT\Component Categories\{7DD95801-9882-11CF-9FA9-00AA006C42C4}

    • HKEY_CLASSES_ROOT\Component Categories\{7DD95802-9882-11CF-9FA9-00AA006C42C4}

    • HKEY_CLASSES_ROOT\CLSID\{"your controls GUID"}\Implemented Categories\{7DD95801-9882-11CF-9FA9-00AA006C42C4}

    • HKEY_CLASSES_ROOT\CLSID\{"your controls GUID"}\Implemented Categories\{7DD95802-9882-11CF-9FA9-00AA006C42C4}

Referencias

SDK de cliente de Internet: desarrollo de componentes: inicialización segura y scripting para controles ActiveX