reactos操作系统实现(159)

前端之家收集整理的这篇文章主要介绍了reactos操作系统实现(159)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

NtUserRegisterClassEx函数Win32k.sys里实现窗口类的注册,那么窗口类的注册是什么意思呢?到底注册是为了什么样的目的呢?下面就通过实现代码的分析来解决这些问题,代码如下:

#001 RTL_ATOM APIENTRY

#002 NtUserRegisterClassEx(IN CONST WNDCLASSEXW* lpwcx,

#003 IN PUNICODE_STRING ClassName,

#004 IN PUNICODE_STRING MenuName,

#005 IN WNDPROC wpExtra,

#006 IN DWORD Flags,

#007 IN HMENU hMenu)

#008

#009 /*

#010 * FUNCTION:

#011 * Registers a new class with the window manager

#012 * ARGUMENTS:

#013 * lpwcx = Win32 extended window class structure

#014 * bUnicodeClass = Whether to send ANSI or unicode strings

#015 * to window procedures

#016 * wpExtra = Extra window procedure,if this is not null,its used for the second window procedure for standard controls.

#017 * RETURNS:

#018 * Atom identifying the new class

#019 */

#020 {

#021 WNDCLASSEXW CapturedClassInfo = {0};

#022 UNICODE_STRING CapturedName = {0},CapturedMenuName = {0};

#023 RTL_ATOM Ret = (RTL_ATOM)0;

#024

如果注册标志有问题,就直接返回出错。

#025 if (Flags & ~REGISTERCLASS_ALL)

#026 {

#027 SetLastWin32Error(ERROR_INVALID_FLAGS);

#028 return Ret;

#029 }

#030

增加用户进入锁,以便后面的代码进行临界区访问。

#031 UserEnterExclusive();

#032

使用异常机制处理用户输入来的参数。

#033 _SEH2_TRY

#034 {

注册类的结构大小是否符合内核的注册类的结构大小,如果不符合就返回出错。

#035 /* Probe the parameters and basic parameter checks */

#036 if (ProbeForReadUint(&lpwcx->cbSize) != sizeof(WNDCLASSEXW))

#037 {

#038 goto InvalidParameter;

#039 }

#040

检查读取是否出错。

#041 ProbeForRead(lpwcx,

#042 sizeof(WNDCLASSEXW),

#043 sizeof(ULONG));

拷贝用户空间的注册类信息。

#044 RtlCopyMemory(&CapturedClassInfo,

#045 lpwcx,

#046 sizeof(WNDCLASSEXW));

#047

读取注册窗口类的名称

#048 CapturedName = ProbeForReadUnicodeString(ClassName);

读取注册窗口类的菜单名称

#049 CapturedMenuName = ProbeForReadUnicodeString(MenuName);

#050

窗口类的非法参数检查。

#051 if (CapturedName.Length & 1 || CapturedMenuName.Length & 1 ||

#052 CapturedClassInfo.cbClsExtra < 0 ||

#053 CapturedClassInfo.cbClsExtra + CapturedName.Length +

#054 CapturedMenuName.Length + sizeof(WINDOWCLASS) < CapturedClassInfo.cbClsExtra ||

#055 CapturedClassInfo.cbWndExtra < 0 ||

#056 CapturedClassInfo.hInstance == NULL)

#057 {

#058 goto InvalidParameter;

#059 }

#060

#061 if (CapturedName.Length != 0)

#062 {

#063 ProbeForRead(CapturedName.Buffer,

#064 CapturedName.Length,

#065 sizeof(WCHAR));

#066 }

#067 else

#068 {

#069 if (!IS_ATOM(CapturedName.Buffer))

#070 {

#071 goto InvalidParameter;

#072 }

#073 }

#074

#075 if (CapturedMenuName.Length != 0)

#076 {

#077 ProbeForRead(CapturedMenuName.Buffer,

#078 CapturedMenuName.Length,

#079 sizeof(WCHAR));

#080 }

#081 else if (CapturedMenuName.Buffer != NULL &&

#082 !IS_INTRESOURCE(CapturedMenuName.Buffer))

#083 {

#084 InvalidParameter:

#085 SetLastWin32Error(ERROR_INVALID_PARAMETER);

#086 _SEH2_LEAVE;

#087 }

#088

调用函数UserRegisterClass来更进一步处理注册过程。

#089 /* Register the class */

#090 Ret = UserRegisterClass(&CapturedClassInfo,

#091 &CapturedName,

#092 &CapturedMenuName,

#093 hMenu,/* FIXME - pass pointer */

#094 wpExtra,

#095 Flags);

#096

#097 }

#098 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)

#099 {

#100 SetLastNtError(_SEH2_GetExceptionCode());

#101 }

#102 _SEH2_END;

#103

退出临界区。

#104 UserLeave();

#105

#106 return Ret;

#107 }

#108

上面调用函数UserRegisterClass来更进一步处理,因而再接着分析这个函数的实现,它的代码如下:

#001 RTL_ATOM

#002 UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,

#005 IN HANDLE hMenu,/* FIXME */

#006 IN WNDPROC wpExtra,

#007 IN DWORD dwFlags)

#008 {

#009 PTHREADINFO pti;

#010 PW32THREADINFO ti;

#011 PW32PROCESSINFO pi;

#012 PWINDOWCLASS Class;

#013 RTL_ATOM ClassAtom;

#014 RTL_ATOM Ret = (RTL_ATOM)0;

#015

#016 /* NOTE: Accessing the buffers in ClassName and MenuName may raise exceptions! */

#017

获取当前线程信息。

#018 pti = PsGetCurrentThreadWin32Thread();

#019 ti = GetW32ThreadInfo();

#020 if (ti == NULL || !ti->kpi->RegisteredSysClasses)

#021 {

#022 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);

#023 return (RTL_ATOM)0;

#024 }

#025

#026 pi = ti->kpi;

#027

查找以前是否注册过相同名称的窗口类。

#028 /* try to find a prevIoUsly registered class */

#029 ClassAtom = IntGetClassAtom(ClassName,

#030 lpwcx->hInstance,

#031 pi,

#032 &Class,

#033 NULL);

#034 if (ClassAtom != (RTL_ATOM)0)

#035 {

如果窗口类已经注册过,就返回相应的出错信息。

#036 if (lpwcx->style & CS_GLOBALCLASS)

#037 {

#038 // global classes shall not have same names as system classes

#039 if (Class->Global || Class->System)

#040 {

#041 DPRINT("Class 0x%p does already exist!/n",ClassAtom);

#042 SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);

#043 return (RTL_ATOM)0;

#044 }

#045 }

#046 else if ( !Class->Global && !Class->System)

#047 {

#048 // local class already exists

#049 DPRINT("Class 0x%p does already exist!/n",ClassAtom);

#050 SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);

#051 return (RTL_ATOM)0;

#052 }

#053 }

#054

调用函数IntCreateClass来创建一个窗口类。

#055 Class = IntCreateClass(lpwcx,

#056 ClassName,

#057 MenuName,

#058 wpExtra,

#059 dwFlags,

#060 pti->Desktop,

#061 pi);

#062

如果创建注册类成功,就把这个窗口类保存到系统相应的列表里。

#063 if (Class != NULL)

#064 {

#065 PWINDOWCLASS *List;

#066

保存菜单句柄。

#067 /* FIXME - pass the PMENU pointer to IntCreateClass instead! */

#068 Class->hMenu = hMenu;

#069

根据注册类的使用范围来保存不同的系统列表里。

#070 /* Register the class */

#071 if (Class->System)

#072 List = &pi->SystemClassList;

#073 else if (Class->Global)

#074 List = &pi->GlobalClassList;

#075 else

#076 List = &pi->LocalClassList;

#077

列表插入操作。

#078 Class->Next = *List;

#079 (void)InterlockedExchangePointer((PVOID*)List,

#080 Class);

#081

#082 Ret = Class->Atom;

#083 }

#084

#085 return Ret;

#086 }

通过上面的分析,可以了解到注册一个窗口类,就是分配一个新的窗口类内存结构,然后设置结构的字段,最后把它保存到合适的列表里。

原文链接:https://www.f2er.com/react/308363.html

猜你在找的React相关文章