Isolamento del pacchetto driver
L'isolamento dei pacchetti driver è un requisito per i driver di Windows che rende i pacchetti driver più resilienti alle modifiche esterne, all'aggiornamento più semplice e più semplice da installare.
Nota
Anche se l'isolamento dei pacchetti driver è necessario per i driver di Windows, i driver desktop di Windows ne traggono comunque vantaggio grazie a una maggiore resilienza e facilità di servizio.
Nella tabella seguente vengono illustrate alcune procedure di esempio per i pacchetti driver legacy non più consentite per i driver windows nella colonna sinistra insieme al comportamento necessario per i driver di Windows nella colonna destra.
Driver non isolato | Driver isolato |
---|---|
INF copia i file in %windir%\System32 o %windir%\System32\drivers | I file del driver vengono eseguiti dall'archivio driver |
Interagisce con stack di dispositivi/driver usando percorsi hardcoded | Interagisce con stack di dispositivi/driver usando le funzioni fornite dal sistema o le interfacce del dispositivo |
Percorso hardcodes in percorsi globali del Registro di sistema | Usa le funzioni HKR e fornite dal sistema per il percorso relativo del Registro di sistema e dello stato del file |
Scritture di file di runtime in qualsiasi percorso | I file vengono scritti in relazione ai percorsi forniti dal sistema operativo |
Per informazioni su come determinare se il pacchetto driver soddisfa i requisiti di isolamento dei pacchetti driver, vedere Convalida dei driver di Windows. Per esempi di come aggiornare un INF per soddisfare i requisiti di isolamento dei pacchetti driver, vedere Conversione di un INF per seguire l'isolamento del pacchetto driver.
Eseguire dall'archivio driver
Tutti i pacchetti driver isolati lasciano i file del pacchetto driver nell'archivio driver. Ciò significa che specificano DIRID 13 nel relativo INF per specificare il percorso dei file del pacchetto driver durante l'installazione. Per altre informazioni su come usarlo in un pacchetto driver, vedere Eseguire dall'archivio driver.
Lettura e scrittura dello stato
Nota
Se il componente usa le proprietà dell'interfaccia del dispositivo o del dispositivo per archiviare lo stato, continuare a usare tale metodo e l'API del sistema operativo appropriata per archiviare e accedere allo stato. Le indicazioni seguenti per lo stato del Registro di sistema e del file sono destinate ad altri stati che devono essere archiviati da un componente.
L'accesso a vari stati del Registro di sistema e file deve essere eseguito chiamando le funzioni che forniscono a un chiamante la posizione dello stato e quindi lo stato viene letto/scritto in relazione a tale posizione. Non usare percorsi assoluti del Registro di sistema e percorsi di file hardcoded.
In questa sezione sono disponibili le procedure seguenti:
Stato del Registro di sistema
In questa sezione sono disponibili le procedure seguenti:
Stato del Registro di sistema del dispositivo PnP
I pacchetti driver isolati e i componenti in modalità utente usano in genere una delle due posizioni per archiviare lo stato del dispositivo nel Registro di sistema. Si tratta della chiave hardware (chiave del dispositivo) per il dispositivo e della chiave software (chiave del driver) per il dispositivo. La chiave hardware è in genere per le impostazioni relative al modo in cui una singola istanza del dispositivo interagisce con l'hardware. Ad esempio, per abilitare una funzionalità hardware o inserire l'hardware in una modalità specifica. La chiave software è in genere per le impostazioni relative al modo in cui una singola istanza del dispositivo interagisce con il sistema e altri software. Ad esempio, per configurare il percorso di un file di dati, per l'interazione con un framework o per accedere alle impostazioni dell'app per un dispositivo. Per recuperare un handle in questi percorsi del Registro di sistema, utilizzare una delle opzioni seguenti:
IoOpenDeviceRegistryKey (WDM)
Direttiva INF AddReg che usa voci reg-root HKR in una sezione del registro dei componenti aggiuntivi a cui si fa riferimento da una sezione INF DDInstall o DDInstall.HW, come illustrato di seguito:
[ExampleDDInstall.HW]
AddReg = Example_DDInstall.AddReg
[Example_DDInstall.AddReg]
HKR,,ExampleValue,,%13%\ExampleFile.dll
Stato del Registro di sistema dell'interfaccia del dispositivo
Per leggere e scrivere lo stato del Registro di sistema dell'interfaccia del dispositivo, usare una delle opzioni seguenti:
Direttiva INF AddReg che usa le voci reg-root HKR in un add-registry-section a cui si fa riferimento da una sezione add-interface-section
Stato del Registro di sistema del servizio
Lo stato del servizio deve essere classificato in una delle 3 categorie
Stato del Registro di sistema del servizio non modificabile
Lo stato del servizio non modificabile è lo stato fornito dal pacchetto driver che installa il servizio. Questi valori del Registro di sistema impostati da INF per i servizi driver e Win32 devono essere archiviati nella sottochiave "Parameters" del servizio fornendo una riga HKR in una sezione AddReg e quindi facendo riferimento a tale sezione nella sezione di installazione del servizio in INF. Ad esempio:
[ExampleDDInstall.Services]
Addservice = ExampleService, 0x2, Example_Service_Inst
[Example_Service_Inst]
DisplayName = %ExampleService.SvcDesc%
ServiceType = 1
StartType = 3
ErrorControl = 1
ServiceBinary = %13%\ExampleService.sys
AddReg=Example_Service_Inst.AddReg
[Example_Service_Inst.AddReg]
HKR, Parameters, ExampleValue, 0x00010001, 1
Per accedere alla posizione di questo stato dal servizio in fase di esecuzione, usare una di queste funzioni:
IoOpenDriverRegistryKey (WDM) con un DRIVER_REGKEY_TYPE di DriverRegKeyParameters
GetServiceRegistryStateKey (Servizi Win32) con un SERVICE_REGISTRY_STATE_TYPE di ServiceRegistryStateParameters
Questi valori del Registro di sistema forniti da INF nella sottochiave "Parameters" per il servizio devono essere letti solo in fase di esecuzione e non modificati. Devono essere trattati come di sola lettura.
Se i valori del Registro di sistema forniti da INF sono impostazioni predefinite che possono essere sovrascritte in fase di esecuzione, i valori di override devono essere scritti nello stato del Registro di sistema del servizio interno o nello stato del Registro di sistema del servizio condiviso per il servizio. Quando si recuperano le impostazioni, l'impostazione può essere cercata per prima nello stato modificabile. Se non esiste, l'impostazione può essere cercata nello stato non modificabile. RtlQueryRegistryValueWithFallback può essere usato per consentire le impostazioni di query, ad esempio quelle con override e un valore predefinito.
Stato del Registro di sistema del servizio interno
Lo stato del servizio interno è lo stato scritto in fase di esecuzione e di proprietà e gestito solo dal servizio stesso ed è accessibile solo a tale servizio. Per accedere alla posizione per lo stato del servizio interno, usare una di queste funzioni dal servizio:
IoOpenDriverRegistryKey (WDM) con un DRIVER_REGKEY_TYPE di DriverRegKeyPersistentState
GetServiceRegistryStateKey (Servizi Win32) con un SERVICE_REGISTRY_STATE_TYPE di ServiceRegistryStatePersistent
Se il servizio vuole consentire ad altri componenti di modificare queste impostazioni, il servizio deve esporre un'interfaccia che un altro componente può chiamare in che indica al servizio come modificare queste impostazioni. Ad esempio, un servizio Win32 potrebbe esporre un'interfaccia COM o RPC e un servizio driver potrebbe esporre un'interfaccia IOCTL tramite un'interfaccia dispositivo.
Stato del Registro di sistema del servizio condiviso
Lo stato del servizio condiviso è lo stato scritto in fase di esecuzione e può essere condiviso con altri componenti in modalità utente se sono sufficientemente privilegiati. Per accedere alla posizione per questo stato del servizio condiviso, usare una di queste funzioni:
IoOpenDriverRegistryKey (WDM) con un DRIVER_REGKEY_TYPE di DriverRegKeySharedPersistentState
GetSharedServiceRegistryStateKey (Servizi Win32) con un SERVICE_SHARED_REGISTRY_STATE_TYPE di ServiceSharedRegistryPersistentState
Stato del file
In questa sezione sono disponibili le procedure seguenti:
Stato del file del dispositivo
Se i file correlati a un dispositivo devono essere scritti in fase di esecuzione, questi file devono essere archiviati in relazione a un handle o a un percorso di file fornito tramite l'API del sistema operativo. I file di configurazione specifici del dispositivo sono un esempio dei tipi di file da archiviare qui. Per accedere alla posizione di questo stato, usare una di queste funzioni dal servizio:
IoGetDeviceDirectory (WDM) con il parametro DirectoryType impostato su DeviceDirectoryData
Stato del file del servizio
Lo stato del file di servizio può essere classificato in una delle 3 categorie
Stato del file del servizio non modificabile
Lo stato del file del servizio non modificabile è costituito da file che fanno parte del pacchetto driver. Per altre informazioni sull'accesso a tali file, vedere Eseguire da Driver Store.
Stato del file del servizio interno
Lo stato del file del servizio interno è lo stato scritto in fase di esecuzione e di proprietà e gestito solo dal servizio stesso ed è accessibile solo a tale servizio. Per accedere alla posizione per lo stato del servizio interno, usare una di queste funzioni dal servizio:
IoGetDriverDirectory (WDM, KMDF) con il parametro DirectoryType impostato su DriverDirectoryData
GetServiceDirectory (Servizi Win32) con il parametro eDirectoryType impostato su ServiceDirectoryPersistentState
Se il servizio vuole consentire ad altri componenti di modificare queste impostazioni, il servizio deve esporre un'interfaccia che un altro componente può chiamare in che indica al servizio come modificare queste impostazioni. Ad esempio, un servizio Win32 potrebbe esporre un'interfaccia COM o RPC e un servizio driver potrebbe esporre un'interfaccia IOCTL tramite un'interfaccia dispositivo.
Stato del file del servizio condiviso
Lo stato del file del servizio condiviso è lo stato scritto in fase di esecuzione e può essere condiviso con altri componenti in modalità utente se sono sufficientemente privilegiati. Per accedere alla posizione per questo stato del servizio condiviso, usare una di queste funzioni:
IoGetDriverDirectory (WDM, KMDF) con il parametro DirectoryType impostato su DriverDirectorySharedData
GetSharedServiceDirectory (Servizi Win32) con il parametro DirectoryType impostato su ServiceSharedDirectoryPersistentState
DriverData e ProgramData
I file che possono essere condivisi con altri componenti, ma che non rientrano nella categoria dello stato del file del servizio condiviso possono essere scritti in percorsi DriverData
o ProgramData
.
Queste posizioni offrono ai componenti una posizione in cui scrivere lo stato temporaneo o lo stato che deve essere utilizzato da altri componenti e potenzialmente raccolti e copiati da un sistema da elaborare da un altro sistema. Ad esempio, i file di log personalizzati o i dump di arresto anomalo si adattano a questa descrizione.
Evitare di scrivere file nella radice delle DriverData
directory o ProgramData
. Creare invece una sottodirectory con il nome della società e quindi scrivere file e altre sottodirectory all'interno di tale directory.
Ad esempio, per un nome aziendale di Contoso, un driver in modalità kernel potrebbe scrivere un log personalizzato in \DriverData\Contoso\Logs
e un'applicazione in modalità utente potrebbe raccogliere o analizzare i file di log da %DriverData%\Contoso\Logs
.
DriverData
La DriverData
directory è disponibile in Windows 10, versione 1803 e successive ed è accessibile agli amministratori e ai driver UMDF.
I driver in modalità kernel accedono alla DriverData
directory usando un collegamento simbolico fornito dal sistema denominato \DriverData
.
I programmi in modalità utente accedono alla DriverData
directory usando la variabile %DriverData%
di ambiente .
ProgramData
La %ProgramData%
variabile di ambiente in modalità utente è disponibile per i componenti in modalità utente da usare per l'archiviazione dei dati.
File temporanei
I file temporanei vengono in genere usati nelle operazioni intermedie. Questi valori possono essere scritti in un sottopercorso nelle variabili di %TEMP%
ambiente o %TMP%
. Poiché questi percorsi sono accessibili tramite variabili di ambiente, questa possibilità è limitata ai componenti in modalità utente. Non vi sono garanzie sulla durata o la persistenza di questi file temporanei dopo la chiusura degli handle. Il sistema operativo o l'utente può rimuoverli in qualsiasi momento e potrebbe non essere persistente in un riavvio.
Evitare di scrivere file nella radice delle %TEMP%
directory o %TMP%
. Creare invece una sottodirectory con il nome della società e quindi scrivere file e altre sottodirectory all'interno di tale directory.
Stato della proprietà
Sia i dispositivi che le interfacce del dispositivo supportano l'archiviazione dello stato tramite il modello di proprietà PnP. Il modello di proprietà consente di archiviare i dati delle proprietà strutturate su un dispositivo o un'interfaccia del dispositivo. Ciò è destinato a dati più piccoli che si adattano ragionevolmente ai tipi di proprietà supportati dal modello di proprietà.
Per accedere alle proprietà del dispositivo, è possibile usare queste API:
Driver WDM
Driver WDF
Codice in modalità utente
Per accedere alle proprietà dell'interfaccia del dispositivo, è possibile usare queste API:
Driver WDM
Driver WDF
Codice in modalità utente
Uso delle interfacce dei dispositivi
Se un driver vuole consentire ad altri componenti di leggere o modificare lo stato interno del driver, il driver deve esporre un'interfaccia che un altro componente può chiamare in che indica al driver quali impostazioni restituire o come modificare determinate impostazioni. Ad esempio, il servizio driver potrebbe esporre un'interfaccia IOCTL tramite un'interfaccia del dispositivo.
In genere, il driver proprietario dello stato espone un'interfaccia del dispositivo in una classe di interfaccia dispositivo personalizzata. Quando il driver è pronto per consentire ad altri componenti di accedere allo stato, abilita l'interfaccia . Per ricevere notifiche quando un'interfaccia del dispositivo è abilitata, i componenti in modalità utente possono registrarsi per le notifiche di arrivo dell'interfaccia del dispositivo e i componenti in modalità kernel possono usare IoRegisterPlugPlayNotification. Per consentire a questi componenti di accedere allo stato, il driver che abilita l'interfaccia deve definire un contratto per la classe di interfaccia dispositivo personalizzata. Questo contratto è in genere uno dei due tipi seguenti:
Un contratto di I/O può essere associato a tale classe di interfaccia dispositivo che fornisce un meccanismo per l'accesso allo stato. Altri componenti usano l'interfaccia del dispositivo abilitata per inviare richieste di I/O conformi al contratto.
Interfaccia direct-call che viene restituita tramite un'interfaccia di query. Altri driver potrebbero inviare IRP_MN_QUERY_INTERFACE per recuperare i puntatori di funzione dal driver da chiamare.
In alternativa, se il driver proprietario dello stato consente l'accesso diretto allo stato, altri driver potrebbero accedere allo stato usando funzioni fornite dal sistema per l'accesso a livello di codice allo stato dell'interfaccia del dispositivo. Per altre informazioni, vedere Stato del Registro di sistema dell'interfaccia del dispositivo.
Queste interfacce o lo stato (a seconda del metodo di condivisione usato) devono essere correttamente con controllo delle versioni in modo che il driver proprietario dello stato possa essere eseguito indipendentemente da altri componenti che accedono a tale stato. I fornitori di driver non possono basarsi su altri componenti gestiti contemporaneamente al driver e rimanere nella stessa versione.
Poiché i dispositivi e i driver che controllano le interfacce sono disponibili, i driver e le applicazioni devono evitare di chiamare IoGetDeviceInterfaces all'avvio del componente per ottenere un elenco di interfacce abilitate. La procedura consigliata consiste invece nella registrazione per le notifiche relative all'arrivo o alla rimozione dell'interfaccia del dispositivo e quindi chiamare la funzione appropriata per ottenere l'elenco delle interfacce abilitate esistenti nel computer.
Per altre informazioni sulle interfacce dei dispositivi, vedere:
Riferimento rapido del supporto del sistema operativo per le API di gestione dello stato
La maggior parte dei pacchetti driver deve supportare una gamma di versioni del sistema operativo. Per altre informazioni su come ottenere questo risultato in un pacchetto driver, vedere Supporto di più versioni del sistema operativo. Le tabelle seguenti forniscono un riferimento rapido di quando è stato aggiunto il supporto del sistema operativo per varie API di gestione dello stato.
Driver WDM
Sistema operativo | Aggiunta del supporto |
---|---|
Windows 2000 | IoOpenDeviceRegistryKey IoOpenDeviceInterfaceRegistryKey |
Windows Vista | IoGetDevicePropertyData IoSetDevicePropertyData |
Windows 8 | IoGetDeviceInterfacePropertyData IoSetDeviceInterfacePropertyData |
Windows 8.1 | IoQueryFullDriverPath |
Windows 10 1803 | IoOpenDriverRegistryKey per RegKeyType di DriverRegKeyParameters e DriverRegKeyPersistentState IoGetDeviceDirectory IoGetDriverDirectory per DirectoryType di DriverDirectoryImage e DriverDirectoryData |
Windows 10 1809 | RtlQueryRegistryValueWithFallback |
Windows 11 21H2 | IoOpenDriverRegistryKey per RegKeyType di DriverRegKeySharedPersistentState IoGetDriverDirectory per DirectoryType di DriverDirectorySharedData |
Driver KMDF
Driver UMDF
Codice in modalità utente
Sistema operativo | Aggiunta del supporto |
---|---|
Windows 2000 | CM_Open_DevNode_Key |
Windows Vista | CM_Open_Device_Interface_Key CM_Get_DevNode_Property CM_Set_DevNode_Property CM_Get_Device_Interface_Property CM_Set_Device_Interface_Property |
Windows 10 2004 | GetServiceRegistryStateKey GetServiceDirectory |
Windows 11 21H2 | GetSharedServiceRegistryStateKey GetSharedServiceDirectory |