Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Jeśli piszesz sterownik 64-bitowy lub zapisujesz sterownik, który można skompilować w celu uruchomienia w systemach 32-bitowych i 64-bitowych, postępuj zgodnie z wytycznymi dotyczącymi przenoszenia w sekcji Techniki programowania sterowników. Poniżej opisano niektóre pułapki, które mogą wystąpić podczas pisania 64-bitowego sterownika audio.
Przede wszystkim potencjalny problem do zidentyfikowania w istniejącym 32-bitowym kodzie sterownika dotyczy konwersji między typami wskaźnika a typami całkowitymi, takimi jak DWORD lub ULONG. Programiści z doświadczeniem w pisaniu kodu dla maszyn 32-bitowych mogą być przyzwyczajeni do zakładania, że wartość wskaźnika mieści się w DWORD lub ULONG. W przypadku 64-bitowego kodu to założenie jest niebezpieczne. Rzutowanie wskaźnika do typu DWORD lub ULONG może spowodować obcięcie wskaźnika 64-bitowego. Lepszym podejściem jest rzutowanie wskaźnika na typ DWORD_PTR lub ULONG_PTR. Niepodpisane liczby całkowite typu DWORD_PTR lub ULONG_PTR są zawsze wystarczająco duże, aby przechowywać cały wskaźnik, niezależnie od tego, czy kod jest kompilowany dla maszyny 32-lub 64-bitowej.
Na przykład pole IRP wskaźnika IoStatus.Informacja jest typu ULONG_PTR. Poniższy kod pokazuje, co nie robić podczas kopiowania 64-bitowej wartości wskaźnika do tego pola:
PDEVICE_RELATIONS pDeviceRelations;
Irp->IoStatus.Information = (ULONG)pDeviceRelations; // wrong
Przykładowy kod błędnie rzutuje wskaźnik pDeviceRelations na typ ULONG, co może ucinać wartość wskaźnika, jeśli sizeof(pDeviceRelations) > sizeof(ULONG). Właściwym podejściem jest rzutowanie wskaźnika na ULONG_PTR, jak pokazano poniżej:
PDEVICE_RELATIONS pDeviceRelations;
Irp->IoStatus.Information = (ULONG_PTR)pDeviceRelations; // correct
Spowoduje to zachowanie wszystkich 64 bitów wartości wskaźnika.
Lista zasobów przechowuje fizyczny adres zasobu w strukturze typu PHYSICAL_ADDRESS (zobacz IResourceList). Aby uniknąć obcinania adresu 64-bitowego, należy uzyskać dostęp do składowej QuadPart struktury, a nie jej elementu członkowskiego LowPart podczas kopiowania adresu do struktury lub odczytywania adresu ze struktury. Na przykład makro FindTranslatedPort zwraca wskaźnik do struktury CM_PARTIAL_RESOURCE_DESCRIPTOR zawierającej podstawowy adres portu we/wy. U. Port. Początkowy element członkowski tej struktury jest wskaźnikiem PHYSICAL_ADDRESS do adresu podstawowego. Poniższy kod pokazuje, czego nie robić:
PUSHORT pBase = (PUSHORT)FindTranslatedPort(0)->u.Port.Start.LowPart; // wrong
Ponownie może to obcinać wskaźnik. Zamiast tego należy uzyskać dostęp do QuadPart tej składowej, jak pokazano poniżej:
PUSHORT pBase = (PUSHORT)FindTranslatedPort(0)->u.Port.Start.QuadPart; // correct
Spowoduje to skopiowanie całego wskaźnika 64-bitowego.
Wbudowane funkcje Win64, takie jak PtrToUlong i UlongToPtr , bezpiecznie konwertują między typami wskaźników i liczb całkowitych bez polegania na założeniach dotyczących względnych rozmiarów tych typów. Jeśli jeden typ jest krótszy niż drugi, należy go rozszerzyć podczas konwertowania na dłuższy typ. Niezależnie od tego, czy krótszy typ jest rozszerzany przez wypełnienie bitem znaku, czy zerami, jest jasno określony dla każdej funkcji Win64. Oznacza to, że wszystkie fragmenty kodu, takie jak
ULONG ulSlotPhysAddr[NUM_PHYS_ADDRS];
ulSlotPhysAddr[0] = ULONG(pulPhysDmaBuffer) + DMA_BUFFER_SIZE; // wrong
element powinien zostać zastąpiony przez
ULONG_PTR ulSlotPhysAddr[NUM_PHYS_ADDRS];
ulSlotPhysAddr[0] = PtrToUlong(pulPhysDmaBuffer) + DMA_BUFFER_SIZE; // correct
Jest to preferowane, mimo że ulSlotPhysAddr może reprezentować wartość rejestru sprzętowego, który ma długość tylko 32, a nie 64 bitów. Aby uzyskać listę wszystkich nowych funkcji pomocnika Win64 na potrzeby konwertowania między typami wskaźników i liczb całkowitych, zobacz The New Data Types (Nowe typy danych).