reactos操作系统实现(162)

co_IntCreateWindowEx函数主要用创建一个显示的窗口,具体实现代码如下:

#001  HWND APIENTRY

#002  co_IntCreateWindowEx(DWORD dwExStyle,

#003                       PUNICODE_STRING ClassName,

#004                       PUNICODE_STRING WindowName,

#005                       DWORD dwStyle,

#006                       LONG x,

#007                       LONG y,

#008                       LONG nWidth,

#009                       LONG nHeight,

#010                       HWND hWndParent,

#011                       HMENU hMenu,

#012                       HINSTANCE hInstance,

#013                       LPVOID lpParam,

#014                       DWORD dwShowMode,

#015                       BOOL bUnicodeWindow)

#016  {

#017     PWINSTATION_OBJECT WinSta;

#018     PWINDOW Wnd = NULL;

#019     PWINDOWCLASS *ClassLink, Class = NULL;

#020     RTL_ATOM ClassAtom;

#021     PWINDOW_OBJECT Window = NULL;

#022     PWINDOW_OBJECT ParentWindow = NULL, OwnerWindow;

#023     HWND ParentWindowHandle;

#024     HWND OwnerWindowHandle;

#025     PMENU_OBJECT SystemMenu;

#026     HWND hWnd;

#027     POINT Pos;

#028     SIZE Size;

#029     PW32THREADINFO ti = NULL;

#030  #if 0

#031 

#032     POINT MaxSize, MaxPos, MinTrack, MaxTrack;

#033  #else

#034 

#035     POINT MaxPos;

#036  #endif

#037     CREATESTRUCTW Cs;

#038     CBT_CREATEWNDW CbtCreate;

#039     LRESULT Result;

#040     BOOL MenuChanged;

#041     DECLARE_RETURN(HWND);

#042     BOOL HasOwner;

#043     USER_REFERENCE_ENTRY ParentRef, Ref;

#044     PTHREADINFO pti;

#045 

 

获取当前运行的线程。

#046     pti = PsGetCurrentThreadWin32Thread();

 

获取桌面窗口作为父窗口。

#047     ParentWindowHandle = pti->Desktop->DesktopWindow;

#048     OwnerWindowHandle = NULL;

#049 

 

是否为创建消息窗口。

#050     if (hWndParent == HWND_MESSAGE)

#051     {

#052        /*

#053         * native ole32.OleInitialize uses HWND_MESSAGE to create the

#054         * message window (style: WS_POPUP|WS_DISABLED)

#055         */

#056        DPRINT1("FIXME - Parent is HWND_MESSAGE/n");

#057        // ParentWindowHandle set already.     

#058     }

 

是否已经父窗口。

#059     else if (hWndParent)

#060     {

#061        if ((dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)

#062        {  //temp hack

#063           PWINDOW_OBJECT Par = UserGetWindowObject(hWndParent), Root;

#064           if (Par && (Root = UserGetAncestor(Par, GA_ROOT)))

#065              OwnerWindowHandle = Root->hSelf;

#066        }

#067        else

#068           ParentWindowHandle = hWndParent;

#069     }

 

如果又设置为子窗口属性,但又没有父窗口,就提示出错返回。

#070     else if ((dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD)

#071     {

#072        SetLastWin32Error(ERROR_TLW_WITH_WSCHILD);

#073        RETURN( (HWND)0);  /* WS_CHILD needs a parent, but WS_POPUP doesn't */

#074     }

#075 

 

获取父窗口对象。

#076  //   if (NULL != ParentWindowHandle)

#077  //   {

#078     ParentWindow = UserGetWindowObject(ParentWindowHandle);

#079 

#080     if (ParentWindow) UserRefObjectCo(ParentWindow, &ParentRef);

#081  //   }

#082  //   else

#083  //   {

#084  //      ParentWindow = NULL;

#085  //   }

#086 

#087     /* FIXME: parent must belong to the current process */

#088 

 

检查WINDOWS的线程信息。

#089     /* Check the window station. */

#090     ti = GetW32ThreadInfo();

#091     if (ti == NULL || pti->Desktop == NULL)

#092     {

#093        DPRINT1("Thread is not attached to a desktop! Cannot create window!/n");

#094        RETURN( (HWND)0);

#095     }

#096 

#097     /* Check the class. */

#098 

 

检查要创建的窗口类是否已经注册好。

#099     ClassAtom = IntGetClassAtom(ClassName,

#100                                 hInstance,

#101                                 ti->kpi,

#102                                 &Class,

#103                                 &ClassLink);

#104 

#105     if (ClassAtom == (RTL_ATOM)0)

#106     {

#107        if (IS_ATOM(ClassName->Buffer))

#108        {

#109           DPRINT1("Class 0x%p not found/n", (DWORD_PTR) ClassName->Buffer);

#110        }

#111        else

#112        {

#113           DPRINT1("Class /"%wZ/" not found/n", ClassName);

#114        }

#115 

#116        SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS);

#117        RETURN((HWND)0);

#118     }

#119  

 

