Выполнение привилегированных операций с помощью C++

Специальные клиентские приложения могут вызывать привилегированные операции. Например, приложение может позволить руководителю перезагрузить офисный компьютер, не отвечающий на запросы. С помощью инструментария управления Windows (WMI) можно выполнить привилегированную операцию, вызвав поставщик WMI для привилегированной операции.

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

Вызов поставщика для привилегированной операции

  1. Получите разрешения для клиентского процесса на выполнение привилегированной операции.

    Как правило, администратор устанавливает разрешения с помощью средств системного администрирования перед запуском процесса.

  2. Получите разрешение для процесса поставщика, чтобы включить привилегированную операцию.

    Как правило, разрешения поставщика можно задать с помощью вызова функции AdjustTokenPrivileges .

  3. Получите разрешение для клиентского процесса, чтобы включить привилегированную операцию.

    Этот шаг необходим, только если поставщик является локальным для клиента. Если клиент и поставщик существуют на одном компьютере, клиент должен специально включить привилегированную операцию, используя один из следующих методов:

    • Если процесс принадлежит клиенту, он может использовать AdjustTokenPrivileges для настройки маркера процесса перед вызовом WMI. В этом случае вам больше не нужно кодировать.
    • Если клиенту не удается получить доступ к маркеру клиента, он может использовать следующую процедуру для создания маркера потока и использовать для этого маркера AdjustTokenPrivileges .

В следующей процедуре описывается, как создать маркер потока и использовать в этом маркере AdjustTokenPrivileges .

Создание маркера потока и использование AdjustTokenPrivileges для этого маркера

  1. Создайте копию маркера процесса, вызвав ImpersonateSelf.

  2. Получите созданный маркер потока, вызвав GetTokenInformation.

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

  4. Получите указатель на IWbemServices.

  5. Заслойте указатель на IWbemServices с помощью вызова CoSetProxyBlanket.

  6. Повторите шаги 1–5 при каждом вызове WMI.

    Примечание

    Необходимо повторить эти действия, так как COM неправильно кэширует маркеры.

     

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

#include <wbemidl.h>

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

// Get the privileges 
// The token has been obtained outside the scope of this code sample
// ================== 
DWORD dwLen;
bool bRes;
HANDLE hToken;

// obtain dwLen
bRes = GetTokenInformation(
  hToken, 
  TokenPrivileges, 
  NULL, 
  0,
  &dwLen
); 

BYTE* pBuffer = new BYTE[dwLen];
if(pBuffer == NULL)
{
  CloseHandle(hToken);
  return WBEM_E_OUT_OF_MEMORY;
} 

bRes = GetTokenInformation(
  hToken, 
  TokenPrivileges, 
  pBuffer,     
  dwLen,        
  &dwLen
);

if (!bRes)
{
  CloseHandle(hToken);
  delete [] pBuffer;
  return WBEM_E_ACCESS_DENIED;
} 

// Iterate through all the privileges and enable them all
// ====================================================== 
TOKEN_PRIVILEGES* pPrivs = (TOKEN_PRIVILEGES*)pBuffer;
for (DWORD i = 0; i < pPrivs->PrivilegeCount; i++)
{
  pPrivs->Privileges[i].Attributes |= SE_PRIVILEGE_ENABLED;
} 
// Store the information back in the token
// ========================================= 
bRes = AdjustTokenPrivileges(
  hToken, 
  FALSE, 
  pPrivs, 
  0, NULL, NULL
);

delete [] pBuffer;
CloseHandle(hToken); 

if (!bRes)
  return WBEM_E_ACCESS_DENIED;
else
  return WBEM_S_NO_ERROR;