PDA

View Full Version : [C++ / Windows API] Registro


Teo@Unix
06-05-2010, 08:57
Ciao,

ho un quesito su windows vista e 7...

ho necessità di usare le API per creare, eliminare e modificare alcune chiavi di registro...
su windows XP e privilegi amministrativi nessun problema, per quanto riguarda NT6.0 in avanti credo ci sia il problema dell' UAC, che funzioni uso per richiedere i permessi sufficienti a poter lavorare sul registro?

Un funzione tipo che utilizzo è:

LONG res;
HKEY hKey = HKEY_LOCAL_MACHINE;
// Memory management registry key:
char const* lpSubKey = "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management";
DWORD ulOptions = 0; // Reserved
REGSAM samDesired = KEY_ALL_ACCESS; // Get complete permissions
HKEY phkResult; // Out

// Open registry key:
res = RegOpenKeyExA(
hKey,
lpSubKey,
ulOptions,
samDesired,
&phkResult
);

Su Xp funziona, su win 7 no, credo per il motivo detto prima.

eraser
06-05-2010, 10:22
Ti serve solo in un'occasione oppure ti servono privilegi elevati più volte durante l'utilizzo dell'applicazione?

Perché in caso ti servano più volte, ti conviene direttamente richiedere permessi elevati all'avvio dell'applicazione stessa modificando il manifesto dell'eseguibile.

Da Visual Studio vai su Progetto - Proprietà - Linker - File manifesto - Livello di esecuzione controllo dell'account utente.

Da lì selezioni requireAdministrator. Facendo così, ogni volta che eseguirai l'applicazione, l'UAC ti mostrerà la richiesta per ottenere privilegi elevati.

Certo, se si potesse evitare sarebbe meglio, però se ne hai proprio bisogno penso sia la soluzione più veloce ed efficace.

PS: non è che non puoi lavorare sul registro con Windows Vista e 7, ci puoi lavorare tranquillamente senza privilegi elevati. Ti servono i privilegi elevati perché stai accedendo ad un ramo del registro che non dovrebbe essere modificato se non da un amministratore, per cui un utente normale non può accedervi

tomminno
06-05-2010, 10:28
Hai provato a vedere quanto vale res dopo la chiamata a RegOpenKeyExA?
Ti consiglio comunque di usare RegOpenKeyEx.

eraser
06-05-2010, 10:34
Hai provato a vedere quanto vale res dopo la chiamata a RegOpenKeyExA?
Ti consiglio comunque di usare RegOpenKeyEx.

Non è che cambi molto tra RegOpenKeyExA e RegOpenKeyEx :) Quest'ultima è semplicemente una redirezione alla RegOpenKeyExW che è la versione unicode della funzione

Teo@Unix
06-05-2010, 10:49
grazie,

Ti serve solo in un'occasione oppure ti servono privilegi elevati più volte durante l'utilizzo dell'applicazione?
No praticamente solo all'avvio quando devo controllare e nel caso modificare delle chiavi.
Perché in caso ti servano più volte, ti conviene direttamente richiedere permessi elevati all'avvio dell'applicazione stessa modificando il manifesto dell'eseguibile.

Da Visual Studio vai su Progetto - Proprietà - Linker - File manifesto - Livello di esecuzione controllo dell'account utente.
si per me andrebbe bene, però sto usando QtCreator...


PS: non è che non puoi lavorare sul registro con Windows Vista e 7, ci puoi lavorare tranquillamente senza privilegi elevati. Ti servono i privilegi elevati perché stai accedendo ad un ramo del registro che non dovrebbe essere modificato se non da un amministratore, per cui un utente normale non può accedervi

si, si questo lo so.

tomminno
06-05-2010, 10:55
Non è che cambi molto tra RegOpenKeyExA e RegOpenKeyEx :) Quest'ultima è semplicemente una redirezione alla RegOpenKeyExW che è la versione unicode della funzione

