C++ を使用した特権操作の実行

特別なクライアント アプリケーションが特権操作を呼び出す場合があります。 たとえば、アプリケーションは、応答しないオフィス コンピューターを再起動することをマネージャーに許可する場合があります。 Windows Management Instrumentation (WMI) を使用すると、特権操作のために WMI プロバイダーを呼び出すことで、特権操作を実行できます。

次の手順では、特権操作のためにプロバイダーを呼び出す方法について説明します。

特権操作のためにプロバイダーを呼び出すには

  1. 特権操作を実行するクライアント プロセスのアクセス許可を取得します。

    通常、管理者は、プロセスを実行する前に、システム管理ツールを使用してアクセス許可を設定します。

  2. 特権操作を有効にするプロバイダー プロセスのアクセス許可を取得します。

    通常、AdjustTokenPrivileges 関数を呼び出してプロバイダーのアクセス許可を設定できます。

  3. 特権操作を有効にするクライアント プロセスのアクセス許可を取得します。

    この手順は、プロバイダーがクライアントに対してローカルである場合にのみ必要です。 クライアントとプロバイダーが同じコンピューター上に存在する場合、クライアントは、次のいずれかの手法を使用して、特権操作を明示的に有効にする必要があります。

    • クライアントがプロセスを所有している場合、クライアントは、AdjustTokenPrivileges を使用して、WMI を呼び出す前にプロセス トークンを調整できます。 この場合、これ以上コーディングする必要はありません。
    • クライアントがクライアント トークンにアクセスできない場合、クライアントは、次の手順を使用してスレッド トークンを作成し、そのトークンで AdjustTokenPrivileges を使用することができます。

次の手順では、スレッド トークンを作成し、そのトークンで AdjustTokenPrivileges を使用する方法について説明します。

スレッド トークンを作成し、そのトークンで AdjustTokenPrivileges を使用するには

  1. ImpersonateSelf を呼び出して、プロセス トークンのコピーを作成します。

  2. GetTokenInformation を呼び出して、新しく作成されたスレッド トークンを取得します。

  3. 新しいトークンで AdjustTokenPrivileges を呼び出して特権操作を有効にします。

  4. IWbemServices へのポインターを取得します。

  5. CoSetProxyBlanket を呼び出して IWbemServices へのポインターをクロークします。

  6. WMI への各呼び出しで手順 1 から 5 を繰り返します。

    注意

    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;