⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 window.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
//   if (NULL != ParentWindowHandle)
//   {
   ParentWindow = UserGetWindowObject(ParentWindowHandle);

   if (ParentWindow) UserRefObjectCo(ParentWindow, &ParentRef);
//   }
//   else
//   {
//      ParentWindow = NULL;
//   }

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

   /* Check the window station. */
   ti = GetW32ThreadInfo();
   if (ti == NULL || PsGetCurrentThreadWin32Thread()->Desktop == NULL)
   {
      DPRINT1("Thread is not attached to a desktop! Cannot create window!\n");
      RETURN( (HWND)0);
   }

   /* Check the class. */

   ClassAtom = IntGetClassAtom(ClassName,
                               hInstance,
                               ti->kpi,
                               &Class,
                               &ClassLink);

   if (ClassAtom == (RTL_ATOM)0)
   {
      if (IS_ATOM(ClassName->Buffer))
      {
         DPRINT1("Class 0x%p not found\n", (DWORD_PTR) ClassName->Buffer);
      }
      else
      {
         DPRINT1("Class \"%wZ\" not found\n", ClassName);
      }

      SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS);
      RETURN((HWND)0);
   }

   Class = IntReferenceClass(Class,
                             ClassLink,
                             ti->Desktop);
   if (Class == NULL)
   {
       DPRINT1("Failed to reference window class!\n");
       RETURN(NULL);
   }

   WinSta = PsGetCurrentThreadWin32Thread()->Desktop->WindowStation;

   //FIXME: Reference thread/desktop instead
   ObReferenceObjectByPointer(WinSta, KernelMode, ExWindowStationObjectType, 0);

   /* Create the window object. */
   Window = (PWINDOW_OBJECT)
            ObmCreateObject(gHandleTable, (PHANDLE)&hWnd,
                            otWindow, sizeof(WINDOW_OBJECT) + Class->WndExtra
                           );

   DPRINT("Created object with handle %X\n", hWnd);
   if (!Window)
   {
      ObDereferenceObject(WinSta);
      SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
      RETURN( (HWND)0);
   }

   UserRefObjectCo(Window, &Ref);

   ObDereferenceObject(WinSta);

   if (NULL == PsGetCurrentThreadWin32Thread()->Desktop->DesktopWindow)
   {
      /* If there is no desktop window yet, we must be creating it */
      PsGetCurrentThreadWin32Thread()->Desktop->DesktopWindow = hWnd;
   }

   /*
    * Fill out the structure describing it.
    */
   Window->ti = ti;
   Window->Class = Class;
   Class = NULL;

   Window->SystemMenu = (HMENU)0;
   Window->ContextHelpId = 0;
   Window->IDMenu = 0;
   Window->Instance = hInstance;
   Window->hSelf = hWnd;

   if (!hMenu)
       hMenu = Window->Class->hMenu;

   if (0 != (dwStyle & WS_CHILD))
   {
      Window->IDMenu = (UINT) hMenu;
   }
   else
   {
      IntSetMenu(Window, hMenu, &MenuChanged);
   }

   Window->MessageQueue = PsGetCurrentThreadWin32Thread()->MessageQueue;
   IntReferenceMessageQueue(Window->MessageQueue);
   Window->Parent = ParentWindow;

   if((OwnerWindow = UserGetWindowObject(OwnerWindowHandle)))
   {
      Window->hOwner = OwnerWindowHandle;
      HasOwner = TRUE;
   }
   else
   {
      Window->hOwner = NULL;
      HasOwner = FALSE;
   }

   Window->UserData = 0;

   Window->IsSystem = Window->Class->System;
   if (Window->Class->System)
   {
       /* NOTE: Always create a unicode window for system classes! */
       Window->Unicode = TRUE;
       Window->WndProc = Window->Class->WndProc;
       Window->WndProcExtra = Window->Class->WndProcExtra;
   }
   else
   {
       Window->Unicode = Window->Class->Unicode;
       Window->WndProc = Window->Class->WndProc;
       Window->CallProc = NULL;
   }

   Window->OwnerThread = PsGetCurrentThread();
   Window->FirstChild = NULL;
   Window->LastChild = NULL;
   Window->PrevSibling = NULL;
   Window->NextSibling = NULL;
   Window->ExtraDataSize = Window->Class->WndExtra;

   /* extra window data */
   if (Window->Class->WndExtra)
      Window->ExtraData = (PCHAR)(Window + 1);

   InitializeListHead(&Window->PropListHead);
   InitializeListHead(&Window->WndObjListHead);

   if (NULL != WindowName->Buffer)
   {
      Window->WindowName.MaximumLength = WindowName->MaximumLength;
      Window->WindowName.Length = WindowName->Length;
      Window->WindowName.Buffer = ExAllocatePoolWithTag(PagedPool, WindowName->MaximumLength,
                                  TAG_STRING);
      if (NULL == Window->WindowName.Buffer)
      {
         DPRINT1("Failed to allocate mem for window name\n");
         SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
         RETURN( NULL);
      }
      RtlCopyMemory(Window->WindowName.Buffer, WindowName->Buffer, WindowName->MaximumLength);
   }
   else
   {
      RtlInitUnicodeString(&Window->WindowName, NULL);
   }

   /*
    * This has been tested for WS_CHILD | WS_VISIBLE.  It has not been
    * tested for WS_POPUP
    */
   if ((dwExStyle & WS_EX_DLGMODALFRAME) ||
         ((!(dwExStyle & WS_EX_STATICEDGE)) &&
          (dwStyle & (WS_DLGFRAME | WS_THICKFRAME))))
      dwExStyle |= WS_EX_WINDOWEDGE;
   else
      dwExStyle &= ~WS_EX_WINDOWEDGE;

   /* Correct the window style. */
   if (!(dwStyle & WS_CHILD))
   {
      dwStyle |= WS_CLIPSIBLINGS;
      DPRINT("3: Style is now %lx\n", dwStyle);
      if (!(dwStyle & WS_POPUP))
      {
         dwStyle |= WS_CAPTION;
         Window->Flags |= WINDOWOBJECT_NEED_SIZE;
         DPRINT("4: Style is now %lx\n", dwStyle);
      }
   }

   /* create system menu */
   if((dwStyle & WS_SYSMENU) &&
         (dwStyle & WS_CAPTION) == WS_CAPTION)
   {
      SystemMenu = IntGetSystemMenu(Window, TRUE, TRUE);
      if(SystemMenu)
      {
         Window->SystemMenu = SystemMenu->MenuInfo.Self;
         IntReleaseMenuObject(SystemMenu);
      }
   }

   /* Insert the window into the thread's window list. */
   InsertTailList (&PsGetCurrentThreadWin32Thread()->WindowListHead, &Window->ThreadListEntry);

   /* Allocate a DCE for this window. */
   if (dwStyle & CS_OWNDC)
   {
      Window->Dce = DceAllocDCE(Window, DCE_WINDOW_DC);
   }
   /* FIXME:  Handle "CS_CLASSDC" */

   Pos.x = x;
   Pos.y = y;
   Size.cx = nWidth;
   Size.cy = nHeight;

   Window->ExStyle = dwExStyle;
   Window->Style = dwStyle & ~WS_VISIBLE;

   /* call hook */
   Cs.lpCreateParams = lpParam;
   Cs.hInstance = hInstance;
   Cs.hMenu = hMenu;
   Cs.hwndParent = hWndParent; //Pass the original Parent handle!
   Cs.cx = Size.cx;
   Cs.cy = Size.cy;
   Cs.x = Pos.x;
   Cs.y = Pos.y;
   Cs.style = Window->Style;
   Cs.lpszName = (LPCWSTR) WindowName;
   Cs.lpszClass = (LPCWSTR) ClassName;
   Cs.dwExStyle = dwExStyle;
   CbtCreate.lpcs = &Cs;
   CbtCreate.hwndInsertAfter = HWND_TOP;
   if (co_HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) hWnd, (LPARAM) &CbtCreate))
   {
      /* FIXME - Delete window object and remove it from the thread windows list */
      /* FIXME - delete allocated DCE */
      DPRINT1("CBT-hook returned !0\n");
      RETURN( (HWND) NULL);
   }

   x = Cs.x;
   y = Cs.y;
   nWidth = Cs.cx;
   nHeight = Cs.cy;

   /* default positioning for overlapped windows */
   if(!(Window->Style & (WS_POPUP | WS_CHILD)))
   {
      RECT rc, WorkArea;
      PRTL_USER_PROCESS_PARAMETERS ProcessParams;
      BOOL CalculatedDefPosSize = FALSE;

      IntGetDesktopWorkArea(((PW32THREAD)Window->OwnerThread->Tcb.Win32Thread)->Desktop, &WorkArea);

      rc = WorkArea;
      ProcessParams = PsGetCurrentProcess()->Peb->ProcessParameters;

      if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16)
      {
         CalculatedDefPosSize = IntCalcDefPosSize(ParentWindow, Window, &rc, TRUE);

         if(ProcessParams->WindowFlags & STARTF_USEPOSITION)
         {
            ProcessParams->WindowFlags &= ~STARTF_USEPOSITION;
            Pos.x = WorkArea.left + ProcessParams->StartingX;
            Pos.y = WorkArea.top + ProcessParams->StartingY;
         }
         else
         {
            Pos.x = rc.left;
            Pos.y = rc.top;
         }

/*
   According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and
   y is something else. and Quote!
 */

/* Never believe Microsoft's documentation... CreateWindowEx doc says
 * that if an overlapped window is created with WS_VISIBLE style bit
 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
 * reveals that
 *
 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
 * 2) it does not ignore the y parameter as the docs claim; instead, it
 *    uses it as second parameter to ShowWindow() unless y is either
 *    CW_USEDEFAULT or CW_USEDEFAULT16.
 *
 * The fact that we didn't do 2) caused bogus windows pop up when wine
 * was running apps that were using this obscure feature. Example -
 * calc.exe that comes with Win98 (only Win98, it's different from
 * the one that comes with Win95 and NT)
 */
         if(y != CW_USEDEFAULT && y != CW_USEDEFAULT16)
         {
            dwShowMode = y;
         }
      }
      if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16)
      {
         if(!CalculatedDefPosSize)
         {
            IntCalcDefPosSize(ParentWindow, Window, &rc, FALSE);
         }
         if(ProcessParams->WindowFlags & STARTF_USESIZE)
         {
            ProcessParams->WindowFlags &= ~STARTF_USESIZE;
            Size.cx = ProcessParams->CountX;
            Size.cy = ProcessParams->CountY;
         }
         else
         {
            Size.cx = rc.right - rc.left;
            Size.cy = rc.bottom - rc.top;
         }

         /* move the window if necessary */
         if(Pos.x > rc.left)
            Pos.x = max(rc.left, 0);
         if(Pos.y > rc.top)
            Pos.y = max(rc.top, 0);
      }
   }
   else
   {
      /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */
      if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16)
      {
         Pos.x = 0;
         Pos.y = 0;
      }
      if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16)
      {
         Size.cx = 0;
         Size.cy = 0;
      }
   }

   /* Initialize the window dimensions. */
   Window->WindowRect.left = Pos.x;
   Window->WindowRect.top = Pos.y;
   Window->WindowRect.right = Pos.x + Size.cx;
   Window->WindowRect.bottom = Pos.y + Size.cy;
   if (0 != (Window->Style & WS_CHILD) && ParentWindow)
   {
      IntGdiOffsetRect(&(Window->WindowRect), ParentWindow->ClientRect.left,
                       ParentWindow->ClientRect.top);
   }
   Window->ClientRect = Window->WindowRect;

   /*
    * Get the size and position of the window.
    */
   if ((dwStyle & WS_THICKFRAME) || !(dwStyle & (WS_POPUP | WS_CHILD)))
   {
      POINT MaxSize, MaxPos, MinTrack, MaxTrack;

      /* WinPosGetMinMaxInfo sends the WM_GETMINMAXINFO message */
      co_WinPosGetMinMaxInfo(Window, &MaxSize, &MaxPos, &MinTrack,
                             &MaxTrack);
      if (MaxSize.x < Size.cx)
         Size.cx = MaxSize.x;
      if (MaxSize.y < Size.cy)
         Size.cy = MaxSize.y;
      if (Size.cx < MinTrack.x )
         Size.cx = MinTrack.x;
      if (Size.cy < MinTrack.y )
         Size.cy = MinTrack.y;
      if (Size.cx < 0)
         Size.cx = 0;
      if (Size.cy < 0)
         Size.cy = 0;
   }

   Window->WindowRect.left = Pos.x;
   Window->WindowRect.top = Pos.y;
   Window->WindowRect.right = Pos.x + Size.cx;
   Window->WindowRect.bottom = Pos.y + Size.cy;
   if (0 != (Window->Style & WS_CHILD) && ParentWindow)
   {
      IntGdiOffsetRect(&(Window->WindowRect), ParentWindow->ClientRect.left,
                       ParentWindow->ClientRect.top);
   }
   Window->ClientRect = Window->WindowRect;

   /* FIXME: Initialize the window menu. */

   /* Send a NCCREATE message. */
   Cs.cx = Size.cx;
   Cs.cy = Size.cy;
   Cs.x = Pos.x;
   Cs.y = Pos.y;

   DPRINT("[win32k.window] IntCreateWindowEx style %d, exstyle %d, parent %d\n", Cs.style, Cs.dwExStyle, Cs.hwndParent);
   DPRINT("IntCreateWindowEx(): (%d,%d-%d,%d)\n", x, y, Size.cx, Size.cy);
   DPRINT("IntCreateWindowEx(): About to send NCCREATE message.\n");
   Result = co_IntSendMessage(Window->hSelf, WM_NCCREATE, 0, (LPARAM) &Cs);
   if (!Result)
   {
      /* FIXME: Cleanup. */
      DPRINT("IntCreateWindowEx(): NCCREATE message failed.\n");
      RETURN((HWND)0);
   }

   /* Calculate the non-client size. */
   MaxPos.x = Window->WindowRect.left;
   MaxPos.y = Window->WindowRect.top;


   DPRINT("IntCreateWindowEx(): About to get non-client size.\n");
   /* WinPosGetNonClientSize SENDS THE WM_NCCALCSIZE message */
   Result = co_WinPosGetNonClientSize(Window,
                                      &Window->WindowRect,
                                      &Window->ClientRect);

   IntGdiOffsetRect(&Window->WindowRect,
                    MaxPos.x - Window->WindowRect.left,
                    MaxPos.y - Window->WindowRect.top);


   if (NULL != ParentWindow)
   {
      /* link the window into the parent's child list */
      if ((dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
      {
         PWINDOW_OBJECT PrevSibling;

         PrevSibling = ParentWindow->LastChild;

         /* link window as bottom sibling */
         IntLinkWindow(Window, ParentWindow, PrevSibling /*prev sibling*/);
      }
      else
      {
         /* link window as top sibling (but after topmost siblings) */
         PWINDOW_OBJECT InsertAfter, Sibling;
         if (!(dwExStyle & WS_EX_TOPMOST))
         {
            InsertAfter = NULL;
            Sibling = ParentWindow->FirstChild;
            while (Sibling && (Sibling->ExStyle & WS_EX_TOPMOST))
            {
               InsertAfter = Sibling;
               Sibling = Sibling->NextSibling;
            }
         }
         else
         {
            InsertAfter = NULL;
         }

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

      }
   }

   /* Send the WM_CREATE message. */
   DPRINT("IntCreateWindowEx(): about to send CREATE message.\n");
   Result = co_IntSendMessage(Window->hSelf, WM_CREATE, 0, (LPARAM) &Cs);


   if (Result == (LRESULT)-1)
   {
      /* FIXME: Cleanup. */
      DPRINT("IntCreateWindowEx(): send CREATE message failed.\n");
      RETURN((HWND)0);
   }


   /* Send move and size messages. */
   if (!(Window->Flags & WINDOWOBJECT_NEED_SIZE))
   {
      LONG lParam;

      DPRINT("IntCreateWindow(): About to send WM_SIZE\n");

      if ((Window->ClientRect.right - Window->ClientRect.left) < 0 ||
            (Window->ClientRect.bottom - Window->ClientRect.top) < 0)
      {
         DPRINT("Sending bogus WM_SIZE\n");
      }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -