Неспособность создать объект высота COM на Windows Seven
Вопрос
Я разрабатываю COM Surrogate Объект в 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 (такое, что регистрация автоматизирована). Работает, но проблема в том, что я не могу передавать указатель Fundle к генерируемому MIDL-прототипу функции.
Я пытался передать это, используя ВАРИАНТ тип:
v.vt = VT_PTR;
void (*myptr)(void);
myptr = &DoTheStuff;
v.byref = myptr;
hr = theElevated->CoTaskExecuter(0, v);
В результате я получаю «неверный тип аргумента».
Может ли кто-нибудь пролить свет на эту тему? Возможно, что я пытаюсь достичь, невозможен дизайн?
Нет правильного решения
Другие советы
Я считаю, что проблемы, которые вы испытываете дизайном, и что намерение улучшения безопасности окна помогло избежать потенциальных рисков безопасности.
Microsoft действительно не хочет, чтобы вы подняли свои привилегии, если он может остановить вас от этого. Выполнение произвольных функций в качестве привилегированного пользователя не должно быть легко, если Windows даже прилично защищенная система. Возможно, вы могли бы попробовать олицетворящую другой пользователь, используя токены и получить лучший доступ таким образом, но даже тогда это будет растягиваться. Если я помню правильно, пользовательские прималы даже не гарантируют, что вы получите полный доступ. Лучшее решение в этом случае - просто использовать учетную запись Super User и правильно запросить правильные привилегии.