私は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);
その結果、「無効な引数の型」が表示されます。
誰かがこの主題に光を当てることができますか? おそらく、私が達成しようとしていることは設計上不可能ですか?