Ho creato un server COM locale che richiede l'elevazione e deve essere istanziato da all'interno di un processo non elevato.Moniker di elevazione COM non riesce ad elevare il server in Vista/Windows 7
Utilizzando MSDN's article on the COM elevation moniker, ho configurato la classe del server in base ai requisiti specificati. Il server è stato registrato con successo nell'hive HKLM.
L'esempio di codice:
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;
Quando si tratta di CoGetObject(PWideChar(sMonikerName), @rBindOpts, IID, PInterface)
ottengo lo schermo UAC e confermare in esecuzione il server come amministratore. Tuttavia, OleCheck(iRes)
restituisce: "L'operazione richiesta richiede l'elevazione" errore.
Da that article Ho letto di "Altezza sopra la spalla (OTS)".
È questo l'unico modo per ottenere la mia istanza del server disponibile per il processo non elevato? In tal caso, quando deve essere chiamato CoInitializeSecurity
sul server?
completi dettagli di registrazione
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
Sopra sono le uniche voci che esistono nel mio registro dopo la registrazione del server.
Ulteriori dettagli
provato senza successo chiamando CoInitializeSecurity()
implicitamente + impostando le autorizzazioni di pranzo come consigliato utilizzando il seguente codice:
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;
Come AppID GUID Ho cercato di usare sia lo stesso CLSID GUID della mia interfaccia server e un nuovo GUID generato: il risultato è stato lo stesso. I valori AccessPermission
e LaunchPermission
sono stati visualizzati nel luogo specificato dopo la registrazione del server.
cercato anche:
- Specificando
ROTFlags = 1
nel AppId chiave - Costruire il server come un'applicazione a 64 bit
Ulteriori chiavi di registro/valori che ho creato manualmente:
[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}"
Non dovresti scrivere direttamente a "HKEY_CLASSES_ROOT' direttamente. Va bene per la lettura, ma per scrivere dovresti usare 'HKEY_LOCAL_MACHINE \ Software \ Classes'. MSDN dice tanto. A parte questo, dove e come si chiama 'CoInitializeSecurity()'? –
OK sulla chiave di registro. Risolto il problema. Secondo la sezione "Over-the-Shoulder (OTS) Elevation" 'CoInitializeSecurity()' è chiamato implicitamente (si veda l'esempio con il codice 'SetAccessPermissions') e quindi non l'ho mai chiamato da solo. – AlexeyDaryin
Hai provato a chiamarlo in modo esplicito ancora? –