增加已经注册好的窗口类引用计数。

#120     Class = IntReferenceClass(Class,

#121                               ClassLink,

#122                               pti->Desktop);

#123     if (Class == NULL)

#124     {

#125         DPRINT1("Failed to reference window class!/n");

#126         RETURN(NULL);

#127     }

#128 

 

获取桌面工作站。

#129     WinSta = pti->Desktop->WindowStation;

#130 

#131     //FIXME: Reference thread/desktop instead

#132     ObReferenceObjectByPointer(WinSta, KernelMode, ExWindowStationObjectType, 0);

#133 

 

调用函数UserCreateObject创建窗口对象。

#134     /* Create the window object. */

#135     Window = (PWINDOW_OBJECT)

#136              UserCreateObject(gHandleTable, (PHANDLE)&hWnd,

#137                              otWindow, sizeof(WINDOW_OBJECT));

#138     if (Window)

#139     {

 

分配窗口所占用的堆空间。

#140         Window->Wnd = DesktopHeapAlloc(pti->Desktop,

#141                                        sizeof(WINDOW) + Class->WndExtra);

#142         if (!Window->Wnd)

#143             goto AllocErr;

#144         RtlZeroMemory(Window->Wnd,

#145                       sizeof(WINDOW) + Class->WndExtra);

#146         Window->Wnd->hdr.Handle = hWnd; /* FIXME: Remove hack */

#147         Wnd = Window->Wnd;

#148 

#149         Wnd->ti = ti;

#150         Wnd->pi = ti->kpi;

#151         Wnd->pdesktop = pti->Desktop;

#152         Wnd->hWndLastActive = hWnd;

#153     }

#154 

 

检查是否创建窗口对象成功。

#155     DPRINT("Created object with handle %X/n", hWnd);

#156     if (!Window)

#157     {

#158  AllocErr:

#159        ObDereferenceObject(WinSta);

#160        SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);

#161        RETURN( (HWND)0);

#162     }

#163 

 

增加引用窗口计数。

#164     UserRefObjectCo(Window, &Ref);

#165 

#166     ObDereferenceObject(WinSta);

#167 

 

如果还没有桌面窗口,说明当前创建的窗口就是桌面窗口。

#168     if (NULL == pti->Desktop->DesktopWindow)

#169     {

#170        /* If there is no desktop window yet, we must be creating it */

#171        pti->Desktop->DesktopWindow = hWnd;

#172        pti->Desktop->DesktopInfo->Wnd = Wnd;

#173     }

#174 

 

填写窗口描述结构。

#175     /*

#176      * Fill out the structure describing it.

#177      */

#178     Window->ti = ti;

#179     Wnd->Class = Class;

#180     Class = NULL;

#181 

#182     Window->SystemMenu = (HMENU)0;

#183     Wnd->ContextHelpId = 0;

#184     Wnd->IDMenu = 0;

#185     Wnd->Instance = hInstance;

#186     Window->hSelf = hWnd;

#187 

 

设置窗口消息队列。

#188     Window->MessageQueue = pti->MessageQueue;

#189     IntReferenceMessageQueue(Window->MessageQueue);

#190     Window->Parent = ParentWindow;

#191     Wnd->Parent = ParentWindow ? ParentWindow->Wnd : NULL;

#192     if (Wnd->Parent != NULL && hWndParent != 0)

#193     {

#194         Wnd->HideFocus = Wnd->Parent->HideFocus;

#195         Wnd->HideAccel = Wnd->Parent->HideAccel;

#196     }

#197 

 

设置属于那一个窗口。

#198     if((OwnerWindow = UserGetWindowObject(OwnerWindowHandle)))

#199     {

#200        Window->hOwner = OwnerWindowHandle;

#201        Wnd->Owner = OwnerWindow->Wnd;

#202        HasOwner = TRUE;

#203     }

#204     else

#205     {

#206        Window->hOwner = NULL;

#207        Wnd->Owner = NULL;

#208        HasOwner = FALSE;

#209     }

#210 

 

窗口用户数据设置为0.

#211     Wnd->UserData = 0;

#212 

#213     Wnd->IsSystem = Wnd->Class->System;

#214 

#215     /* BugBoy Comments: Comment below say that System classes are always created as UNICODE.

#216        In windows, creating a window with the ANSI version of CreateWindow sets the window

#217        to ansi as verified by testing with IsUnicodeWindow API.

#218 

#219        No where can I see in code or through testing does the window change back to ANSI

#220        after being created as UNICODE in ROS. I didnt do more testing to see what problems this would cause.*/

#221      // See NtUserDefSetText! We convert to Unicode all the time and never use Mix. (jt)

 

根据是否系统里定义的窗口类来选择是否使用UNICODE的窗口。

#222     if (Wnd->Class->System)

#223     {

#224         /* NOTE: Always create a unicode window for system classes! */

#225         Wnd->Unicode = TRUE;

#226         Wnd->WndProc = Wnd->Class->WndProc;

#227         Wnd->WndProcExtra = Wnd->Class->WndProcExtra;

