Невозможность создать объект COM-объекта возвышения в Windows Seven

Я разрабатываю COM-суррогатный объект в C, он будет использоваться моими приложениями для вызова диалогового окна повышения UAC для определенных действий, требующих административных прав.

Планируется, чтобы это экспортировало функцию, которая принимает указатель на функцию с переменным числом аргументов и выполняет ее в другом контексте. Таким образом, приложение может использовать этот объект для выполнения некоторых действий с правами администратора, все, что им нужно сделать, это использовать этот объект и передать ему указатель на функцию, которая должна быть выполнена с указанными правами.

Это работает частично, вызов CoCreateInstance идет хорошо, передается указатель функции и выполняется моя функция. Однако, когда я создаю экземпляр этого объекта с использованием CoCreateInstanceAsAdmin, возникают проблемы; вот код:


HRESULT CoCreateInstanceAsAdmin(HWND hwnd, REFCLSID rclsid, REFIID riid, __out void ** ppv)
{
 // Manual implementation of CreateInstanceAsAdmin
 CComPtr 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 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 и других сайтах, поэтому я вполне уверен, что ничего не было пропущено.

Среди вещей, которые я пытался решить, это реализовать его с помощью ATL (например, автоматическая регистрация). Это работает, но проблема в том, что я не могу передать указатель funtion на прототип прототипа сгенерированного MIDL.

Я попытался передать его с помощью типа VARIANT:


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

в результате получается "Недопустимый тип аргумента".

Может ли кто-то пролить свет на эту тему? Возможно, то, чего я пытаюсь достичь, невозможно по дизайну?

Ответ 1

Я считаю, что проблемы, которые возникают у вас, - это дизайн и что цель улучшения безопасности окон - помочь избежать потенциальных рисков безопасности.

Ответ 2

Microsoft не хочет, чтобы вы повышали свои привилегии, если это может помешать вам сделать это. Выполнение произвольных функций в качестве привилегированного пользователя не должно быть легким, если Windows является даже прилично защищенной системой. Вы могли бы попытаться олицетворить другого пользователя, используя токены, и получить лучший доступ таким образом, но даже тогда это будет растяжкой. Если я правильно помню, пользовательские олицетворения даже не гарантируют, что вы получите полный доступ. Лучшее решение в этом случае - просто использовать учетную запись суперпользователя и правильно запросить правильные привилегии.