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

📄 desktop.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
                              NULL,
                              (PHANDLE)&Ret))
   {
      Status = ObOpenObjectByPointer(DesktopObject,
                                     0,
                                     NULL,
                                     0,
                                     ExDesktopObjectType,
                                     UserMode,
                                     (PHANDLE)&Ret);
      if(!NT_SUCCESS(Status))
      {
         /* unable to create a handle */
         DPRINT1("Unable to create a desktop handle\n");
         return NULL;
      }
   }
   else
   {
       DPRINT1("Got handle: %lx\n", Ret);
   }

   return Ret;
}

PUSER_MESSAGE_QUEUE FASTCALL
IntGetFocusMessageQueue(VOID)
{
   PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
   if (!pdo)
   {
      DPRINT("No active desktop\n");
      return(NULL);
   }
   return (PUSER_MESSAGE_QUEUE)pdo->ActiveMessageQueue;
}

VOID FASTCALL
IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue)
{
   PUSER_MESSAGE_QUEUE Old;
   PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
   if (!pdo)
   {
      DPRINT("No active desktop\n");
      return;
   }
   if(NewQueue != NULL)
   {
      if(NewQueue->Desktop != NULL)
      {
         DPRINT("Message Queue already attached to another desktop!\n");
         return;
      }
      IntReferenceMessageQueue(NewQueue);
      InterlockedExchange((LONG*)&NewQueue->Desktop, (LONG)pdo);
   }
   Old = (PUSER_MESSAGE_QUEUE)InterlockedExchange((LONG*)&pdo->ActiveMessageQueue, (LONG)NewQueue);
   if(Old != NULL)
   {
      InterlockedExchange((LONG*)&Old->Desktop, 0);
      IntDereferenceMessageQueue(Old);
   }
}

HWND FASTCALL IntGetDesktopWindow(VOID)
{
   PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
   if (!pdo)
   {
      DPRINT("No active desktop\n");
      return NULL;
   }
   return pdo->DesktopWindow;
}

PWINDOW_OBJECT FASTCALL UserGetDesktopWindow(VOID)
{
   PDESKTOP_OBJECT pdo = IntGetActiveDesktop();

   if (!pdo)
   {
      DPRINT("No active desktop\n");
      return NULL;
   }

   return UserGetWindowObject(pdo->DesktopWindow);
}


HWND FASTCALL IntGetCurrentThreadDesktopWindow(VOID)
{
   PDESKTOP_OBJECT pdo = PsGetCurrentThreadWin32Thread()->Desktop;
   if (NULL == pdo)
   {
      DPRINT1("Thread doesn't have a desktop\n");
      return NULL;
   }
   return pdo->DesktopWindow;
}

BOOL FASTCALL IntDesktopUpdatePerUserSettings(BOOL bEnable)
{
   if (bEnable)
   {
      RTL_QUERY_REGISTRY_TABLE QueryTable[2];
      NTSTATUS Status;

      RtlZeroMemory(QueryTable, sizeof(QueryTable));

      QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
      QueryTable[0].Name = L"PaintDesktopVersion";
      QueryTable[0].EntryContext = &g_PaintDesktopVersion;

      /* Query the "PaintDesktopVersion" flag in the "Control Panel\Desktop" key */
      Status = RtlQueryRegistryValues(RTL_REGISTRY_USER,
                                      L"Control Panel\\Desktop",
                                      QueryTable, NULL, NULL);
      if (!NT_SUCCESS(Status))
      {
         DPRINT1("RtlQueryRegistryValues failed for PaintDesktopVersion (%x)\n",
                 Status);
         g_PaintDesktopVersion = FALSE;
         return FALSE;
      }

      DPRINT("PaintDesktopVersion = %d\n", g_PaintDesktopVersion);

      return TRUE;
   }
   else
   {
      g_PaintDesktopVersion = FALSE;
      return TRUE;
   }
}

/* PUBLIC FUNCTIONS ***********************************************************/

NTSTATUS FASTCALL
co_IntShowDesktop(PDESKTOP_OBJECT Desktop, ULONG Width, ULONG Height)
{
   CSR_API_MESSAGE Request;

   Request.Type = MAKE_CSR_API(SHOW_DESKTOP, CSR_GUI);
   Request.Data.ShowDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
   Request.Data.ShowDesktopRequest.Width = Width;
   Request.Data.ShowDesktopRequest.Height = Height;

   return co_CsrNotify(&Request);
}

