Accesso al registro di sistema

Transcript

Accesso al registro di sistema
Tutorial
[Access]
Michele de Nittis
ACCESSO AL REGISTRO DI SISTEMA: LETTURA DEL NOME
DEL COMPUTER.
Versione: 1
Data Versione: domenica 12 dicembre 2004
1
Introduzione
Questo tutorial nasce per un’esigenza pratica. Mi capita spesso di studiare soluzioni
e di acquisire nuove esperienze e nozioni su un particolare argomento per poi dimenticarle
se non le applico frequentemente.
Dunque questo testo è una sorta di mio appunto mnemonico, scritto, per quanto
possibile, in modo strutturato e corretto per essere riletto anche a distanza di tempo senza
particolari sforzi.
Ho pensato, poi, che questo mio lavoro sarebbe potuto risultare utile anche a coloro
che sono in cerca di materiale tecnico e documentale per la risoluzione delle
problematiche che io ho già affrontato e descritte nel presente documento.
Nelle seguenti sezioni affronterò il tema dell’invocazione delle API Win32 per
l’accesso alle informazioni immagazzinate nel registro di sistema mediante un esempio
pratico: la lettura dell’identificatore o nome del computer.
Dove leggere il Nome del Computer?
Il nome del computer è immagazzinato come valore di una chiave del registro di
sistema. Per accedere al registro di sistema tramite VBA è necessario sfruttare le API di
Windows. Le API Win32 sono librerie che forniscono insiemi di funzioni per l’interazione
con il sistema operativo. Di tutti questi insiemi ci interessa solo quello costituito da tutte le
funzioni di accesso al registro di windows. Non illustreremo le modalità d’impiego di tutte
queste funzioni ma solo di due in quanto, una volta capito il procedimento, risultèrà
semplice invocare tutte le altre. Come si avrà modo di constatare, le funzioni delle API di
Windows sono dichiarate in modo C-Like. Per essere fruibili in VBA devono essere
ridichiarate all’interno di un modulo. In questo tutorial verrà ricordato, e non spiegato nei
dettagli, come dichiarare una funzione VBA in modo che invochi una funzione di una
libreria di sistema o, più in generale, di una DLL.
Per acquisire il nome identificativo del PC si deve leggere il valore della chiave di
registro:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ComputerName
\ActiveComputerName
oppure
2
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ComputerName
\ComputerName
Per leggere il valore di una chiave di un registro è necessario richiamare le seguenti
due funzioni di sistema:
o RegOpenKeyEx();
o RegQueryValueEx().
RegOpenKeyEx[A|W]1
LONG RegOpenKeyEx(
HKEY hKey,
LPCTSTR lpSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult
);
//
//
//
//
//
handle to open key
address of name of subkey to open
reserved
security access mask
address of handle to open key
Questa funzione consente di aprire una chiave del registro. Il significato dei
parametri è illustrato nella seguente tabella:
hkey
HKEY
(Long)
Riferimento (lett. Handle) alla chiave a cui si vuol accedere. Windows ha
sette valori di chiavi riservati, corrispondenti alle chiavi di primo livello
nella struttura ad albero del registro:
HKEY_CLASSES_ROOT (&H80000000)
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER (&H80000001)
HKEY_DYN_DATA (solo win 95)
HKEY_LOCAL_MACHINE (&H80000002)
HKEY_PERFORMANCE_DATA (solo NT)
HKEY_USERS (&H80000003)
LpSubKey
LPCSTR
UlOptions
SamDesired
DWORD
REGSAM
PhkResult
PHKEY
Indirizzo di una stringa che specifica il nome della sottochiave dalla quale
leggere il valore;
Riservato
Maschera a bit che indica il tipo di accesso alla chiave-sottochiave. I
possibili valori del parametro possono essere combinati tra loro con
l’operatore OR. I principali valori per questo parametro sono i seguenti:
- KEY_ALL_ACCESS: tutti i tipi di accesso (&H2003F);
- KEY_CREATE_LINK: accesso con autorizzazione a creare un link ;
- KEY_CREATE_SUB_KEY: accesso con permesso di creazione di
una sottochiave (&H4);
- KEY_ENUMERATE_SUB_KEYS: accesso con autorizzazione ad
enumerare le sottochiavi (&H8);
- KEY_EXECUTE: accesso in lettura;
- KEY_NOTIFY: accesso con possibilità di cambiare la notifica
(&H10);
- KEY_QUERY_VALUE: accesso con possibilità di interrogare una
sottochiave (&H1);
- KEY_SET_VALUE: accesso per impostare i valori di una
sottochiave
Puntatore all’Handle della chiave aperta.
1
Alcune DLL a 32 bit includono funzioni con versioni leggermente diverse in modo che vengano riconosciute sia
stringhe Unicode che ANSI. Se il nome di una funzione termina con una "A", si tratta della versione ANSI, se invece termina
con una "W", si tratta della versione Unicode.
3
La funzione restituisce un valore intero: 0 (ERROR_SUCCESS) se non si sono
verificati problemi, altrimenti un valore positivo che descrive il problema riscontrato.
Si deve, dunque, definire la funzione VBA che apre la chiave del registro
desiderata impiegando la funzione RegOpenKeyEx(). A tal proposito ricordiamo
sinteticamente che per accedere ad una funzione di una DLL esterna è necessaria una
particolare dichiarazione VBA che effettui una mappatura dei tipi di dato nativi di VBA con
quelli:
a) dei parametri formali attesi dalla funzione di sistema;
b) del tipo di dato restituito;
c) eventualmente del nome della funzione stessa.
La sintassi per dichiarare in VBA una funzione che accede ad una funzione di
sistema o di una libreria DLL è la seguente:
[Public | Private] Declare Function nome Lib "nomelibreria" [Alias "nomealias"]
[([elencoargomenti])] [As tipo],
dove nome è il nome della funzione VBA, nomelibreria è il nome della libreria che
contiene la funzione da invocare, nomeAlias è il nome della funzione della Libreria di
sistema/DLL da invocare ed elencoargomenti è, ovviamente, l’elenco degli argomenti da
passera alla funzione.
Nell’area delle dichiarazioni delle variabili, dunque, dichiariamo la funzione della
libreria Win32 come segue:
Public
Declare
Function
MyRegOpenKeyExA
Lib
"advapi32.dll"
Alias
"RegOpenKeyExA" (ByVal hkey As Long, ByVal lpSubkey As String, ByVal ulOptions
As Long, ByVal samDesired As Long, ByRef phkresult As Long) As Long
Si osservi che il parametro phkresult viene passato alla funzione ByRef perché
deve poter essere modificato dalla funzione stessa. Al termine dell’esecuzione della
funzione, infatti, phkresult conterrà l’handle della chiave aperta.
Applichiamo, dunque, la funzione RegOpenKeyEx (ovvero MyRegOpenKeyExA)
per aprire la chiave di registro necessaria per leggere il nome del computer.
Public Function ApriChiaveNomeComputer() As Long
Dim MyName As String
Dim RegPath As String
Dim l_MyName As Long
Dim risultato As Long
Dim MyHandle As Long
RegPath = "SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName"
risultato = MyRegOpenKeyExA(HKEY_LOCAL_MACHINE, RegPath, 0, KEY_QUERY_VALUE, MyHandle)
If risultato = 0 Then
ApriChiaveNomeComputer = MyHandle
Else
MsgBox "Errore n°: " & risultato
ApriChiaveNomeComputer = 0
4
End If
End Function
Una volta aperta la chiave di registro specificata ed ottenuto il relativo handle, è
possibile invocare la funzione che legge il valore di una sua sottochiave.
RegQueryValueEx[A|W]2
LONG RegQueryValueEx(
HKEY hKey,
LPTSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
);
//
//
//
//
//
//
handle to key to query
address of name of value to query
reserved
address of buffer for value type
address of data buffer
address of data buffer size
Se la funzione viene eseguita con successo restituisce il valore ERROR_SUCCESS
(0), altrimenti un numero intero positivo che rappresenta il tipo di errore verificatosi.
Esaminiamo nel dettaglio i sei parametri:
hkey
HKEY
LpValueName
LPTSTR
Riferimento alla chiave aperta.
Stringa che specifica il nome della sottochiave dalla quale prelevare il
valore;
lpReserved
LPDWORD
Riservato: deve essere NULL;
lpType
LPDWORD
Puntatore ad una variabile che riceve il tipo di valore della sottochiave.
Alcuni tra i valori possibili sono:
LpData
LPBYTE
-
REG_BINARY : generico dato binario;
-
REG_DWORD (4): numero a 32 bit;
-
REG_SZ (1): Stringa terminata dal carattere NULL.
Puntatore ad un buffer di memoria di dimensione sufficiente a ricevere il
valore della sottochiave;
LpcbData
LPDWORD
Puntatore ad una variabile che contiene la dimensione in byte del buffer
puntato dal parametro LpData. Dopo l’esecuzione della funzione il valore
del parametro viene aggiornato con l’effettiva lunghezza in byte del
valore letto dalla sottochiave.
Dichiariamo, quindi, la funzione della libreria nell’area delle dichiarazioni di un
modulo:
Public Declare Function MyRegQueryValueExA Lib "advapi32.dll" Alias
"RegQueryValueExA" (ByVal hkey As Long, ByVal lpValueName As String, ByVal
lpReserved as Long, ByVal lpType as Long, ByVal lpData As String, lpcbData As
Long) As Long
Il codice VBA della funzione che deve leggere il nome del computer, mediante
l’invocazione
della
funzione
di
sistema
MyRegQueryValueExA), è la seguente:
2
Vedi la precedente nota 1.
5
RegQueryValueEx
(ovvero
Public Sub mostraNomeComputer()
Dim MyName As String
Dim RegPath As String
Dim l_MyName As Long
Dim KeyType As Long
Dim risultato As Long
l_MyName = 255
MyName = String(l_MyName, vbNullChar)
RegPath = "ComputerName"
risultato = ApriChiaveNomeComputer()
If risultato > 0 Then
risultato = MyRegQueryValueExA(risultato, RegPath, 0, KeyType, MyName, l_MyName)
If risultato = 0 Then
MsgBox "Nome Computer: " & MyName
Else
MsgBox "Errore nella lettura del nome del computer"
End If
Else
MsgBox "Problemi nell'apertura della chiave del registro."
End If
End Sub
La stringa MyName viene modificata dalla funzione in modo da contenere il valore
della sottochiave letta e quindi deve essere vista come un buffer di un numero di byte
sufficiente a contenere il risultato aspettato.
Dunque MyName può essere definita con la funzione String(numByte,
vbNullChar)
Conclusione
L’esposizione del presente tutorial, sebbene interessi un caso molto particolare,
evidenzia l’uso delle funzioni della libreria Win32 per accedere alle chiavi del registro di
windows da VBA. Come già detto la metodologia illustrata può essere applicata a tutte le
altre funzioni della libreria. Le fonti di questo tutorial sono state:
o
Il sito www.sitocomune.com;
o
La documentazione MSDN Library a corredo di Visual Studio 6.0;
o
Un tutorial sul registro di configurazione di Windows (www.alground.com);
Ringrazio in anticipo tutti coloro che vorranno contribuire a migliorare questi appunti
con suggerimenti, correzioni e segnalazioni di imprecisione contattandomi dal mio sito
personale ( www.mdenittis.it ).
6