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


Снижение безопасности для приемника в отдельном процессе

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

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

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

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

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

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

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

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

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

    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).