14

私はC でCOM サロゲートオブジェクトを開発しています。これは、管理者権限を必要とする特定のアクションに対して、アプリケーションで UAC 昇格ダイアログを呼び出すために使用されます。

計画は、これを、可変数の引数を持つ関数へのポインターを取り、別のコンテキストで実行する関数をエクスポートすることです。このようにして、アプリケーションはこのオブジェクトを使用して、管理者権限でいくつかのアクションを実行できます。必要なのは、そのオブジェクトを使用して、その権限で実行する必要がある関数へのポインターを渡すことだけです。

これは部分的に機能し、 CoCreateInstanceの呼び出しは正常に行われ、関数ポインターが渡され、関数が実行されます。

しかし、COM Elevation Moniker アーカイブと Microsoft のCoCreateInstanceAsAdminのサンプル コードを使用してこのオブジェクトのインスタンスを作成すると、問題が発生します。

コードは次のとおりです。

HRESULT CoCreateInstanceAsAdmin(HWND hwnd, REFCLSID rclsid, REFIID riid, __out void ** ppv)
{
 // Manual implementation of CreateInstanceAsAdmin
 CComPtr<IBindCtx> BindCtx;
 HRESULT hr = CreateBindCtx(0,&BindCtx);
 BIND_OPTS3 bo;
 memset(&bo, 0, sizeof(bo));
 bo.cbStruct = sizeof(bo);
 bo.grfMode = STGM_READWRITE;
 bo.hwnd = hwnd;
 bo.dwClassContext = CLSCTX_LOCAL_SERVER;
 hr = BindCtx->SetBindOptions(&bo);
 if (SUCCEEDED(hr))
 {
  // Use the passed in CLSID to help create the COM elevation moniker string
  CComPtr<IMoniker> Moniker;
  WCHAR wszCLSID[50];
  WCHAR wszMonikerName[300];
  StringFromGUID2(rclsid,wszCLSID,sizeof(wszCLSID) / sizeof(wszCLSID[0]));
  //Elevation:Administrator!new
  hr = StringCchPrintfW(wszMonikerName, sizeof(wszMonikerName)/sizeof(wszMonikerName[0]), L"Elevation:Administrator!new:%s", wszCLSID);
  if (SUCCEEDED(hr))
  {
   // Create the COM elevation moniker
   ULONG ulEaten = 0;
   ULONG ulLen = (ULONG)wcslen(wszMonikerName);
   LPBC pBindCtx = BindCtx.p;
   hr = MkParseDisplayName(pBindCtx,wszMonikerName,&ulEaten,&Moniker);
   if (SUCCEEDED(hr) && ulEaten == ulLen)
   {
    // Use passed in reference to IID to bind to the object
    IDispatch * pv = NULL;
    hr = Moniker->BindToObject(pBindCtx,NULL,riid,ppv);
   }
  }
 }
 return hr;
}

CoCreateInstanceAsAdminの呼び出しが「クラスが登録されていません」で失敗する。

オブジェクトは、次のレジストリ キーを作成することによって登録されます (ここに REG ファイルの本体があります)。


[HKEY_CLASSES_ROOT\COMsurrogate]
@="COMsurrogate Class"

[HKEY_CLASSES_ROOT\COMsurrogate\CurVer]
@="COMsurrogate.1"

[HKEY_CLASSES_ROOT\COMsurrogate\CLSID]
@="{686B6F70-06AE-4dfd-8C26-4564684D9F9F}"

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}]
@="COMsurrogate Class"
"LocalizedString"="@C:\\Windows\\system32\\COMsurrogate.dll,-101"
"DllSurrogate"=""

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}\ProgID]
@="COMsurrogate.1"

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}\VersionIndependentProgID]
@="COMsurrogate"

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}\InprocServer32]
@="@C:\\windows\system32\COMsurrogate.dll"
"ThreadingModel"="Apartment"

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}\NotInsertable]

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}\Programmable]

いくつかのレジストリ エントリが欠落していると思われます。これが、エラー メッセージを読んでたどり着いた結論です。ただし、このレジストリ キーのリストは、MSDN や他のサイトのドキュメントを調べた後に編集されたものです。

私がこれを解決しようとしたことの1つは、ATLを介して実装することです(登録が自動化されるように)。これは機能しますが、問題は、MIDL で生成された関数プロトタイプに関数ポインターを渡すことができないことです。

VARIANT型を使用して渡そうとしました:


 v.vt = VT_PTR;
 void (*myptr)(void);
 myptr = &DoTheStuff;
 v.byref = myptr;
 hr = theElevated->CoTaskExecuter(0, v);

その結果、「無効な引数の型」が表示されます。

誰かがこの主題に光を当てることができますか? おそらく、私が達成しようとしていることは設計上不可能ですか?

4

2 に答える 2