Condividi tramite


Esegui dall'archivio driver

Un INF che usa "Esegui dall'archivio driver" significa che INF usa DIRID 13 per specificare il percorso per i file del pacchetto driver durante l'installazione.

Per un file 'run from Driver Store' payloaded by an INF, the subdir listed in the SourceDisksFiles entry for the file in the INF must match the subdir listed in the DestinationDirs entry for the file in the INF.

Inoltre, non è possibile usare una direttiva CopyFiles per rinominare un file eseguito dall'archivio driver. Queste restrizioni sono necessarie in modo che l'installazione di un INF in un dispositivo non comporti la creazione di nuovi file nella directory dell'archivio driver.

Poiché le voci SourceDisksFiles non possono avere più voci con lo stesso nome file e CopyFiles non possono essere usate per rinominare un file, ogni file 'run from Driver Store' a cui un riferimento INF deve avere un nome file univoco.

I pacchetti driver hanno supporto generale per l'esecuzione da Driver Store a partire da Windows 10 1709. Tuttavia, alcuni stack di dispositivi possono porre restrizioni aggiuntive sui file che è necessario fornire tale plug-in tale stack. Alcuni esempi sono questi stack di dispositivi che non supportano l'esecuzione da Driver Store fino a Windows 10 1803:

Se si specifica un file binario che si collega a uno stack di dispositivi specifico, consultare la documentazione relativa allo stack di dispositivi specifico a cui si sta collegando per verificare se supporta la fornitura di un percorso di file completo al file binario e in caso di restrizioni sul percorso completo del file. Se supporta la fornitura di un percorso di file completo al file binario senza restrizioni su tale percorso, deve supportare il file da eseguire dall'archivio driver.

Ricerca dinamica e caricamento di file dall'archivio driver

In alcuni casi è necessario che un componente carichi un file che fa parte di un pacchetto driver che usa "Esegui dall'archivio driver". I percorsi di questi file del pacchetto driver non devono essere hardcoded perché possono essere diversi tra versioni diverse del pacchetto driver, versioni diverse del sistema operativo, diverse edizioni del sistema operativo e così via. Quando si verifica una tale necessità di caricare i file del pacchetto driver, questi file di pacchetto driver devono essere individuati e caricati dinamicamente usando alcuni dei paradigmi descritti di seguito.

Trovare e caricare file nello stesso pacchetto driver

Quando un file in un pacchetto driver deve caricare un altro file dallo stesso pacchetto driver, un'opzione potenziale per individuare in modo dinamico il file consiste nel determinare la directory da cui è in esecuzione il file e caricare l'altro file rispetto a tale directory.

Un driver WDM o KMDF in esecuzione da Driver Store in Windows 10 versione 1803 e successive che deve accedere ad altri file dal pacchetto driver deve chiamare IoGetDriverDirectory con DriverDirectoryImage come tipo di directory per ottenere il percorso di directory da cui è stato caricato il driver. In alternativa, per i driver che devono supportare le versioni del sistema operativo precedenti a Windows 10 versione 1803, usare IoQueryFullDriverPath per trovare il percorso del driver, ottenere il percorso della directory da cui è stato caricato e cercare i file relativi a tale percorso. Se il driver in modalità kernel è un driver KMDF, può usare WdfDriverWdmGetDriverObject per recuperare l'oggetto driver WDM da passare a IoQueryFullDriverPath.

I file binari in modalità utente possono usare GetModuleHandleExW e GetModuleFileNameW per determinare da dove è stato caricato il file binario. Ad esempio, un file binario del driver UMDF può eseguire operazioni simili alle seguenti:

bRet = GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
                         (PCWSTR)&DriverEntry,
                         &handleModule);