#228     }

#229     else

#230     {

#231         Wnd->Unicode = Wnd->Class->Unicode;

#232         Wnd->WndProc = Wnd->Class->WndProc;

#233         Wnd->CallProc = NULL;

#234     }

#235 

 

设置当前窗口的线程。

#236     Window->OwnerThread = PsGetCurrentThread();

#237     Window->FirstChild = NULL;

#238     Window->LastChild = NULL;

#239     Window->PrevSibling = NULL;

#240     Window->NextSibling = NULL;

#241     Wnd->ExtraDataSize = Wnd->Class->WndExtra;

#242 

#243     InitializeListHead(&Wnd->PropListHead);

#244     InitializeListHead(&Window->WndObjListHead);

#245 

 

设置窗口的名称。

#246     if (NULL != WindowName->Buffer && WindowName->Length > 0)

#247     {

#248        Wnd->WindowName.Buffer = DesktopHeapAlloc(Wnd->pdesktop,

#249                                                  WindowName->Length + sizeof(UNICODE_NULL));

#250        if (Wnd->WindowName.Buffer == NULL)

#251        {

#252            SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);

#253            RETURN( (HWND)0);

#254        }

#255 

#256        Wnd->WindowName.Buffer[WindowName->Length / sizeof(WCHAR)] = L'/0';

#257        _SEH2_TRY

#258        {

#259            RtlCopyMemory(Wnd->WindowName.Buffer,

#260                          WindowName->Buffer,

#261                          WindowName->Length);

#262            Wnd->WindowName.Length = WindowName->Length;

#263        }

#264        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)

#265        {

#266            WindowName->Length = 0;

#267            Wnd->WindowName.Buffer[0] = L'/0';

#268        }

#269        _SEH2_END;

#270     }

#271 

 

检查是否创建对话框窗口。

#272     /*

#273      * This has been tested for WS_CHILD | WS_VISIBLE.  It has not been

#274      * tested for WS_POPUP

#275      */

#276     if ((dwExStyle & WS_EX_DLGMODALFRAME) ||

#277           ((!(dwExStyle & WS_EX_STATICEDGE)) &&

#278            (dwStyle & (WS_DLGFRAME | WS_THICKFRAME))))

#279        dwExStyle |= WS_EX_WINDOWEDGE;

#280     else

#281        dwExStyle &= ~WS_EX_WINDOWEDGE;

#282 

 

检查不是子窗口的属性是否对。

#283     /* Correct the window style. */

#284     if (!(dwStyle & WS_CHILD))

#285     {

#286        dwStyle |= WS_CLIPSIBLINGS;

#287        DPRINT("3: Style is now %lx/n", dwStyle);

#288        if (!(dwStyle & WS_POPUP))

#289        {

#290           dwStyle |= WS_CAPTION;

#291           Window->Flags |= WINDOWOBJECT_NEED_SIZE;

#292           DPRINT("4: Style is now %lx/n", dwStyle);

#293        }

#294     }

#295 

 

创建窗口系统菜单。

#296     /* create system menu */

#297     if((dwStyle & WS_SYSMENU) )//&& (dwStyle & WS_CAPTION) == WS_CAPTION)

#298     {

#299        SystemMenu = IntGetSystemMenu(Window, TRUE, TRUE);

#300        if(SystemMenu)

#301        {

#302           Window->SystemMenu = SystemMenu->MenuInfo.Self;

#303           IntReleaseMenuObject(SystemMenu);

#304        }

#305     }

#306 

 

设置窗口菜单。

#307     /* Set the window menu */

#308     if ((dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)

#309     {

#310        if (hMenu)

#311           IntSetMenu(Window, hMenu, &MenuChanged);

#312        else

#313        {

#314            hMenu = Wnd->Class->hMenu;

#315            if (hMenu) IntSetMenu(Window, hMenu, &MenuChanged);

#316        }

#317     }

#318     else

#319         Wnd->IDMenu = (UINT) hMenu;

#320 

 

把窗口添加到线程队列里。

#321     /* Insert the window into the thread's window list. */

#322     InsertTailList (&pti->WindowListHead, &Window->ThreadListEntry);

#323 

 

为窗口分配设备DC,可以分配窗口类的DC,也可以是窗口的DC。这里调用驱动程序来创建一个设备。

#324     /*  Handle "CS_CLASSDC", it is tested first. */

#325     if ((Wnd->Class->Style & CS_CLASSDC) && !(Wnd->Class->Dce)) // One DCE per class to have CLASS.

#326        Wnd->Class->Dce = DceAllocDCE(Window, DCE_CLASS_DC);

#327     /* Allocate a DCE for this window. */

#328     else if ( Wnd->Class->Style & CS_OWNDC)

#329        Window->Dce = DceAllocDCE(Window, DCE_WINDOW_DC);

#330 

 

设置窗口的位置和大小。

#331     Pos.x = x;

#332     Pos.y = y;

#333     Size.cx = nWidth;

#334     Size.cy = nHeight;

#335 

#336     Wnd->ExStyle = dwExStyle;