NTSTATUS FASTCALL
IntHideDesktop(PDESKTOP_OBJECT Desktop)
{
#if 0
   CSRSS_API_REQUEST Request;
   CSRSS_API_REPLY Reply;

   Request.Type = CSRSS_HIDE_DESKTOP;
   Request.Data.HideDesktopRequest.DesktopWindow = Desktop->DesktopWindow;

   return NotifyCsrss(&Request, &Reply);
#else

   PWINDOW_OBJECT DesktopWindow;

   DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow);
   if (! DesktopWindow)
   {
      return ERROR_INVALID_WINDOW_HANDLE;
   }
   DesktopWindow->Style &= ~WS_VISIBLE;

   return STATUS_SUCCESS;
#endif
}




static
HWND* FASTCALL
UserBuildShellHookHwndList(PDESKTOP_OBJECT Desktop)
{
   ULONG entries=0;
   PSHELL_HOOK_WINDOW Current;
   HWND* list;
   
   /* fixme: if we save nb elements in desktop, we dont have to loop to find nb entries */
   LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
      entries++;

   if (!entries) return NULL;

   list = ExAllocatePool(PagedPool, sizeof(HWND) * (entries + 1)); /* alloc one extra for nullterm */
   if (list)
   {
      HWND* cursor = list;
      
      LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
         *cursor++ = Current->hWnd;
   
      *cursor = NULL; /* nullterm list */
   }

   return list;
}

/*
 * Send the Message to the windows registered for ShellHook
 * notifications. The lParam contents depend on the Message. See
 * MSDN for more details (RegisterShellHookWindow)
 */
VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam)
{
   PDESKTOP_OBJECT Desktop = IntGetActiveDesktop();
   HWND* HwndList;

   static UINT MsgType = 0;

   if (!MsgType)
   {

      /* Too bad, this doesn't work.*/
#if 0
      UNICODE_STRING Str;
      RtlInitUnicodeString(&Str, L"SHELLHOOK");
      MsgType = UserRegisterWindowMessage(&Str);
#endif

      MsgType = IntAddAtom(L"SHELLHOOK");

      DPRINT("MsgType = %x\n", MsgType);
      if (!MsgType)
         DPRINT1("LastError: %x\n", GetLastNtError());
   }

   if (!Desktop)
   {
      DPRINT("IntShellHookNotify: No desktop!\n");
      return;
   }

   HwndList = UserBuildShellHookHwndList(Desktop);
   if (HwndList)
   {
      HWND* cursor = HwndList;
      
      for (; *cursor; cursor++)
      {
         DPRINT("Sending notify\n");
         co_IntPostOrSendMessage(*cursor,
                                 MsgType,
                                 Message,
                                 lParam);
      }

      ExFreePool(HwndList);
   }
   
}

/*
 * Add the window to the ShellHookWindows list. The windows
 * on that list get notifications that are important to shell
 * type applications.
 *
 * TODO: Validate the window? I'm not sure if sending these messages to
 * an unsuspecting application that is not your own is a nice thing to do.
 */
BOOL IntRegisterShellHookWindow(HWND hWnd)
{
   PDESKTOP_OBJECT Desktop = PsGetCurrentThreadWin32Thread()->Desktop;
   PSHELL_HOOK_WINDOW Entry;

   DPRINT("IntRegisterShellHookWindow\n");

   /* First deregister the window, so we can be sure it's never twice in the
    * list.
    */
   IntDeRegisterShellHookWindow(hWnd);

   Entry = ExAllocatePoolWithTag(PagedPool,
                                 sizeof(SHELL_HOOK_WINDOW),
                                 TAG_WINSTA);

   if (!Entry)
      return FALSE;

   Entry->hWnd = hWnd;

   InsertTailList(&Desktop->ShellHookWindows, &Entry->ListEntry);

   return TRUE;
}

/*
 * Remove the window from the ShellHookWindows list. The windows
 * on that list get notifications that are important to shell
 * type applications.
 */
BOOL IntDeRegisterShellHookWindow(HWND hWnd)
{
   PDESKTOP_OBJECT Desktop = PsGetCurrentThreadWin32Thread()->Desktop;
   PSHELL_HOOK_WINDOW Current;

   LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
   {
      if (Current->hWnd == hWnd)
      {
         RemoveEntryList(&Current->ListEntry);
         ExFreePool(Current);
         return TRUE;
      }
   }

   return FALSE;
}

static VOID
IntFreeDesktopHeap(IN OUT PDESKTOP_OBJECT Desktop)
{
    if (Desktop->DesktopHeapSection != NULL)
    {
        ObDereferenceObject(Desktop->DesktopHeapSection);
        Desktop->DesktopHeapSection = NULL;
    }
}
/* SYSCALLS *******************************************************************/


/*
 * NtUserCreateDesktop
 *
 * Creates a new desktop.
 *
 * Parameters
 *    lpszDesktopName
 *       Name of the new desktop.
 *
 *    dwFlags
 *       Interaction flags.
 *
 *    dwDesiredAccess
 *       Requested type of access.
 *
 *    lpSecurity
 *       Security descriptor.
 *
 *    hWindowStation
 *       Handle to window station on which to create the desktop.
 *
 * Return Value
 *    If the function succeeds, the return value is a handle to the newly
 *    created desktop. If the specified desktop already exists, the function
 *    succeeds and returns a handle to the existing desktop. When you are
 *    finished using the handle, call the CloseDesktop function to close it.
 *    If the function fails, the return value is NULL.
 *
 * Status
 *    @implemented
 */

HDESK STDCALL
NtUserCreateDesktop(
   PUNICODE_STRING lpszDesktopName,
   DWORD dwFlags,
   ACCESS_MASK dwDesiredAccess,
   LPSECURITY_ATTRIBUTES lpSecurity,
   HWINSTA hWindowStation)
{
   OBJECT_ATTRIBUTES ObjectAttributes;
   PWINSTATION_OBJECT WinStaObject;
   PDESKTOP_OBJECT DesktopObject;
   UNICODE_STRING DesktopName;
   NTSTATUS Status;
   HDESK Desktop;
   CSR_API_MESSAGE Request;
   PVOID DesktopHeapSystemBase = NULL;
   SIZE_T DesktopInfoSize;
   UNICODE_STRING SafeDesktopName;
   ULONG DummyContext;
   DECLARE_RETURN(HDESK);
  

   DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName);
   UserEnterExclusive();

   Status = IntValidateWindowStationHandle(
               hWindowStation,
               KernelMode,
               0, /* FIXME - WINSTA_CREATEDESKTOP */
               &WinStaObject);

   if (! NT_SUCCESS(Status))
   {
      DPRINT1("Failed validation of window station handle (0x%X), cannot create desktop %wZ\n",
              hWindowStation, lpszDesktopName);
      SetLastNtError(Status);
      RETURN( NULL);
   }
   if(lpszDesktopName != NULL)
   {
      Status = IntSafeCopyUnicodeString(&SafeDesktopName, lpszDesktopName);
      if(!NT_SUCCESS(Status))
      {
         SetLastNtError(Status);
         RETURN( NULL);
	  }
   }
   else
   {
      RtlInitUnicodeString(&SafeDesktopName, NULL);
   }

   if (! IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
                                     &SafeDesktopName))
   {
      SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
      ObDereferenceObject(WinStaObject);
      RtlFreeUnicodeString(&SafeDesktopName);
      RETURN( NULL);
   }
   RtlFreeUnicodeString(&SafeDesktopName);
   ObDereferenceObject(WinStaObject);

   /*
    * Try to open already existing desktop
    */

   DPRINT("Trying to open desktop (%wZ)\n", &DesktopName);

   /* Initialize ObjectAttributes for the desktop object */
   InitializeObjectAttributes(
      &ObjectAttributes,
      &DesktopName,
      0,
      NULL,
      NULL);

   Status = ObOpenObjectByName(
               &ObjectAttributes,
               ExDesktopObjectType,
               KernelMode,
               NULL,
               dwDesiredAccess,
               (PVOID)&DummyContext,
               (HANDLE*)&Desktop);
   if (!NT_SUCCESS(Status)) RETURN(NULL);
   if (Status == STATUS_OBJECT_NAME_EXISTS)
   {
      ExFreePool(DesktopName.Buffer);
      RETURN( Desktop);
   }

   /* Reference the desktop */
   Status = ObReferenceObjectByHandle(Desktop,
                                      0,
                                      ExDesktopObjectType,
                                      KernelMode,
                                      (PVOID)&DesktopObject,
                                      NULL);
   if (!NT_SUCCESS(Status)) RETURN(NULL);

   DesktopObject->DesktopHeapSection = NULL;
   DesktopObject->hDesktopHeap = UserCreateHeap(&DesktopObject->DesktopHeapSection,
                                                &DesktopHeapSystemBase,
                                                4 * 1024 * 1024); /* FIXME */
   if (DesktopObject->hDesktopHeap == NULL)
   {
       ObDereferenceObject(DesktopObject);
       DPRINT1("Failed to create desktop heap!\n");
       RETURN(NULL);
   }

   DesktopInfoSize = FIELD_OFFSET(DESKTOP,
                                  szDesktopName[(lpszDesktopName->Length / sizeof(WCHAR)) + 1]);

   DesktopObject->DesktopInfo = RtlAllocateHeap(DesktopObject->hDesktopHeap,
                                                HEAP_NO_SERIALIZE,
                                                DesktopInfoSize);

   if (DesktopObject->DesktopInfo == NULL)
   {
       ObDereferenceObject(DesktopObject);
       DPRINT1("Failed to create the DESKTOP structure!\n");
       RETURN(NULL);
   }

⌨️ 快捷键说明

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