RegOpenKeyEx è un define che punta a RegOpenKeyExA o RegOpenKeyExW a seconda se il progetto è Unicode o meno, come praticamente tutte le api di windows.
Se usi esplicitamente la versione "A" o "W" e ti capita di dover cambiare il codice di caratteri poi è un dramma.

eraser
06-05-2010, 11:00
RegOpenKeyEx è un define che punta a RegOpenKeyExA o RegOpenKeyExW a seconda se il progetto è Unicode o meno, come praticamente tutte le api di windows.
Se usi esplicitamente la versione "A" o "W" e ti capita di dover cambiare il codice di caratteri poi è un dramma.

Onde evitare casini di define, preferisco sempre esplicitare cosa utilizzo ;)

Teo@Unix
06-05-2010, 11:04
Hai provato a vedere quanto vale res dopo la chiamata a RegOpenKeyExA?
Ti consiglio comunque di usare RegOpenKeyEx.

ora non riesco a dirtelo perchè non ho un windows 7 sottomano.
Al 90% è un problema di permessi...

Un' API per poter ottenere i privilegi?

eraser
06-05-2010, 11:10
CoCreateInstanceAsAdmin()

http://msdn.microsoft.com/en-us/library/ms679687

fero86
06-05-2010, 11:15
Onde evitare casini di define, preferisco sempre esplicitare cosa utilizzo ;) casini tipo? la definizione delle macro generiche senza il suffisso A o W serve proprio ad evitare i casini, basta usare la macro _T intorno agli string literals e i tipi TCHAR, LPTSTR e LPCTSTR. il consiglio di tomminno é giusto, e comunque su Windows per questioni di performance é preferibile usare le API Unicode piuttosto che quelle ANSI: il kernel lavora comunque in Unicode, quindi le API in versione ANSI introducono un overhead dovuto al fatto che la stringa va convertita in Unicode prima di essere passata alla system call. addirittura esistono alcune API di cui non esiste la versione ANSI, bisogna usare per forza il suffisso W.

Teo@Unix
06-05-2010, 11:43
CoCreateInstanceAsAdmin()

http://msdn.microsoft.com/en-us/library/ms679687

grazie, sembra risolva il mio problema, proverò il prima possibile...

P.S.
ma su windows tutto sto casino per dei privilegi °.° ?

eraser
06-05-2010, 14:16
casini tipo? la definizione delle macro generiche senza il suffisso A o W serve proprio ad evitare i casini, basta usare la macro _T intorno agli string literals e i tipi TCHAR, LPTSTR e LPCTSTR. il consiglio di tomminno é giusto, e comunque su Windows per questioni di performance é preferibile usare le API Unicode piuttosto che quelle ANSI: il kernel lavora comunque in Unicode, quindi le API in versione ANSI introducono un overhead dovuto al fatto che la stringa va convertita in Unicode prima di essere passata alla system call. addirittura esistono alcune API di cui non esiste la versione ANSI, bisogna usare per forza il suffisso W.

Se è per questo si può dire anche che le versioni ANSI delle API sono per la gran parte stub per le versioni Unicode. Si può dire che le versioni ANSI invocano le versioni Unicode. Si può dire che le api native utilizzano esclusivamente stringhe Unicode e sì, il kernel di Windows utilizza solo stringhe formattate in Unicode. Grazie per la specifica del kernel di Windows ;)

Non ho mai detto che il consiglio sia sbagliato, ho detto che preferisco personalmente esplicitare direttamente quale versione dell'API utilizzare per evitare di trovarmi in situazioni quali quelle dove mi sono trovato - cioè di progetti passati da un PC ad un altro e le API chiamate erano differenti, per cui venivano ad esempio chiamate le versioni ANSI con stringhe Unicode e viceversa.

Comunque avete una capacità di tergiversare in questa sezione :D La domanda iniziale era tutt'altra, ma ci si è focalizzati su una cavolata :D Saranno scelte sue se ha utilizzato la versione ANSI invece della Unicode :D D'altronde ci sono, per cui se si vuole utilizzarle sono lì :D

