win32k在被载入内存后,执行DriverEntry的入口函数
NTSTATUS STDCALL
DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
......
GlobalUserHeap = UserCreateHeap(&GlobalUserHeapSection,
&GlobalUserHeapBase,
1 * 1024 * 1024); /* FIXME - 1 MB for now... */
......
GdiHandleTable = GDIOBJ_iAllocHandleTable(&GdiTableSection);
......
}
该函数建立了一个包含了win32k的一个会话空间的全局用户堆,不过只有1M大小,感觉有点小。同时win32k初始化时,还为该会话空间的GDI对象(DC, PEN, FONT, BITMAP REGION等对象)建立了一个专有的句柄表 GdiHandleTable ,专门存放系统或用户建立的GDI对象句柄,不过GDI对象体是在换页池中申请的,而句柄表中仅仅存放了返回给用户空间的GDI对象句柄(对象在句柄表中的索引号)而已。
在创建一个窗口时,窗口创建函数调用UserCreateObject为窗口分配内存空间,这时窗口是作为一种对象来管理(此对象非C++对象,说白了其实就是一块包含窗口信息的内存块),
UserCreateObject函数的功能就是调用UserHeapAlloc函数在GlobalUserHeap堆中分配“对象”,这里就是窗口对象,并调用UserAllocHandle函数将指定的对象插入到指定的句柄表中,并返回该对象在句柄表中的句柄(起始就是该对象在句柄表中的索引号)
而前面在调用UserCreateObject函数时指定了gHandleTable作为句柄表,而全局gHandleTable句柄表又是通过UserCreateHandleTable函数同样也是在GlobalUserHeap堆中分配内存空间
在句柄表中存放了窗口对象,但是表示窗口坐标的信息是存放在桌面堆中的。在win32k中,当启动一个进程后,会为这个进程的所有线程建立一个win32线程信息块,这个信息块中的hdesktop描述了该win32线程属于那个桌面,而桌面是作为所有属于该桌面的进程共享的资源,只有将桌面上的所有窗口放入不同进程的共享区域,内核的win32窗口函数才能找到这些窗口数据并协调彼此的显示。桌面窗口在 winlogon中被创建起来。
桌面堆:
在初始化桌面对象时,win32k调用NtUserCreateDesktop建立桌面对象的同时也为该桌面创建了一个桌面堆
HDESK STDCALL
NtUserCreateDesktop(
PUNICODE_STRING lpszDesktopName,
DWORD dwFlags,
ACCESS_MASK dwDesiredAccess,
LPSECURITY_ATTRIBUTES lpSecurity,
HWINSTA hWindowStation)
{
......
DesktopObject->hDesktopHeap = UserCreateHeap(&DesktopObject->DesktopHeapSection,
&DesktopHeapSystemBase,
HeapLimit);
......
}
至于桌面堆的大小目前是4M