Я создал локальный COM-сервер, который требует возвышения и должен быть создан изнутри невыполненного процесса.COM Elevation Moniker не может поднять сервер под Vista/Windows 7
Используя MSDN's article on the COM elevation moniker, я настроил класс сервера, следуя указанным требованиям. Сервер был успешно зарегистрирован в ульке HKLM.
Пример кода:
procedure CoCreateInstanceAsAdmin(const Handle: HWND;
const ClassID, IID: TGuid; PInterface: PPointer);
var
rBindOpts: TBindOpts3;
sMonikerName: WideString;
iRes: HRESULT;
begin
ZeroMemory(@rBindOpts, Sizeof(TBindOpts3));
rBindOpts.cbStruct := Sizeof(TBindOpts3);
rBindOpts.hwnd := Handle;
rBindOpts.dwClassContext := CLSCTX_LOCAL_SERVER;
sMonikerName := 'Elevation:Administrator!new:' + GUIDToString(ClassID);
iRes := CoGetObject(PWideChar(sMonikerName), @rBindOpts, IID, PInterface);
OleCheck(iRes);
end;
class function CoIMyServer.Create: IMyServer;
begin
CoCreateInstanceAsAdmin(HInstance, CLASS_IMyServer, IMyServer, @Result);
end;
Когда дело доходит до CoGetObject(PWideChar(sMonikerName), @rBindOpts, IID, PInterface)
я получаю экран UAC и подтвердите запуск сервера в качестве администратора. Однако OleCheck(iRes)
возвращает: «Требуемая операция требует превышения».
От that article Я читал о «надземном (OTS) возвышении».
Это единственный способ получить экземпляр моего сервера для невозбужденного процесса? Если да, то когда должно быть вызвано CoInitializeSecurity
на сервере?
Полная информация о регистрации
HKLM\SOFTWARE\Wow6432Node\Classes\CLSID
{MyServer CLSID}
(Default) = IMyServer Object
LocalizedString = @C:\Program Files (x86)\MyServer\MyServer.exe,-15500
Elevation
Enabled = 0x000001 (1)
LocalServer32
(Default) = C:\PROGRA~2\MyServer\MYSERVER.EXE
ProgID
(Default) = uMyServer.IMyServer
TypeLib
(Default) = {TypeLib GUID}
Version
(Default) = 1.0
HKLM\SOFTWARE\Wow6432Node\Classes\Interface
{GUID of IID_IMyServer}
(Default) = IMyServer
ProxyStubClsid32
(Default) = {Some GUID}
TypeLib
(Default) = {TypeLib GUID}
Version = 1.0
Выше только те записи, которые существуют в моем реестре после регистрации на сервере.
Дополнительная информация
Пробовала без успеха вызова CoInitializeSecurity()
неявных + установка разрешений на обед в соответствии с рекомендациями, используя следующий код:
function GetSecurityDescriptor(const lpszSDDL: LPWSTR; out pSD: PSecurityDescriptor): Boolean;
begin
Result := ConvertStringSecurityDescriptorToSecurityDescriptorW(lpszSDDL, SDDL_REVISION_1,
pSD, nil);
end;
function GetLaunchActPermissionsWithIL(out pSD: PSecurityDescriptor): Boolean;
var
lpszSDDL: LPWSTR;
begin
// Allow World Local Launch/Activation permissions. Label the SD for LOW IL Execute UP
lpszSDDL := 'O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;LW)';
Result := GetSecurityDescriptor(lpszSDDL, pSD);
end;
function GetAccessPermissionsForLUAServer(out pSD: PSecurityDescriptor): Boolean;
var
lpszSDDL: LPWSTR;
begin
// Local call permissions to IU, SY
lpszSDDL := 'O:BAG:BAD:(A;;0x3;;;IU)(A;;0x3;;;SY)';
Result := GetSecurityDescriptor(lpszSDDL, pSD);
end;
function SetAccessPermissions(hAppKey: HKEY; pSD: PSECURITY_DESCRIPTOR): Boolean;
var
dwLen: DWORD;
iRes: LONG;
begin
dwLen := GetSecurityDescriptorLength(pSD);
iRes := RegSetValueExA(hAppKey, 'AccessPermission', 0, REG_BINARY, pSD, dwLen);
Result := iRes = ERROR_SUCCESS;
end;
function SetLaunchActPermissions(hAppKey: HKEY; pSD: PSECURITY_DESCRIPTOR): Boolean;
var
dwLen: DWORD;
iRes: LONG;
begin
dwLen := GetSecurityDescriptorLength(pSD);
iRes := RegSetValueExA(hAppKey, 'LaunchPermission', 0, REG_BINARY, pSD, dwLen);
Result := iRes = ERROR_SUCCESS;
end;
procedure Initialize;
var
pSD: PSecurityDescriptor;
sSubKey: WideString;
hAppKey: HKEY;
begin
sSubKey := 'AppID\{GUID}';
RegOpenKeyW(HKEY_CLASSES_ROOT, PWideChar(sSubKey), hAppKey);
if GetAccessPermissionsForLUAServer(pSD) then
if not SetAccessPermissions(hAppKey, pSD) then
raise Exception.Create(Format('Access permissions aren''t set. System error: %d',
[GetLastError()]));
pSD := nil;
if GetLaunchActPermissionsWithIL(pSD) then
if not SetLaunchActPermissions(hAppKey, pSD) then
raise Exception.Create(Format('Launch permissions aren''t set. System error: %d',
[GetLastError()]));
end;
initialization
TAutoObjectFactory.Create(ComServer, TMyServer, Class_IMyServer,
ciMultiInstance, tmApartment);
Initialize;
Как AppID GUID я пытался использовать как то же самое CLSID GUID моего интерфейса сервера и новый сгенерированный идентификатор GUID: результат был таким же. AccessPermission
и LaunchPermission
значения были указаны в указанном месте после регистрации сервера.
попытался также:
- Указание
ROTFlags = 1
в APPID ключа - Построение сервера, как 64-разрядное приложение
Дополнительные ключи реестра/значения I, созданные вручную:
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID\MyServer.exe]
@="MyServer"
"AppID"="{My GUID}"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID\{My GUID}]
@="MyServer"
"ROTFlags"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{My GUID}]
@="MyServer Object"
"AppID"="{My GUID}"
Вы действительно не должны писать прямо в HKEY_CLASSES_ROOT. Это нормально для чтения, но для записи вы должны использовать 'HKEY_LOCAL_MACHINE \ Software \ Classes' вместо этого. MSDN говорит так же. Помимо этого, где и как вы называете 'CoInitializeSecurity()'? –
Хорошо о разделе реестра. Исправлено. Согласно разделу «Over-The-Shoulder (OTS) Elevation» раздел CoInitializeSecurity() 'называется неявным (см. Пример с кодом SetAccessPermissions), и поэтому я никогда не называл это сам. – AlexeyDaryin
Вы пробовали еще раз называть это? –