共用方式為


撰寫 64 位音訊驅動程式

如果您要撰寫 64 位驅動程式或撰寫可在 32 位和 64 位系統上執行的驅動程式,請遵循 驅動程式程式設計技術中的移植指導方針。 撰寫 64 位音訊驅動程式時可能會遇到的一些陷阱如下所述。

首先,在現有的 32 位驅動程式程式碼中尋找的潛在問題,是在指標類型和 DWORD 或 ULONG 等整數類型之間轉換。 對於 32 位機器撰寫程式碼經驗的程式設計人員,可用來假設指標值符合 DWORD 或 ULONG。 對於 64 位程式碼,此假設很危險。 將指標轉換成類型 DWORD 或 ULONG 可能會導致截斷 64 位指標。 更好的方法是將指標轉換成類型DWORD_PTR或ULONG_PTR。 不論程式碼是針對 32 位或 64 位電腦編譯,DWORD_PTR或ULONG_PTR類型的不帶正負號整數永遠都足以儲存整個指標。

例如, IRP 指標欄位 IoStatus資訊 的類型為 ULONG_PTR。 下列程式碼顯示將 64 位指標值複製到此欄位時,該怎麼做:

    PDEVICE_RELATIONS pDeviceRelations;
    Irp->IoStatus.Information = (ULONG)pDeviceRelations;  // wrong

此程式碼範例錯誤地將指標轉換成 pDeviceRelations 類型 ULONG,如果 sizeof(pDeviceRelations) > sizeof(ULONG) ,則會截斷指標值。 正確的方法是將指標轉換成 ULONG_PTR,如下列所示:

    PDEVICE_RELATIONS pDeviceRelations;
    Irp->IoStatus.Information = (ULONG_PTR)pDeviceRelations;  // correct

這會保留指標值的所有 64 位。

資源清單會將資源的實體位址儲存在類型PHYSICAL_ADDRESS (請參閱 IResourceList) 。 若要避免截斷 64 位位址,您應該在將位址複製到結構或從結構讀取位址時,存取結構的 QuadPart 成員,而不是它的 LowPart 成員。 例如, FindTranslatedPort 宏會傳回包含 I/O 埠基底位址 之CM_PARTIAL_RESOURCE_DESCRIPTOR 結構的指標。 u.。這個 結構的開始成員是基底位址PHYSICAL_ADDRESS指標。 下列程式碼顯示不做的事:

    PUSHORT pBase = (PUSHORT)FindTranslatedPort(0)->u.Port.Start.LowPart;  // wrong

同樣地,這可以截斷指標。 相反地,您應該存取此成員的 QuadPart ,如下列所示:

    PUSHORT pBase = (PUSHORT)FindTranslatedPort(0)->u.Port.Start.QuadPart;  // correct

這會複製整個 64 位指標。

內嵌 Win64 函式,例如 PtrToUlongUlongToPtr 安全地在指標和整數類型之間轉換,而不需依賴這些類型的相對大小假設。 如果某個類型比另一個類型短,則必須在轉換成較長的類型時加以擴充。 每個 Win64 函式的符號位或零填滿符號位,即可擴充較短的類型。 這表示任何程式碼片段,例如

    ULONG ulSlotPhysAddr[NUM_PHYS_ADDRS];
    ulSlotPhysAddr[0] = ULONG(pulPhysDmaBuffer) + DMA_BUFFER_SIZE;  // wrong

應取代為

    ULONG_PTR ulSlotPhysAddr[NUM_PHYS_ADDRS];
    ulSlotPhysAddr[0] = PtrToUlong(pulPhysDmaBuffer) + DMA_BUFFER_SIZE;  // correct

即使 ulSlotPhysAddr 可能代表只有 32 位而非 64 位長的硬體暫存器值,還是建議使用這個值。 如需用於在指標和整數類型之間轉換之所有新 Win64 協助程式函式的清單,請參閱 新資料類型