Поделиться через


Понижение уровня безопасности узла приёма в отдельном процессе

Инструментарий управления Windows (WMI) может создать приемник для получения асинхронных обратных вызовов для клиентского приложения в отдельном процессе. Отдельный процесс Unsecapp.exe. Используйте интерфейс IWbemUnsecuredApartment. IWbemUnsecuredApartment позволяет контролировать, авторизует ли Unsecapp.exe обратные вызовы в приемник. Дополнительные сведения см. в разделе Настройка безопасности для асинхронного вызова.

Затем можно снизить безопасность этого процесса, а WMI может получить доступ к приемнику без ограничений. В целях поддержки данной техники WMI предоставляет процесс Unsecapp.exe для функционирования в качестве отдельного процесса. Вы можете разместить Unsecapp.exe, вызвав интерфейс IUnsecuredApartment.

Интерфейс IUnsecuredApartment позволяет клиентскому приложению создать отдельный процесс, специально выделенный и работающий Unsecapp.exe для размещения реализации IWbemObjectSink. Выделенный процесс может вызывать CoInitializeSecurity, чтобы предоставить WMI-доступ к выделенному процессу без ущерба для безопасности основного процесса. После инициализации выделенный процесс выступает в качестве посредника между основным процессом и WMI.

В следующей процедуре описывается выполнение асинхронного вызова с IUnsecuredApartment.

Выполнить асинхронный вызов с помощью IUnsecuredApartment

  1. Создайте выделенный процесс с вызовом CoCreateInstance.

    В следующем примере кода вызывается CoCreateInstance для создания выделенного процесса.

    IUnsecuredApartment* pUnsecApp = NULL;
    
    CoCreateInstance(CLSID_UnsecuredApartment, NULL, 
      CLSCTX_LOCAL_SERVER, IID_IUnsecuredApartment, 
      (void**)&pUnsecApp);
    
  2. Создайте экземпляр объекта sink.

    В следующем примере кода создается новый объект приемника.

    CMySink* pSink = new CMySink;
    pSink->AddRef();
    
  3. Создайте заглушку для приемника.

    Заглушка — это функция-оболочка, сгенерированная из элемента приемника.

    В следующем примере кода вызывается CreateObjectStub для создания заглушки для приемника.

    IUnknown* pStubUnk = NULL; 
    pUnsecApp->CreateObjectStub(pSink, &pStubUnk);
    
  4. Вызовите QueryInterface для оболочки и запросите указатель на интерфейс IWbemObjectSink.

    В следующем примере кода вызывается QueryInterface и запрашивается указатель на интерфейс IWbemObjectSink.

    IWbemObjectSink* pStubSink = NULL;
    pStubUnk->QueryInterface(IID_IWbemObjectSink, (void **)&pStubSink); pStubUnk->Release();
    
  5. Отпустите указатель объекта-поглотителя.

    Указатель объекта можно освободить, так как заглушка теперь владеет указателем.

    В следующем примере кода освобождается указатель объекта приемника.

    pSink->Release();
    
  6. Используйте заглушку в любом асинхронном вызове.

    После завершения вызова сбросьте локальный отсчет ссылок.

    В следующем примере кода используется заглушка в асинхронном вызове.

    // pServices is an IWbemServices* object
    pServices->CreateInstanceEnumAsync(strClassName, 0, NULL, pStubSink);
    

    Иногда после вызова может потребоваться отменить асинхронный вызов. Если необходимо отменить звонок, отмените вызов с тем же указателем, который первоначально сделал звонок.

    В следующем примере кода показано, как отменить асинхронный вызов.

    pServices->CancelAsyncCall(pStubSink);
    
  7. Отпустите ссылку на локальный ресурс после завершения использования асинхронного вызова.

    Убедитесь, что указатель pStubSink освобождается только после подтверждения, что асинхронный вызов не нужно отменять. Кроме того, не выпускайте pStubSink после выпуска WMI pSink указателя приемника. Освобождение pStubSink после pSink создает циклический счетчик ссылок, в котором как приемник, так и заглушка остаются в памяти навсегда. В качестве альтернативы, возможным местом для освобождения указателя может быть вызов IWbemObjectSink::SetStatus, сделанный WMI, чтобы сообщить о завершении первоначального асинхронного вызова.

  8. По завершении деинициализируйте COM с вызовом Release().

    В следующем примере кода показано, как вызвать Release() на указателе pUnsecApp.

    pUnsecApp->Release();
    

    В примерах кода в этом разделе для правильной компиляции требуется следующая инструкция #include и ссылка.

    #include <wbemidl.h>
    #pragma comment(lib, "wbemuuid.lib")
    

Для получения дополнительной информации о функции и параметрах CoInitializeSecurity см. документацию COM в Комплекте Разработки Программного Обеспечения (SDK) для платформы.