Поделиться через


Написание 64-разрядных драйверов принтера

Внимание

Современная платформа печати — это предпочтительный способ взаимодействия с принтерами Windows. Рекомендуется использовать драйвер класса "Входящие" Microsoft IPP вместе с приложениями поддержки печати (PSA), чтобы настроить возможности печати в Windows 10 и 11 для разработки устройств принтера.

Дополнительные сведения см. в статье "Современная платформа печати" и руководство по проектированию приложений поддержки печати.

Если вы пишете 64-разрядный драйвер или пишете драйвер, который можно скомпилировать для запуска в 32-разрядных и 64-разрядных системах, следуйте 64-разрядным рекомендациям по переносу драйвера на 64-разрядную версию Windows. В этом разделе описываются некоторые ограничения и проблемы, которые могут возникнуть при написании 64-разрядного драйвера принтера.

Дополнительные сведения об использовании украшений для идентификации 64-разрядной архитектуры см. в следующих разделах:

Ограничения для дескрипторов контекста устройства

Если 32-разрядное приложение работает в 64-разрядной версии операционной системы Microsoft Windows, подключаемый модуль драйвера принтера, работающий в контексте процесса Splwow64.exe thunking, не должен вызывать функцию GDI CreateDC . Этот вызов завершится ошибкой.

Проблемы с написанием 64-разрядных драйверов

В существующем 32-разрядном коде драйвера следует внимательно следить за преобразованиями между типами указателей и целыми типами, такими как DWORD или ULONG. Если у вас есть опыт написания кода для 32-разрядных компьютеров, может потребоваться предположить, что значение указателя вписывается в DWORD или ULONG. Для 64-разрядного кода это предположение опасно. Если ввести указатель на тип DWORD или ULONG, может быть усечен 64-разрядный указатель.

Вместо этого приведите указатель на тип DWORD_PTR или ULONG_PTR. Целое число без знака типа DWORD_PTR или ULONG_PTR всегда достаточно большое для хранения всего указателя независимо от того, компилируется ли код для 32-разрядного или 64-разрядного компьютера.

Например, поле указателя pDrvOptItems.UserData в структуре OEMCUIPPARAM имеет тип ULONG_PTR. В следующем примере кода показано, что не делать при копировании 64-разрядного значения указателя в это поле.

PUSERDATA pData;
OEMCUIPPARAM->pDrvOptItems.UserData = (ULONG)pData;  // Wrong

Предыдущий пример кода приводит указатель pData к типу ULONG, который может усечь значение указателя, если sizeof(pData) >sizeof(ULONG). Правильный подход — приведение указателя к ULONG_PTR, как показано в следующем примере кода.

PUSERDATA pData;
OEMCUIPPARAM->pDrvOptItems.UserData = (ULONG_PTR)pData;  // Correct

В приведенном выше примере кода сохраняются все 64 бита значения указателя.

Встроенные 64-разрядные функции, такие как PtrToUlong и UlongToPtr , безопасно преобразуются между типами указателя и целых чисел, не опираясь на предположения относительного размера этих типов. Если один тип короче другого, его необходимо расширить при преобразовании в более длинный тип. Если более короткий тип расширен путем заполнения бита знака или нуля, каждая функция Win64 может обрабатывать эти ситуации. Рассмотрим следующий пример кода.

ULONG ulHWPhysAddr[NUM_PHYS_ADDRS];
ulSlotPhysAddr[0] = ULONG(pulPhysHWBuffer) + HW_BUFFER_SIZE;  // wrong

В приведенном выше примере кода следует заменить приведенный ниже пример кода.

ULONG_PTR ulHWPhysAddr[NUM_PHYS_ADDRS];
ulSlotPhysAddr[0] = PtrToUlong(pulPhysHWBuffer) + HW_BUFFER_SIZE;  // correct

Второй пример кода предпочтителен, хотя

ulSlotPhysAddr

может представлять значение аппаратного регистра, длиной всего 32 бита, а не 64 битами. Список всех новых вспомогательных функций Win64 для преобразования между указателем и целыми типами см. в разделе "Новые типы данных".