一个会话是一个登录用户的实例,它包含了自己的窗口管理,桌面,shell和应用程序。最显著的就是windows xp的快速用户切换,即你可以在一台机器上登录多个用户。每个用户实际上有一个独有的会话和一个独有的内核内存范围,我们称为会话空间。
当设计一个视频驱动的时候,你会遇到一个问题。就是说,如果你的迷你小端口驱动可能处理的那个内存超出了当前会话上下文,你不能简单地传递任意的内存到你的迷你小端口驱动。这里有个例子传递这个内存给系统进程中的另外的线程来处理。
如果系统进程没有关联你的会话,你将会访问一个不同的内存区域,而不是你想的那样。当这个发生时,你会得到"A driver has not been correctly ported to Terminal Services"这样的蓝屏信息。
显示驱动不象到目前为止我们接触过的驱动那样。但它仍然是pe格式。它不象迷你小端口驱动那样,是一个连接到一个不同框架的正规的内核驱动。它不能直接通过连接到内核而使用内核api,并且由于前面说明的原因也不能使用他们。如果你的api传递的内存超出了会话空间,那么你就会蓝屏,除非你保证你只是传递了系统内存。这是另一个为什么只能使用Eng* API函数集的原因。然而,你可以从迷你小端口驱动请求一个函数指针表,没有什么东西会阻止你这么做。
任何时候,显示驱动同普通驱动相比表现的更像一个dll,实际上它也是被看作是一个dll.这个驱动框架被绑定在WIN32K.SYS上,WIN32K.SYS实现了windows管理器和GDI.这个驱动编译使用"-entry:DrvEnableDriver@12 /SUBSYSTEM:NATIVE",其中DrvEnableDriver作为显示驱动的入口点。
DrvEnableDriver
DrvEnableDriver是显示驱动的初始入口点。它与DriverEntry没有任何关系。这个API入口参数有一个DRVENABLEDATA结构,这个结构需要使用一个指向驱动入口的函数表来填充。这个表包含了一系列函数指针的索引值和函数指针。其中索引值表示了函数类型,就像"INDEX_DrvCompletePDEV"是指它对应的函数指针是指向驱动中一个DrvCompletePDEV型的处理函数。其中一些API是可选的,但有一些是必须的。
这个入口点为了返回你的函数序列负责。你也可以在这里做一些你需要的初始化动作。下面的代码来自于本文的显示驱动例子。
/*
* Display Drivers provide a list of function entry points for specific GDI
* tasks. These are identified by providing a pre-defined "INDEX" value (pre-
* defined
* by microsoft) followed by the function entry point. There are levels of
* flexibility
* on which ones you are REQUIRED and which ones are technically OPTIONAL.
*
*/
DRVFN g_DrvFunctions[] =
{
{ INDEX_DrvAssertMode, (PFN) GdiExample_DrvAssertMode },
{ INDEX_DrvCompletePDEV, (PFN) GdiExample_DrvCompletePDEV },
{ INDEX_DrvCreateDeviceBitmap, (PFN) GdiExample_DrvCreateDeviceBitmap },
{ INDEX_DrvDeleteDeviceBitmap, (PFN) GdiExample_DrvDeleteDeviceBitmap },
{ INDEX_DrvDestroyFont, (PFN) GdiExample_DrvDestroyFont },
{ INDEX_DrvDisablePDEV, (PFN) GdiExample_DrvDisablePDEV },
{ INDEX_DrvDisableDriver, (PFN) GdiExample_DrvDisableDriver },
{ INDEX_DrvDisableSurface, (PFN) GdiExample_DrvDisableSurface },
{ INDEX_DrvSaveScreenBits, (PFN) GdiExample_DrvSaveScreenBits },
{ INDEX_DrvEnablePDEV, (PFN) GdiExample_DrvEnablePDEV },
{ INDEX_DrvEnableSurface, (PFN) GdiExample_DrvEnableSurface },
{ INDEX_DrvEscape, (PFN) GdiExample_DrvEscape },
{ INDEX_DrvGetModes, (PFN) GdiExample_DrvGetModes },
{ INDEX_DrvMovePointer, (PFN) GdiExample_DrvMovePointer },
{ INDEX_DrvNotify, (PFN) GdiExample_DrvNotify },
// { INDEX_DrvRealizeBrush, (PFN) GdiExample_DrvRealizeBrush },
{ INDEX_DrvResetPDEV, (PFN) GdiExample_DrvResetPDEV },
{ INDEX_DrvSetPalette, (PFN) GdiExample_DrvSetPalette },
{ INDEX_DrvSetPointerShape, (PFN) GdiExample_DrvSetPointerShape },
{ INDEX_DrvStretchBlt, (PFN) GdiExample_DrvStretchBlt },
{ INDEX_DrvSynchronizeSurface, (PFN) GdiExample_DrvSynchronizeSurface },
{ INDEX_DrvAlphaBlend, (PFN) GdiExample_DrvAlphaBlend },
{ INDEX_DrvBitBlt, (PFN) GdiExample_DrvBitBlt },
{ INDEX_DrvCopyBits, (PFN) GdiExample_DrvCopyBits },
{ INDEX_DrvFillPath, (PFN) GdiExample_DrvFillPath },
{ INDEX_DrvGradientFill, (PFN) GdiExample_DrvGradientFill },
{ INDEX_DrvLineTo, (PFN) GdiExample_DrvLineTo },
{ INDEX_DrvStrokePath, (PFN) GdiExample_DrvStrokePath },
{ INDEX_DrvTextOut, (PFN) GdiExample_DrvTextOut },
{ INDEX_DrvTransparentBlt, (PFN) GdiExample_DrvTransparentBlt },
};
ULONG g_ulNumberOfFunctions = sizeof(g_DrvFunctions) / sizeof(DRVFN);
/*********************************************************************
* DrvEnableDriver
*
* This is the initial driver entry point. This is the "DriverEntry"
* equivlent for Display and Printer drivers. This function must
* return a function table that represents all the supported entry
* points into this driver.
*
*********************************************************************/
BOOL DrvEnableDriver(ULONG ulEngineVersion,
ULONG ulDataSize, DRVENABLEDATA *pDrvEnableData)
{
BOOL bDriverEnabled = FALSE;
/*
* We only want to support versions > NT 4
*
*/
if(HIWORD(ulEngineVersion) >= 0x3 &&
ulDataSize >= sizeof(DRVENABLEDATA))
{
pDrvEnableData->iDriverVersion = DDI_DRIVER_VERSION;
pDrvEnableData->pdrvfn = g_DrvFunctions;
pDrvEnableData->c = g_ulNumberOfFunctions;
bDriverEnabled = TRUE;
}
return bDriverEnabled;