This section provides step-by-step porting details that pertain to both display and print drivers.
Most functions that were originally exported by winsrv.dll are now exported by win32k.sys, so a simple relink of the driver resolves references to these functions. However, all other functions imported by your driver (from kernel32.dll, advapi32.dll, or any other DLL) must be replaced or eliminated because they are no longer available. If your driver directly references functions from any image other than win32k.sys, the system will not load your image. Therefore, the basic requirement for enabling a graphics driver to run under Windows NT 4.0 is to remove any calls to Win32 functions, and replace them with the calls exported by win32k.sys.
link -dump -imports your_driver.dll
Here are some common changes to make to your graphics drivers to port them from Windows NT 3.51 to 4.0.
#include <stddef.h> #include <stdarg.h> #include <limits.h> #include <windef.h> #include <wingdi.h> #include <winddi.h> //These include files are for display drivers only. #include <devioctl.h> #include <ntddvdeo.h> #include <ioaccess.h> //These include files are for print drivers only. #include <gdispool.h> //Private defines #include <my_headers>
Note Due to problems with the spooler API header file, you might encounter compiler warnings in the pre-beta Windows NT 4.0 release. These problems will be fixed by the official Windows 4.0 release.
CRITICAL_SECTION |
HSEMAPHORE |
InitializeCriticalSection | |
EnterCriticalSection | |
LeaveCriticalSection | |
DeleteCriticalSection |
Note that where storage for a critical section was provided by the caller (the functions took a pointer to the critical section), the semaphore routines always use a handle (storage is allocated and destroyed within the semaphore routines).
Win32 Debug Function |
GDI Debug Function |
DebugBreak | |
OutputDebugString |
VOID DebugPrint(LONG DebugPrintLevel, PCHAR DebugMessage, ...) { #define STANDARD_DEBUG_PREFIX "MyDisplay:" va_list ap; va_start(ap, Debugmessage); if (DebugPrintLevel <= DebugLevel) { EngDebugPrint(STANDARD_DEBUG_PREFIX, DebugMessage, ap); // The following line appends the newline // automatically. // EngDebugPrint("", "\n", ap); } va_end(ap); }
Win32 Memory Function |
KM GDI Memory Function |
LocalAlloc, GlobalAlloc, VirtualAlloc | |
VirtualFree, GlobalFree | |
LocalLock, GlobalLock, LocalUnlock, GlobalUnlock |
none (not used) |
ppdef = (PPDEF) EngAllocMem(FL_ZERO_MEMORY, sizeof(PDEV),'agxD');
Note Memory is often referred to as pool in the kernel. The kernel memory functions are actually called ExAllocatePool and ExFreePool.
Note Heaps are not supported in kernel mode, so you cannot destroy the heap to clean up memory.
Any remaining Win32 functions in the original Windows NT 3.51 driver must be removed. If your driver absolutely requires a function that is not currently exposed, then Microsoft should be made aware of this requirement so the function can be exposed or an appropriate alternative can be found.
String routines, such as strcmp, are not exported from win32k.sys. Calls to these routines should be removed if possible. Limited C-runtime functionality is available in libcntpr.lib, which statically links to the driver.
Don’t use native floating point operations. Windows NT does not support kernel-mode floating point operations on some systems. Specifically, the Windows NT kernel does not preserve floating point registers on kernel-mode stack switches, so using floating point registers in the driver corrupts an application’s floating point registers.
GDI has introduced a new set of services that allows graphics drivers to emulate floating point arithmetic. See the reference pages for the FLOATOBJ_Xxx services for more information.
Each thread is allocated a limited amount of stack space for all function calls and interrupts. The Windows NT kernel allocates an initial 12K on x86 and MIPS platforms, and 16K on ALPHA and PowerPC platforms. The stack can grow to accommodate callbacks from the kernel to user mode and back; the maximum stack size is 60K/64K in the kernel. Only 12K/16K of the stack is visible at any point in time. The only exception to these policies is OpenGL, which is allocated the entire 60K/64K stack at once.
In Microsoft’s driver design, a guideline of 1K of stack space per function is used. This heuristic was arrived at by studying the stack needs of a typical graphics driver. The first few kilobytes on the stack contain the functions called to get from the application to the driver, such as the system service functions. The last 2-3 kilobytes are reserved for page faults and interrupts. The fact that some driver calls spawn several nested function calls is also accounted for. For example, the S3’s implementation of DrvStretchBlt calls EngStretchBlt, which calls DrvBitBlt, which calls another internal S3 fill function. Using the 1K per function guideline means that only up to 4K of the stack is used for these four functions.
You should also look at the size of your functions’ parameters. Only small structures and very small arrays of data should be stored on the stack. Arrays of 1024 or 512 elements and arrays the size of the screen’s width should not be passed. Consider the following: if each array element is a DWORD, 1024 elements uses 4K of stack space.
Memory beyond the stack pointer should not be touched in assembly routines because interrupts can occur at any time.
A routine is guaranteed to be using too much stack space if you get an undefined external for something such as _chkstk.
Because all Windows NT 3.51 drivers are incompatible in Windows NT 4.0, a few things have been cleaned up in the drivers:
The section entitled Special Features of a User-Mode Process, described earlier in this document, should be examined. Drivers depending on any of these features must be changed to avoid these problems.
The sections that follow this one are Porting Steps for Display Drivers and Porting Steps for Printer Drivers. Read the section that pertains to your driver type for additional type-specific porting hints.
Install your new driver, and test. Use the kernel-mode kd debugger or windbg to debug your driver. NTSD can no longer be used for debugging graphics drivers.