#337     Wnd->Style = dwStyle & ~WS_VISIBLE;

#338 

 

设置窗口HOOK

#339     /* call hook */

#340     Cs.lpCreateParams = lpParam;

#341     Cs.hInstance = hInstance;

#342     Cs.hMenu = hMenu;

#343     Cs.hwndParent = hWndParent; //Pass the original Parent handle!

#344     Cs.cx = Size.cx;

#345     Cs.cy = Size.cy;

#346     Cs.x = Pos.x;

#347     Cs.y = Pos.y;

#348     Cs.style = Wnd->Style;

#349     Cs.lpszName = (LPCWSTR) WindowName;

#350     Cs.lpszClass = (LPCWSTR) ClassName;

#351     Cs.dwExStyle = dwExStyle;

#352     CbtCreate.lpcs = &Cs;

#353     CbtCreate.hwndInsertAfter = HWND_TOP;

#354     if (co_HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) hWnd, (LPARAM) &CbtCreate))

#355     {

#356        /* FIXME - Delete window object and remove it from the thread windows list */

#357        /* FIXME - delete allocated DCE */

#358        DPRINT1("CBT-hook returned !0/n");

#359        RETURN( (HWND) NULL);

#360     }

#361 

#362     x = Cs.x;

#363     y = Cs.y;

#364     nWidth = Cs.cx;

#365     nHeight = Cs.cy;

#366 

 

计算重叠窗口位置和大小。

#367     /* default positioning for overlapped windows */

#368     if(!(Wnd->Style & (WS_POPUP | WS_CHILD)))

#369     {

#370        RECT rc, WorkArea;

#371        PRTL_USER_PROCESS_PARAMETERS ProcessParams;

#372        BOOL CalculatedDefPosSize = FALSE;

#373 

#374        IntGetDesktopWorkArea(((PTHREADINFO)Window->OwnerThread->Tcb.Win32Thread)->Desktop, &WorkArea);

#375 

#376        rc = WorkArea;

#377        ProcessParams = PsGetCurrentProcess()->Peb->ProcessParameters;

#378 

#379        if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16)

#380        {

#381           CalculatedDefPosSize = IntCalcDefPosSize(ParentWindow, Window, &rc, TRUE);

#382 

#383           if(ProcessParams->WindowFlags & STARTF_USEPOSITION)

#384           {

#385              ProcessParams->WindowFlags &= ~STARTF_USEPOSITION;

#386              Pos.x = WorkArea.left + ProcessParams->StartingX;

#387              Pos.y = WorkArea.top + ProcessParams->StartingY;

#388           }

#389           else

#390           {

#391              Pos.x = rc.left;

#392              Pos.y = rc.top;

#393           }

#394 

#395  /*

#396     According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and

#397     y is something else. and Quote!

#398   */

#399 

#400  /* Never believe Microsoft's documentation... CreateWindowEx doc says

#401   * that if an overlapped window is created with WS_VISIBLE style bit

#402   * set and the x parameter is set to CW_USEDEFAULT, the system ignores

#403   * the y parameter. However, disassembling NT implementation (WIN32K.SYS)

#404   * reveals that

#405   *

#406   * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16

#407   * 2) it does not ignore the y parameter as the docs claim; instead, it

#408   *    uses it as second parameter to ShowWindow() unless y is either

#409   *    CW_USEDEFAULT or CW_USEDEFAULT16.

#410   *

#411   * The fact that we didn't do 2) caused bogus windows pop up when wine

#412   * was running apps that were using this obscure feature. Example -

#413   * calc.exe that comes with Win98 (only Win98, it's different from

#414   * the one that comes with Win95 and NT)

#415   */

#416           if(y != CW_USEDEFAULT && y != CW_USEDEFAULT16)

#417           {

#418              dwShowMode = y;

#419           }

#420        }

#421        if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16)

#422        {

#423           if(!CalculatedDefPosSize)

#424           {

#425              IntCalcDefPosSize(ParentWindow, Window, &rc, FALSE);

#426           }

#427           if(ProcessParams->WindowFlags & STARTF_USESIZE)

#428           {

#429              ProcessParams->WindowFlags &= ~STARTF_USESIZE;

#430              Size.cx = ProcessParams->CountX;

#431              Size.cy = ProcessParams->CountY;

#432           }

#433           else

#434           {

#435              Size.cx = rc.right - rc.left;

#436              Size.cy = rc.bottom - rc.top;

#437           }

#438 

#439           /* move the window if necessary */

#440           if(Pos.x > rc.left)

#441              Pos.x = max(rc.left, 0);

#442           if(Pos.y > rc.top)

#443              Pos.y = max(rc.top, 0);

#444        }

#445     }

#446     else

#447     {

#448        /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */

#449        if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16)

#450        {

#451           Pos.x = 0;

#452           Pos.y = 0;

#453        }

#454        if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16)

#455        {

#456           Size.cx = 0;

#457           Size.cy = 0;

#458        }

#459     }

#460 

 

初始化窗口显示的大小。

#461     /* Initialize the window dimensions. */

#462     Wnd->WindowRect.left = Pos.x;

#463     Wnd->WindowRect.top = Pos.y;

#464     Wnd->WindowRect.right = Pos.x + Size.cx;

#465     Wnd->WindowRect.bottom = Pos.y + Size.cy;

#466     if (0 != (Wnd->Style & WS_CHILD) && ParentWindow)

#467     {

#468        IntGdiOffsetRect(&(Wnd->WindowRect), ParentWindow->Wnd->ClientRect.left,

#469                         ParentWindow->Wnd->ClientRect.top);

#470     }

#471     Wnd->ClientRect = Wnd->WindowRect;

#472 

#473     /*

#474      * Get the size and position of the window.

#475      */

#476     if ((dwStyle & WS_THICKFRAME) || !(dwStyle & (WS_POPUP | WS_CHILD)))

#477     {

#478        POINT MaxSize, MaxPos, MinTrack, MaxTrack;

#479 

#480        /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */

#481        co_WinPosGetMinMaxInfo(Window, &MaxSize, &MaxPos, &MinTrack,

#482                               &MaxTrack);

#483        if (MaxSize.x < Size.cx)

#484           Size.cx = MaxSize.x;

#485        if (MaxSize.y < Size.cy)

#486           Size.cy = MaxSize.y;

#487        if (Size.cx < MinTrack.x )

#488           Size.cx = MinTrack.x;

#489        if (Size.cy < MinTrack.y )

#490           Size.cy = MinTrack.y;

#491        if (Size.cx < 0)

#492           Size.cx = 0;

#493        if (Size.cy < 0)

#494           Size.cy = 0;

#495     }

#496 

#497     Wnd->WindowRect.left = Pos.x;

#498     Wnd->WindowRect.top = Pos.y;

#499     Wnd->WindowRect.right = Pos.x + Size.cx;

#500     Wnd->WindowRect.bottom = Pos.y + Size.cy;

#501     if (0 != (Wnd->Style & WS_CHILD) && ParentWindow)

#502     {

#503        IntGdiOffsetRect(&(Wnd->WindowRect), ParentWindow->Wnd->ClientRect.left,

#504                         ParentWindow->Wnd->ClientRect.top);

#505     }

 

窗口客户区的大小。

#506     Wnd->ClientRect = Wnd->WindowRect;

#507 

#508     /* FIXME: Initialize the window menu. */

#509 

#510     /* Send a NCCREATE message. */

#511     Cs.cx = Size.cx;

#512     Cs.cy = Size.cy;

#513     Cs.x = Pos.x;

#514     Cs.y = Pos.y;

#515 

#516     DPRINT("[win32k.window] IntCreateWindowEx style %d, exstyle %d, parent %d/n", Cs.style, Cs.dwExStyle, Cs.hwndParent);

#517     DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)/n", x, y, Size.cx, Size.cy);

#518     DPRINT("IntCreateWindowEx(): About to send NCCREATE message./n");

 

发送创建窗口的WM_NCCREATE消息。

#519     Result = co_IntSendMessage(Window->hSelf, WM_NCCREATE, 0, (LPARAM) &Cs);

#520     if (!Result)

#521     {

#522        /* FIXME: Cleanup. */

#523        DPRINT1("IntCreateWindowEx(): NCCREATE message failed. No cleanup performed!/n");

#524        RETURN((HWND)0);

#525     }

#526 

 

计算非窗户客户端的大小。

#527     /* Calculate the non-client size. */

#528     MaxPos.x = Window->Wnd->WindowRect.left;

#529     MaxPos.y = Window->Wnd->WindowRect.top;

#530 

#531 

#532     DPRINT("IntCreateWindowEx(): About to get non-client size./n");

#533     /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */

#534     Result = co_WinPosGetNonClientSize(Window,

#535                                        &Window->Wnd->WindowRect,

#536                                        &Window->Wnd->ClientRect);

#537 

#538     IntGdiOffsetRect(&Window->Wnd->WindowRect,

#539                      MaxPos.x - Window->Wnd->WindowRect.left,

#540                      MaxPos.y - Window->Wnd->WindowRect.top);

#541 

#542 

 

如果父窗口不为空,说明本窗口是子窗口。

#543     if (NULL != ParentWindow)

#544     {

 

把本窗口连接到父窗口列表里。

#545        /* link the window into the parent's child list */

#546        if ((dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)

#547        {

#548           PWINDOW_OBJECT PrevSibling;

#549 

#550           PrevSibling = ParentWindow->LastChild;

#551 

#552           /* link window as bottom sibling */

#553           IntLinkWindow(Window, ParentWindow, PrevSibling /*prev sibling*/);

#554        }

#555        else

#556        {

#557           /* link window as top sibling (but after topmost siblings) */

#558           PWINDOW_OBJECT InsertAfter, Sibling;

#559           if (!(dwExStyle & WS_EX_TOPMOST))

#560           {

#561              InsertAfter = NULL;

#562              Sibling = ParentWindow->FirstChild;