eraser
06-05-2010, 14:18
grazie, sembra risolva il mio problema, proverò il prima possibile...

P.S.
ma su windows tutto sto casino per dei privilegi °.° ?

Con Visual Studio avresti risolto con un paio di click :)

PS: Se non ti va bene neanche la soluzione con quell'API, potresti semplicemente chiedere all'utente di eseguire il programma come amministratore tramite tasto destro. Metti un controllo all'avvio del programma per verificare se si abbiano i privilegi di amministratore e, se il risultato è negativo, mostri un messaggio e chiudi il programma :)

eraser
06-05-2010, 14:25
Hai provato a vedere quanto vale res dopo la chiamata a RegOpenKeyExA?

Comunque giusto per chiarire questo: sicuramente è un problema di permessi :) Sta tentando di accedere ad una chiave di registro che non è accessibile se non con privilegi di amministratore. Per questo non funziona :)

tomminno
06-05-2010, 14:29
Un'altra alternativa è scrivere nel manifest:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>

eraser
06-05-2010, 14:32
Un'altra alternativa è scrivere nel manifest:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>

Esatto, deve creare un file manifest a mano e includerlo nel progetto del Qt Creator

Teo@Unix
06-05-2010, 19:46
Un'altra alternativa è scrivere nel manifest:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>

questa mi sembra una buona idea!

Il file manifest come lo creo?

fero86
06-05-2010, 20:48
Se è per questo si può dire anche che le versioni ANSI delle API sono per la gran parte stub per le versioni Unicode. Si può dire che le versioni ANSI invocano le versioni Unicode. Si può dire che le api native utilizzano esclusivamente stringhe Unicode e sì, il kernel di Windows utilizza solo stringhe formattate in Unicode. Grazie per la specifica del kernel di Windows ;) eh? :mbe:



Non ho mai detto che il consiglio sia sbagliato, ho detto che preferisco personalmente esplicitare direttamente quale versione dell'API utilizzare per evitare di trovarmi in situazioni quali quelle dove mi sono trovato - cioè di progetti passati da un PC ad un altro e le API chiamate erano differenti, per cui venivano ad esempio chiamate le versioni ANSI con stringhe Unicode e viceversa. no guarda, é inutile che fai la parte di quello vissuto :asd:, questa cosa é possibile solamente se il codice é scritto male; per esempio se hai passato un LP(C)STR oppure un LP(C)WSTR laddove era richiesto un LP(C)TSTR. se non si fanno di questi errori il sorgente deve risultare corretto indipendentemente dalla definizione della macro UNICODE.



Comunque avete una capacità di tergiversare in questa sezione :D La domanda iniziale era tutt'altra, ma ci si è focalizzati su una cavolata :D l'importante é che la discussione sia utile e costruttiva.

fero86
06-05-2010, 20:50
questa mi sembra una buona idea!

Il file manifest come lo creo? se usi Visual C++ il manifest viene inserito automaticamente nell'eseguibile e per regolarne il contenuto devi lavorare sulle impostazioni del progetto. in un post precedente ti é stato detto esattamente quale impostazione permette di generare un eseguibile che richiede tramite manifest di essere avviato con permessi amministrativi.

Teo@Unix
06-05-2010, 21:06
no infatti, uso QtCreator, quindi credo di doverlo creare da zero.

eraser
06-05-2010, 22:04
eh? :mbe:


Cosa non ti convince? Disassemblati una qualsiasi funzione ANSI e vedrai che chiama la sua relativa Unicode (o immediatamente successiva).

Esempio 1: FindFirstFileA


push esi ; dwAdditionalFlags
push esi ; lpSearchFilter
push esi ; fSearchOp
lea ecx, [ebp+FindFileData]
push ecx ; lpFindFileData
push esi ; fInfoLevelId
push dword ptr [eax+4] ; lpFileName
call FindFirstFileExW


Esempio 2: CreateMutexA


push esi
push [ebp+bInitialOwner] ; bInitialOwner
push [ebp+lpMutexAttributes] ; lpMutexAttributes
call CreateMutexW