if (bRet) {
    charsWritten = GetModuleFileNameW(handleModule,
                                      path,
                                      pathLength);
    …

Trovare e caricare file in qualsiasi pacchetto driver

In alcuni scenari, un pacchetto driver può contenere un file che deve essere caricato da un file binario in un altro pacchetto driver o da un componente in modalità utente. Questo metodo può essere usato anche per i file dello stesso pacchetto driver, se questo è preferibile rispetto al metodo descritto in precedenza per il caricamento di file dallo stesso pacchetto driver.

Ecco alcuni esempi di scenari che possono comportare il caricamento di file da un pacchetto driver:

  • Una DLL in modalità utente in un pacchetto driver fornisce un'interfaccia per la comunicazione con un driver nel pacchetto driver.

  • Un pacchetto driver di estensione contiene un file di configurazione caricato dal driver nel pacchetto driver di base.

In queste situazioni, il pacchetto driver deve impostare uno stato su un dispositivo o un'interfaccia del dispositivo che indica il percorso del file che dovrebbe essere caricato.

Un pacchetto driver usa in genere un elemento HKR AddReg per impostare questo stato. Per questo esempio, si presuppone che per ExampleFile.dllil pacchetto driver sia presente una voce SourceDisksFiles senza subdir. In questo modo, il file si trova nella radice della directory del pacchetto driver. Si presuppone inoltre che destinationDirs per una direttiva CopyFiles specifichi dirid 13.

Ecco un esempio INF per impostare questo valore come stato del dispositivo:

[ExampleDDInstall.HW]
AddReg = Example_DDInstall.AddReg

[Example_DDInstall.AddReg]
HKR,,ExampleValue,,%13%\ExampleFile.dll

Un esempio INF per impostare questa impostazione come stato dell'interfaccia del dispositivo sarà:

[ExampleDDInstall.Interfaces]
AddInterface = {<fill in an interface class GUID for an interface exposed by the device>},,Example_Add_Interface_Section

[Example_Add_Interface_Section]
AddReg = Example_Add_Interface_Section.AddReg

[Example_Add_Interface_Section.AddReg]
HKR,,ExampleValue,,%13%\ExampleFile.dll

Negli esempi precedenti viene usato un valore di flag vuoti, che genera un valore del Registro di sistema REG_SZ. Ciò comporta la conversione di %13% in un percorso di file in modalità utente completo. In molti casi, è preferibile che il percorso sia relativo a una variabile di ambiente. Se viene utilizzato un valore flag di 0x20000 , il valore del Registro di sistema è di tipo REG_EXPAND_SZ e % 13% converte in un percorso con variabili di ambiente appropriate per astrarre la posizione del percorso. Quando si recupera questo valore del Registro di sistema, chiamare ExpandEnvironmentStrings per risolvere le variabili di ambiente nel percorso.

Se il valore deve essere letto da un componente in modalità kernel, il valore deve essere un valore REG_SZ. Quando il componente in modalità kernel legge tale valore, deve anteporre \??\ prima di passarlo alle API, ad esempio ZwOpenFile.

Per accedere a questa impostazione quando fa parte dello stato del dispositivo, prima l'applicazione deve trovare l'identità del dispositivo. Il codice in modalità utente può usare CM_Get_Device_ID_List_Size e CM_Get_Device_ID_List per ottenere un elenco di dispositivi, filtrati in base alle esigenze. Tale elenco di dispositivi potrebbe contenere più dispositivi, quindi cercare il dispositivo appropriato prima di leggere lo stato dal dispositivo. Ad esempio, chiamare CM_Get_DevNode_Property per recuperare le proprietà nel dispositivo quando si cerca un dispositivo che corrisponde a criteri specifici.

Dopo aver trovato il dispositivo corretto, chiamare CM_Open_DevNode_Key per ottenere un handle nel percorso del Registro di sistema in cui è stato archiviato lo stato del dispositivo.

Il codice in modalità kernel deve recuperare un PDO (oggetto dispositivo fisico) nel dispositivo con lo stato e chiamare IoOpenDeviceRegistryKey. Un modo possibile per recuperare il PDO del dispositivo consiste nell'individuare un'interfaccia abilitata esposta dal dispositivo e usare IoGetDeviceObjectPointer per recuperare l'oggetto dispositivo.

Per accedere a questa impostazione quando si tratta dello stato dell'interfaccia del dispositivo, il codice in modalità utente può chiamare CM_Get_Device_Interface_List_Size e CM_Get_Device_Interface_List.

Inoltre, è possibile usare CM_Register_Notification per ricevere una notifica degli arrivi e delle rimozioni delle interfacce del dispositivo in modo che il codice riceve una notifica quando l'interfaccia è abilitata e quindi può recuperare lo stato. Nella classe dell'interfaccia del dispositivo possono essere presenti più interfacce di dispositivo usate nelle API precedenti. Esaminare tali interfacce per determinare quale sia l'interfaccia corretta per l'impostazione da leggere.

Dopo aver trovato l'interfaccia del dispositivo corretta, chiamare CM_Open_Device_Interface_Key.

Il codice in modalità kernel può recuperare un nome di collegamento simbolico per l'interfaccia del dispositivo da cui ottenere lo stato. A tale scopo, chiama IoRegisterPlugPlayNotification per eseguire la registrazione per le notifiche dell'interfaccia del dispositivo nella classe di interfaccia dispositivo appropriata. In alternativa, chiama IoGetDeviceInterfaces per ottenere un elenco delle interfacce di dispositivo correnti nel sistema. Nella classe dell'interfaccia del dispositivo possono essere presenti più interfacce di dispositivo usate nelle API precedenti. Esaminare tali interfacce per determinare quale sia l'interfaccia corretta che deve avere l'impostazione da leggere.

Dopo aver trovato il nome del collegamento simbolico appropriato, chiama IoOpenDeviceInterfaceRegistryKey per recuperare un handle nel percorso del Registro di sistema in cui è stato archiviato lo stato dell'interfaccia del dispositivo.

Nota

Usare il flag CM_GETIDLIST_FILTER_PRE edizione Standard NT con CM_Get_Device_ID_List_Size e CM_Get_Device_ID_List o il flag CM_GET_DEVICE_INTERFACE_LIST_PRE edizione Standard NT con CM_Get_Device_Interface_List_Size e CM_Get_Device_Interface_List. In questo modo si garantisce che l'hardware correlato allo stato che contiene il percorso del file sia presente e pronto per la comunicazione.

Rimozione del pacchetto driver

Per impostazione predefinita, un pacchetto driver non può essere rimosso dal sistema se è ancora installato in qualsiasi dispositivo. Tuttavia, alcune opzioni per la rimozione di un pacchetto driver dal sistema consentono di tentare di essere rimosso "force". Questo tentativo di rimuovere il pacchetto driver anche se il pacchetto driver è ancora installato in alcuni dispositivi del sistema. Le rimozioni forzate non sono consentite per i pacchetti driver con file che sono "eseguiti dall'archivio driver". Quando un pacchetto driver viene rimosso dal sistema, il relativo contenuto dell'archivio driver viene rimosso. Se sono presenti dispositivi ancora installati con tale pacchetto driver, tutti i file 'run from Driver Store' in tale pacchetto driver verranno ora eliminati e quelli mancanti potrebbero causare malfunzionamenti del dispositivo. Per impedire l'inserimento del dispositivo in uno stato non valido, i pacchetti driver che contengono file "eseguiti dall'archivio driver" non possono essere rimossi forzatamente. Possono essere rimossi solo una volta che non sono più installati in alcun dispositivo. Per facilitare la rimozione di tali pacchetti driver, è possibile usare DiUninstallDriver o pnputil /delete-driver <oem#.inf> /uninstall . Questi metodi di rimozione aggiorneranno prima di tutto tutti i dispositivi che usano il pacchetto driver da rimuovere per non essere più installati con tale pacchetto driver prima di tentare di rimuovere il pacchetto driver.

Sviluppo di pacchetti driver

Test dei file binari privati

Quando si sviluppa un pacchetto driver, se è necessario sostituire un file eseguibile specifico dal pacchetto driver con una versione privata invece di ricompilare completamente e sostituire il pacchetto driver nel sistema, è consigliabile usare un debugger del kernel insieme al comando .kdfiles. Poiché il percorso completo del file nell'archivio driver non deve essere hardcoded, è consigliabile che nel mapping con estensione kdfiles il nome del file OldDriver sia solo il nome diretto del file senza informazioni sul percorso precedenti. Per facilitare questo (e altri scenari), i nomi dei file nei pacchetti driver devono essere il più univoci possibile in modo che non corrisponda al nome di un file da un pacchetto driver non correlato nel sistema.

Conversione di un INF per l'uso dell'esecuzione da Driver Store

Se si dispone di un pacchetto driver esistente con inF che non usa l'esecuzione dall'archivio driver e la conversione per l'esecuzione da Driver Store, gli esempi seguenti mostrano alcuni utilizzi comuni dei file inFs e modelli per l'aggiornamento di tali file da eseguire da DriverStore.

Riferimento rapido per gli aggiornamenti della directory di destinazione

La tabella seguente fornisce un riferimento rapido per trovare le indicazioni appropriate in base alla directory di destinazione corrente DIRID specificata da un pacchetto driver INF per un file.

DIRID Sottodirectory Dettagli
13 Il file usa già 'Esegui dall'archivio driver'. Non sono necessarie ulteriori operazioni.
1 DIRID 1 non deve essere usato. Non esiste alcuna garanzia che la directory di origine sarà disponibile quando è necessario risolvere un riferimento al file. Se invece i componenti del pacchetto driver dipendono da file specifici, includere tali file nel pacchetto driver ed eseguirli dall'Archivio driver.
10 Firmware Per informazioni su come usare DIRID 13 con un pacchetto di driver di aggiornamento del firmware per usarlo come "esegui dall'archivio driver", vedi Creazione di un pacchetto di driver di aggiornamento per.
10 Vedere Altri file.
11 Vedere Altri file.
12 UMDF Vedere File binario del driver UMDF.
12 La maggior parte dei file con una destinazione di DIRID 12 rappresenta i file binari del servizio driver. Vedere File binario del servizio.
16422, 16426, 16427, 16428 La maggior parte dei file con una destinazione di questi DIRID rappresenta l'installazione di un'applicazione. Fornire invece un'applicazione UWP (piattaforma UWP (Universal Windows Platform)) e installarla usando una direttiva AddSoftware da una sezione DDInstall.Software del pacchetto driver INF. Per informazioni dettagliate, vedi Associazione di un driver a un'app piattaforma UWP (Universal Windows Platform) (UWP).

File binario del servizio

Se l'INF aggiunge un servizio e il file binario non viene eseguito da Driver Store, l'INF potrebbe essere simile al seguente:

[DestinationDirs]
 ; Copy the file to %windir%\system32\drivers
 Example_CopyFiles = 12

[ExampleDDInstall]
CopyFiles = Example_CopyFiles

[Example_CopyFiles]
ExampleBinary.sys

[ExampleDDInstall.Services]
AddService = ExampleService,0x2,Example_Service_Inst

[Example_Service_Inst]
DisplayName   = %SvcDesc%
ServiceType   = %SERVICE_KERNEL_DRIVER%
StartType     = %SERVICE_DEMAND_START%
ErrorControl  = %SERVICE_ERROR_NORMAL%
; Point at the file in %windir%\system32\drivers
ServiceBinary = %12%\ExampleBinary.sys

Per spostare questo file da eseguire dall'archivio driver, è necessario aggiornare la voce DestinationDirs per cui il file verrà copiato e aggiornare la direttiva ServiceBinary che fa riferimento al percorso del file.

[DestinationDirs]
; Update the destination to DIRID 13
Example_CopyFiles = 13

[ExampleDDInstall]
CopyFiles = Example_CopyFiles

[Example_CopyFiles]
ExampleBinary.sys

[ExampleDDInstall.Services]
AddService = ExampleService,0x2,Example_Service_Inst

[Example_Service_Inst]
DisplayName   = %SvcDesc%
ServiceType   = %SERVICE_KERNEL_DRIVER%
StartType     = %SERVICE_DEMAND_START%
ErrorControl  = %SERVICE_ERROR_NORMAL%
; Point at the run from Driver Store file using DIRID 13
ServiceBinary = %13%\ExampleBinary.sys

File binario del driver UMDF

Se l'INF aggiunge un driver UMDF e il file binario non viene eseguito dall'archivio driver, l'INF potrebbe essere simile al seguente:

[DestinationDirs]
; Copy the file to %windir%\system32\drivers\UMDF
Example_CopyFiles = 12, UMDF

[ExampleDDInstall]
CopyFiles = Example_CopyFiles

[Example_CopyFiles]
ExampleUmdfDriver.dll

[ExampleDDInstall.Wdf]
UmdfService = ExampleUmdfDriver,Example_UMDF_Inst
...

[Example_UMDF_Inst]
; Point at the file in %windir%\system32\drivers\UMDF
ServiceBinary = %12%\UMDF\ExampleUmdfDriver.dll
...

Per spostare questo file da eseguire dall'archivio driver, è necessario aggiornare la voce DestinationDirs per cui il file verrà copiato e aggiornare la direttiva ServiceBinary che fa riferimento al percorso del file.

[DestinationDirs]
; Update the destination to DIRID 13
Example_CopyFiles = 13

[ExampleDDInstall]
CopyFiles = Example_CopyFiles

[Example_CopyFiles]
ExampleUmdfDriver.dll

[ExampleDDInstall.Wdf]
UmdfService = ExampleUmdfDriver,Example_UMDF_Inst
...

[Example_UMDF_Inst]
; Point at the run from Driver Store file using DIRID 13
ServiceBinary = %13%\ExampleUmdfDriver.dll
...

Altri file

Se l'INF aggiunge un file che può essere caricato da altri componenti e non viene eseguito da Driver Store, l'INF potrebbe essere simile al seguente. In questo esempio, solo il nome del file viene scritto nello stato del Registro di sistema del dispositivo. I componenti che leggono questo valore del Registro di sistema per determinare quale file caricare dipenderebbe dal file in %windir%\system32 cui si trova o dipende dall'ordine di ricerca di LoadLibrary in grado di trovare il file.

[DestinationDirs]
; Copy the file to %windir%\system32
Example_CopyFiles = 11

[ExampleDDInstall]
CopyFiles=Example_CopyFiles
AddReg=Example_AddReg

[Example_CopyFiles]
ExampleFile.dll

[Example_AddReg]
HKR,,FileLocation,,"ExampleFile.dll"

Per spostare questo file da eseguire dall'archivio driver, è necessario aggiornare la voce DestinationDirs per la posizione in cui il file verrà copiato e aggiornare il percorso salvato nello stato del dispositivo. Ciò richiede che i componenti che leggono il valore del Registro di sistema siano in grado di gestire il valore del Registro di sistema come percorso completo di un file anziché un file relativo a %windir%\system32.

[DestinationDirs]
Example_CopyFiles = 13 ; update the destination to DIRID 13

[ExampleDDInstall]
CopyFiles=Example_CopyFiles
AddReg=Example_AddReg

[Example_CopyFiles]
ExampleFile.dll

[Example_AddReg]
; Point at the run from Driver Store file using DIRID 13
HKR,,FileLocation,,"%13%\ExampleFile.dll"