#563              while (Sibling && (Sibling->Wnd->ExStyle & WS_EX_TOPMOST))

#564              {

#565                 InsertAfter = Sibling;

#566                 Sibling = Sibling->NextSibling;

#567              }

#568           }

#569           else

#570           {

#571              InsertAfter = NULL;

#572           }

#573 

#574           IntLinkWindow(Window, ParentWindow, InsertAfter /* prev sibling */);

#575 

#576        }

#577     }

#578 

 

发送创建窗口的WM_CREATE消息。

#579     /* Send the WM_CREATE message. */

#580     DPRINT("IntCreateWindowEx(): about to send CREATE message./n");

#581     Result = co_IntSendMessage(Window->hSelf, WM_CREATE, 0, (LPARAM) &Cs);

#582 

#583     if (Result == (LRESULT)-1)

#584     {

#585        /* FIXME: Cleanup. */

#586        DPRINT1("IntCreateWindowEx(): send CREATE message failed. No cleanup performed!/n");

#587        IntUnlinkWindow(Window);

#588        RETURN((HWND)0);

#589     }

#590  #if 0

#591     Result = IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_WINDOW, 0);

#592 

#593     if (Result == (LRESULT)-1)

#594     {

#595        /* FIXME: Cleanup. */

#596        DPRINT1("IntCreateWindowEx(): event CREATE hook failed. No cleanup performed!/n");

#597        IntUnlinkWindow(Window);

#598        RETURN((HWND)0);

#599     }

#600  #endif

 

发送窗口设置大小的WM_SIZE消息。

#601     /* Send move and size messages. */

#602     if (!(Window->Flags & WINDOWOBJECT_NEED_SIZE))

#603     {

#604        LONG lParam;

#605 

#606        DPRINT("IntCreateWindow(): About to send WM_SIZE/n");

#607 

#608        if ((Window->Wnd->ClientRect.right - Window->Wnd->ClientRect.left) < 0 ||

#609              (Window->Wnd->ClientRect.bottom - Window->Wnd->ClientRect.top) < 0)

#610        {

#611           DPRINT("Sending bogus WM_SIZE/n");

#612        }

#613 

#614        lParam = MAKE_LONG(Window->Wnd->ClientRect.right -

#615                           Window->Wnd->ClientRect.left,

#616                           Window->Wnd->ClientRect.bottom -

#617                           Window->Wnd->ClientRect.top);

#618        co_IntSendMessage(Window->hSelf, WM_SIZE, SIZE_RESTORED,

#619                          lParam);

#620 

#621        DPRINT("IntCreateWindow(): About to send WM_MOVE/n");

#622 

 

发送窗口移动到某位置的WM_MOVE消息。

#623        if (0 != (Wnd->Style & WS_CHILD) && ParentWindow)

#624        {

#625           lParam = MAKE_LONG(Wnd->ClientRect.left - ParentWindow->Wnd->ClientRect.left,

#626                              Wnd->ClientRect.top - ParentWindow->Wnd->ClientRect.top);

#627        }

#628        else

#629        {

#630           lParam = MAKE_LONG(Wnd->ClientRect.left,

#631                              Wnd->ClientRect.top);

#632        }

#633 

#634        co_IntSendMessage(Window->hSelf, WM_MOVE, 0, lParam);

#635 

#636        /* Call WNDOBJ change procs */

#637        IntEngWindowChanged(Window, WOC_RGN_CLIENT);

#638     }

#639 

 

设置窗口最大化或最小化显示。

#640     /* Show or maybe minimize or maximize the window. */

#641     if (Wnd->Style & (WS_MINIMIZE | WS_MAXIMIZE))

#642     {

#643        RECT NewPos;

#644        UINT16 SwFlag;

#645 

#646        SwFlag = (Wnd->Style & WS_MINIMIZE) ? SW_MINIMIZE :

#647                 SW_MAXIMIZE;

#648 

#649        co_WinPosMinMaximize(Window, SwFlag, &NewPos);

#650 

#651        SwFlag = ((Wnd->Style & WS_CHILD) || UserGetActiveWindow()) ?

#652                  SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED :

#653                  SWP_NOZORDER | SWP_FRAMECHANGED;

#654 

#655        DPRINT("IntCreateWindow(): About to minimize/maximize/n");

#656        DPRINT("%d,%d %dx%d/n", NewPos.left, NewPos.top, NewPos.right, NewPos.bottom);

#657        co_WinPosSetWindowPos(Window, 0, NewPos.left, NewPos.top,

#658                              NewPos.right, NewPos.bottom, SwFlag);

#659     }

#660 

 

如果是创建子窗口,通知父窗口已经创建了一个子窗口。

#661     /* Notify the parent window of a new child. */

#662     if ((Wnd->Style & WS_CHILD) &&

#663         (!(Wnd->ExStyle & WS_EX_NOPARENTNOTIFY)) && ParentWindow)

#664     {

#665        DPRINT("IntCreateWindow(): About to notify parent/n");

#666        co_IntSendMessage(ParentWindow->hSelf,

#667                          WM_PARENTNOTIFY,

#668                          MAKEWPARAM(WM_CREATE, Wnd->IDMenu),

#669                          (LPARAM)Window->hSelf);

#670     }

#671 

#672     if ((!hWndParent) && (!HasOwner))

#673     {

#674        DPRINT("Sending CREATED notify/n");

#675        co_IntShellHookNotify(HSHELL_WINDOWCREATED, (LPARAM)hWnd);

#676     }

#677     else

#678     {

#679        DPRINT("Not sending CREATED notify, %x %d/n", ParentWindow, HasOwner);

#680     }

#681 

 

设置窗口的滚动条。

#682     /* Initialize and show the window's scrollbars */

#683     if (Wnd->Style & WS_VSCROLL)

#684     {

#685        co_UserShowScrollBar(Window, SB_VERT, TRUE);

#686     }

#687     if (Wnd->Style & WS_HSCROLL)

#688     {

#689        co_UserShowScrollBar(Window, SB_HORZ, TRUE);

#690     }

#691 

 

设置窗口显示方式。

#692     if (dwStyle & WS_VISIBLE)

#693     {

#694        if (Wnd->Style & WS_MAXIMIZE)

#695           dwShowMode = SW_SHOW;

#696        else if (Wnd->Style & WS_MINIMIZE)

#697           dwShowMode = SW_SHOWMINIMIZED;

#698 

#699        DPRINT("IntCreateWindow(): About to show window/n");

#700        co_WinPosShowWindow(Window, dwShowMode);

#701 

#702        if (Wnd->ExStyle & WS_EX_MDICHILD)

#703        {

#704          co_IntSendMessage(ParentWindow->hSelf, WM_MDIREFRESHMENU, 0, 0);

#705          /* ShowWindow won't activate child windows */

#706          co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);

#707        }

#708     }

#709 

 

 

#710     /* BugBoy Comments: if the window being created is a edit control, ATOM 0xC007,

#711        then my testing shows that windows (2k and XP) creates a CallProc for it immediately

#712        Dont understand why it does this. */

#713     if (ClassAtom == 0XC007)

#714     {

#715        PCALLPROC CallProc;

#716        //CallProc = CreateCallProc(NULL, Wnd->WndProc, bUnicodeWindow, Wnd->ti->kpi);

#717        CallProc = CreateCallProc(NULL, Wnd->WndProc, Wnd->Unicode , Wnd->ti->kpi);

#718 

#719        if (!CallProc)

#720        {

#721           SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);

#722           DPRINT1("Warning: Unable to create CallProc for edit control. Control may not operate correctly! hwnd %x/n",hWnd);

#723        }

#724        else

#725        {

#726           UserAddCallProcToClass(Wnd->Class, CallProc);

#727           Wnd->CallProc = CallProc;

#728           Wnd->IsSystem = FALSE;

#729        }

#730     }

#731 

 

返回创建窗口的句柄。

#732     DPRINT("IntCreateWindow(): = %X/n", hWnd);

#733     DPRINT("WindowObject->SystemMenu = 0x%x/n", Window->SystemMenu);

#734     RETURN(hWnd);

#735 

 

下面是清除失败时分配的资源。

#736  CLEANUP:

#737     if (!_ret_ && Window && Window->Wnd && ti)

#738         UserFreeWindowInfo(ti, Window);

#739     if (Window)

#740     {

#741        UserDerefObjectCo(Window);

#742        UserDereferenceObject(Window);

#743     }

#744     if (ParentWindow) UserDerefObjectCo(ParentWindow);

#745     if (!_ret_ && ti != NULL)

#746     {

#747         if (Class != NULL)

#748         {

#749             IntDereferenceClass(Class,

#750                                 ti->Desktop,

#751                                 ti->kpi);

#752         }

#753     }

#754     END_CLEANUP;

#755  }