Non ti convince che le API native utilizzino solo stringhe formattate in Unicode? Guardati la definizione ad esempio di ZwCreateFile.


no guarda, é inutile che fai la parte di quello vissuto :asd:


Ma sei sempre così arrogante quando ti poni con le altre persone? Ho semplicemente detto perché preferisco esplicitare. È un problema per te? tu continua come fai tu, io continuo come faccio io. Non ti ho detto che è sbagliato, da nessuna parte.



l'importante é che la discussione sia utile e costruttiva.

Temo che l'autore del thread non la pensi ugualmente :asd: ma tant'è, è un mio pensiero.

Comunque sia, l'argomento del thread è esaurito, per cui la discussione - almeno per me - si conclude qua

eraser
06-05-2010, 22:07
no infatti, uso QtCreator, quindi credo di doverlo creare da zero.

Puoi creare un file manifest da zero e utilizzare il tool mt.exe presente nel Microsoft Windows Software Development Kit.

Il file manifest è semplice. Un esempio è il seguente:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<ms_asmv2:trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-
com:asm.v2">
<ms_asmv2:security>
<ms_asmv2:requestedPrivileges>
<ms_asmv2:requestedExecutionLevel level="requireAdministrator">
</ms_asmv2:requestedExecutionLevel>
</ms_asmv2:requestedPrivileges>
</ms_asmv2:security>
</ms_asmv2:trustInfo>
</assembly>

Per una guida al tool mt.exe puoi guardare direttamente qui:

http://msdn.microsoft.com/en-us/library/bb756929.aspx

Facendo così compili con il QT Creator il tuo exe e poi includi il file manifest con il tool mt.exe

Spero che questo possa servirti a risolvere il problema :)

Ciao :)

Teo@Unix
06-05-2010, 22:58
Cosa non ti convince? Disassemblati una qualsiasi funzione ANSI e vedrai che chiama la sua relativa Unicode (o immediatamente successiva).

Esempio 1: FindFirstFileA


push esi ; dwAdditionalFlags
push esi ; lpSearchFilter
push esi ; fSearchOp
lea ecx, [ebp+FindFileData]
push ecx ; lpFindFileData
push esi ; fInfoLevelId
push dword ptr [eax+4] ; lpFileName
call FindFirstFileExW


Esempio 2: CreateMutexA


push esi
push [ebp+bInitialOwner] ; bInitialOwner
push [ebp+lpMutexAttributes] ; lpMutexAttributes
call CreateMutexW


Non ti convince che le API native utilizzino solo stringhe formattate in Unicode? Guardati la definizione ad esempio di ZwCreateFile.



Ma sei sempre così arrogante quando ti poni con le altre persone? Ho semplicemente detto perché preferisco esplicitare. È un problema per te? tu continua come fai tu, io continuo come faccio io. Non ti ho detto che è sbagliato, da nessuna parte.




Temo che l'autore del thread non la pensi ugualmente :asd: ma tant'è, è un mio pensiero.

Comunque sia, l'argomento del thread è esaurito, per cui la discussione - almeno per me - si conclude qua

interessante il fatto che le funzioni ANSI richiamano poi le Unicode, non mi ero mai posto la questione.
In effetti mi sembra l'operazione più logica, costruire una interfaccia che avvolge la funzione per consentirne un uso diverso, invece di riscrivere tutto.
In stile microsoft direi.


potresti semplicemente chiedere all'utente di eseguire il programma come amministratore tramite tasto destro.


si, però non mi piaceva molto. :D

Per il file manifest, ora mi è chiaro.
Domani guarderò il tool che mi hai indicato.

Grazie eraser.

eraser
06-05-2010, 23:29
si, però non mi piaceva molto. :D

Per il file manifest, ora mi è chiaro.
Domani guarderò il tool che mi hai indicato.

Grazie eraser.

Ti capisco :D in effetti è un po brutto :D

Di nulla, figurati :)