Scrittura di driver audio a 64 bit
Se si scrive un driver a 64 bit o si scrive un driver che può essere compilato per l'esecuzione in sistemi a 32 e a 64 bit, seguire le linee guida per la conversione in Tecniche di programmazione driver. Alcune delle insidie che potresti riscontrare nella scrittura di un driver audio a 64 bit sono descritte di seguito.
Prima di tutto, un potenziale problema da cercare nel codice driver a 32 bit esistente è la conversione tra tipi di puntatore e tipi integer, ad esempio DWORD o ULONG. I programmatori con esperienza di scrittura del codice per i computer a 32 bit possono essere usati per presupponere che un valore del puntatore si adatta a una DWORD o A ULONG. Per il codice a 64 bit, questo presupposto è pericoloso. Il cast di un puntatore al tipo DWORD o ULONG può causare il troncamento di un puntatore a 64 bit. Un approccio migliore consiste nel eseguire il cast del puntatore per digitare DWORD_PTR o ULONG_PTR. Un intero senza segno di tipo DWORD_PTR o ULONG_PTR è sempre abbastanza grande per archiviare l'intero puntatore, indipendentemente dal fatto che il codice sia compilato per un computer a 32 o a 64 bit.
Ad esempio, il campo IoStatus del puntatore IoRP. Le informazioni sono di tipo ULONG_PTR. Il codice seguente mostra cosa non eseguire durante la copia di un valore puntatore a 64 bit in questo campo:
PDEVICE_RELATIONS pDeviceRelations;
Irp->IoStatus.Information = (ULONG)pDeviceRelations; // wrong
Questo esempio di codice esegue erroneamente il cast del puntatore per digitare ULONG, che può troncare il pDeviceRelations
valore del puntatore se sizeof(pDeviceRelations) > sizeof(ULONG)
. L'approccio corretto consiste nel eseguire il cast del puntatore a ULONG_PTR, come illustrato nell'articolo seguente:
PDEVICE_RELATIONS pDeviceRelations;
Irp->IoStatus.Information = (ULONG_PTR)pDeviceRelations; // correct
In questo modo vengono mantenuti tutti i 64 bit del valore del puntatore.
Un elenco di risorse archivia l'indirizzo fisico di una risorsa in una struttura di tipo PHYSICAL_ADDRESS (vedere IResourceList). Per evitare di troncare un indirizzo a 64 bit, è necessario accedere al membro QuadPart della struttura anziché al membro LowPart durante la copia di un indirizzo nella struttura o la lettura di un indirizzo dalla struttura. Ad esempio, la macro FindTranslatedPort restituisce un puntatore a una struttura CM_PARTIAL_RESOURCE_DESCRIPTOR contenente l'indirizzo di base di una porta di I/O. U. Porta. Il membro iniziale di questa struttura è un puntatore PHYSICAL_ADDRESS all'indirizzo di base. Il codice seguente mostra cosa non eseguire:
PUSHORT pBase = (PUSHORT)FindTranslatedPort(0)->u.Port.Start.LowPart; // wrong
Di nuovo, questo può troncare il puntatore. È invece necessario accedere a QuadPart di questo membro, come illustrato nell'esempio seguente:
PUSHORT pBase = (PUSHORT)FindTranslatedPort(0)->u.Port.Start.QuadPart; // correct
In questo modo viene copiato l'intero puntatore a 64 bit.
Funzioni Win64 inline, ad esempio PtrToUlong e UlongToPtr , converte in modo sicuro tra puntatore e tipi integer senza basarsi sui presupposti sulle dimensioni relative di questi tipi. Se un tipo è più breve dell'altro, deve essere esteso durante la conversione nel tipo più lungo. Se il tipo più breve viene esteso riempiendo con il segno o con zero è ben definito per ogni funzione Win64. Ciò significa che tutti i frammenti di codice, ad esempio
ULONG ulSlotPhysAddr[NUM_PHYS_ADDRS];
ulSlotPhysAddr[0] = ULONG(pulPhysDmaBuffer) + DMA_BUFFER_SIZE; // wrong
deve essere sostituito da
ULONG_PTR ulSlotPhysAddr[NUM_PHYS_ADDRS];
ulSlotPhysAddr[0] = PtrToUlong(pulPhysDmaBuffer) + DMA_BUFFER_SIZE; // correct
Questo valore è preferibile anche se ulSlotPhysAddr
potrebbe rappresentare il valore di un registro hardware che è solo 32 anziché 64 bit lunghi. Per un elenco di tutte le nuove funzioni helper Win64 per la conversione tra i tipi puntatore e integer, vedere I nuovi tipi di dati.