#756  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
本实例由VS2008开发,在提供了一套驱动开发框架的同时,又演示了如何获取Shadow SSDT表函数原始地址的办法。 主要函数:ULONG GetShadowSSDT_Function_OriAddr(ULONG index); 原理说明: 根据特征码搜索导出函数KeAddSystemServiceTable来获取Shadow SSDT基址,以及通过ZwQuerySystemInformation()函数获取win32k.sys基址,然后解析PE定位到Shadow SSDT在win32k.sys的偏移地址,并通过进一步计算来得到Shadow SSDT表函数的原始地址。 这里只测试了三个函数:(460)NtUserMessageCall、(475)NtUserPostMessage和(502)NtUserSendInput,具体使用时可以举一反三,网上完整的源代码实例并不太多,希望可以帮到真正有需要的朋友。 系统环境: 在WinXP SP3系统 + 瑞星杀毒软件 打印输出: [ LemonInfo : Loading Shadow SSDT Original Address Driver... ] [ LemonInfo : 创建“设备”值为:0 ] [ LemonInfo : 创建“设备”成功... ] [ LemonInfo : 创建“符号链接”状态值为:0 ] [ LemonInfo : 创建“符号链接”成功... ] [ LemonInfo : 驱动加载成功... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP 开始... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP Enter IRP_MJ_DEVICE_CONTROL... ] [ LemonInfo : 获取ShadowSSDT表 (460)NtUserMessageCall 函数的“当前地址”为:0xB83ECFC4,“起源地址”为:0xBF80EE6B ] [ LemonInfo : 获取ShadowSSDT表 (475)NtUserPostMessage 函数的“当前地址”为:0xB83ECFA3,“起源地址”为:0xBF8089B4 ] [ LemonInfo : 获取ShadowSSDT表 (502)NtUserSendInput 函数的“当前地址”为:0xBF8C31E7,“起源地址”为:0xBF8C31E7 ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP_MJ_DEVICE_CONTROL 成功执行... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP 结束... ] [ LemonInfo : UnLoading Shadow SSDT Original Address Driver... ] [ LemonInfo : 删除“符号链接”成功... ] [ LemonInfo : 删除“设备”成功... ] [ LemonInfo : 驱动卸载成功... ]
上册共分为10部分,这是第1部分 Windows内核情景分析(上册).part01.rar 基本信息 作者: 毛德操 出版社:电子工业出版社 ISBN:9787121081149 上架时间:2009-5-25 出版日期:2009 年5月 开本:16开 页码:1465 版次:1-1 所属分类:计算机 > 操作系统 > Windows 内容简介回到顶部↑ 本书通过分析ReactOS的源代码介绍了Windows内核各个方面的结构、功能、算法与具体实现。全书从“内存管理”、“进程”、“进程间通信”、“设备驱动”等多个方面进行分析介绍,所有的分析都有ReactOS的源代码(以及部分由微软公开的源代码)作为依据,使读者能深入理解Windows内核的方方面面,也可以使读者的软件开发能力和水平得到提高。. 本书可供大学有关专业的高年级学生和研究生用做教学参考,也可供广大的软件工程师,特别是从事系统软件研发的工程师用于工作参考或用做进修教材。... 目录回到顶部↑ 上 册. 第1章 概述 1 1.1 Windows操作系统发展简史 1 1.2 用户空间和系统空间 3 1.3 Windows内核 4 1.4 开源项目ReactOS及其代码 9 1.5 Windows内核函数的命名 10 第2章 系统调用 12 2.1 内核与系统调用 12 2.2 系统调用的内核入口KiSystemService() 22 2.3 系统调用的函数跳转 29 2.4 系统调用的返回 32 2.5 快速系统调用 35 2.6 从内核中发起系统调用 42 第3章 内存管理 44 3.1 内存区间的动态分配 47 3.1.1 内核对用户空间的管理 48 3.1.2 内核对于物理页面的管理 60 3.1.3 虚存页面的映射 67 3.1.4 Hyperspace的临时映射 78 .3.1.5 系统空间的映射 86 3.1.6 系统调用NtAllocateVirtualMemory() 90 3.2 页面异常 97 3.3 页面的换出 107 3.4 共享映射区(Section) 115 3.5 系统空间的缓冲区管理 133 第4章 对象管理 136 4.1 对象与对象目录 136 4.2 对象类型 148 4.3 句柄和句柄表 162 4.4 对象的创建 169 4.5 几个常用的内核函数 179 4.5.1 ObReferenceObjectByHandle() 179 4.5.2 ObReferenceObjectByPointer() 187 4.5.3 ObpLookupEntryDirectory() 188 4.5.4 ObpLookupObjectName() 192 4.5.5 ObOpenObjectByName() 209 4.5.6 ObReferenceObjectByName() 213 4.5.7 ObDereferenceObject() 214 4.6 对象的访问控制 218 4.7 句柄的遗传和继承 218 4.8 系统调用NtDuplicateObject() 223 4.9 系统调用NtClose() 233 第5章 进程与线程 241 5.1 概述 241 5.2 Windows进程的用户空间 253 5.3 系统调用NtCreateProcess() 273 5.4 系统调用NtCreateThread() 284 5.5 Windows的可执行程序映像 300 5.6 Windows的进程创建和映像装入 305 5.7 Windows DLL的装入和连接 329 5.8 Windows的APC机制 358 5.9 Windows线程的调度和切换 381 5.9.1 x86系统结构与线程切换 382 5.9.2 几个重要的数据结构 385 5.9.3 线程的切换 388 5.9.4 线程的调度 395 5.10 线程和进程的优先级 409 5.11 线程本地存储TLS 421 5.12 进程挂靠 434 5.13 Windows的跨进程操作 442 5.14 Windows线程间的相互作用 450 第6章 进程间通信 467 6.1 概述 467 6.2 共享内存区(Section).. 469 6.3 线程的等待/唤醒机制 470 6.4 信号量(Semaphore) 499 6.5 互斥门(Mutant) 505 6.6 事件(Event) 512 6.7 命名管道(Named Pipe)和信插(Mailslot) 516 6.8 本地过程调用(LPC) 521 6.9 视窗报文

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

caimouse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值