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

📄 desktop.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
   }

   /* Back ground is set to none, clear the screen */
   if (doPatBlt)
   {
      PreviousBrush = NtGdiSelectObject(hDC, DesktopBrush);
      NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
      NtGdiSelectObject(hDC, PreviousBrush);
   }

   /*
    * Display system version on the desktop background
    */

   if (g_PaintDesktopVersion)
   {
      static WCHAR s_wszVersion[256] = {0};
      RECT rect;

      if (*s_wszVersion)
      {
         len = wcslen(s_wszVersion);
      }
      else
      {
         len = GetSystemVersionString(s_wszVersion);
      }

      if (len)
      {
         if (!UserSystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0))
         {
            rect.right = UserGetSystemMetrics(SM_CXSCREEN);
            rect.bottom = UserGetSystemMetrics(SM_CYSCREEN);
         }

         color_old = NtGdiSetTextColor(hDC, RGB(255,255,255));
         align_old = NtGdiSetTextAlign(hDC, TA_RIGHT);
         mode_old = NtGdiSetBkMode(hDC, TRANSPARENT);

         NtGdiExtTextOut(hDC, rect.right-16, rect.bottom-48, 0, NULL, s_wszVersion, len, NULL);

         NtGdiSetBkMode(hDC, mode_old);
         NtGdiSetTextAlign(hDC, align_old);
         NtGdiSetTextColor(hDC, color_old);
      }
   }

   RETURN(TRUE);
   
CLEANUP:
   DPRINT("Leave NtUserPaintDesktop, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;   
}


/*
 * NtUserSwitchDesktop
 *
 * Sets the current input (interactive) desktop.
 *
 * Parameters
 *    hDesktop
 *       Handle to desktop.
 *
 * Return Value
 *    Status
 *
 * Status
 *    @unimplemented
 */

BOOL STDCALL
NtUserSwitchDesktop(HDESK hDesktop)
{
   PDESKTOP_OBJECT DesktopObject;
   NTSTATUS Status;
   DECLARE_RETURN(BOOL);
   
   UserEnterExclusive();
   DPRINT("Enter NtUserSwitchDesktop\n");

   DPRINT("About to switch desktop (0x%X)\n", hDesktop);

   Status = IntValidateDesktopHandle(
               hDesktop,
               UserMode,
               0,
               &DesktopObject);

   if (!NT_SUCCESS(Status))
   {
      DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
      RETURN(FALSE);
   }

   /*
    * Don't allow applications switch the desktop if it's locked, unless the caller
    * is the logon application itself
    */
   if((DesktopObject->WindowStation->Flags & WSS_LOCKED) &&
         LogonProcess != NULL && LogonProcess != PsGetCurrentProcessWin32Process())
   {
      ObDereferenceObject(DesktopObject);
      DPRINT1("Switching desktop 0x%x denied because the work station is locked!\n", hDesktop);
      RETURN(FALSE);
   }

   /* FIXME: Fail if the desktop belong to an invisible window station */
   /* FIXME: Fail if the process is associated with a secured
             desktop such as Winlogon or Screen-Saver */
   /* FIXME: Connect to input device */

   /* Set the active desktop in the desktop's window station. */
   DesktopObject->WindowStation->ActiveDesktop = DesktopObject;

   /* Set the global state. */
   InputDesktop = DesktopObject;
   InputDesktopHandle = hDesktop;
   InputWindowStation = DesktopObject->WindowStation;

   ObDereferenceObject(DesktopObject);

   RETURN(TRUE);
   
CLEANUP:
   DPRINT("Leave NtUserSwitchDesktop, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;   
}

/*
 * NtUserResolveDesktopForWOW
 *
 * Status
 *    @unimplemented
 */

DWORD STDCALL
NtUserResolveDesktopForWOW(DWORD Unknown0)
{
   UNIMPLEMENTED
   return 0;
}

/*
 * NtUserGetThreadDesktop
 *
 * Status
 *    @implemented
 */

HDESK STDCALL
NtUserGetThreadDesktop(DWORD dwThreadId, DWORD Unknown1)
{
   NTSTATUS Status;
   PETHREAD Thread;
   PDESKTOP_OBJECT DesktopObject;
   HDESK Ret, hThreadDesktop;
   OBJECT_HANDLE_INFORMATION HandleInformation;
   DECLARE_RETURN(HDESK);
   
   UserEnterExclusive();
   DPRINT("Enter NtUserGetThreadDesktop\n");

   if(!dwThreadId)
   {
      SetLastWin32Error(ERROR_INVALID_PARAMETER);
      RETURN(0);
   }

   Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread);
   if(!NT_SUCCESS(Status))
   {
      SetLastWin32Error(ERROR_INVALID_PARAMETER);
      RETURN(0);
   }

   if(Thread->ThreadsProcess == PsGetCurrentProcess())
   {
      /* just return the handle, we queried the desktop handle of a thread running
         in the same context */
      Ret = ((PW32THREAD)Thread->Tcb.Win32Thread)->hDesktop;
      ObDereferenceObject(Thread);
      RETURN(Ret);
   }

   /* get the desktop handle and the desktop of the thread */
   if(!(hThreadDesktop = ((PW32THREAD)Thread->Tcb.Win32Thread)->hDesktop) ||
         !(DesktopObject = ((PW32THREAD)Thread->Tcb.Win32Thread)->Desktop))
   {
      ObDereferenceObject(Thread);
      DPRINT1("Desktop information of thread 0x%x broken!?\n", dwThreadId);
      RETURN(NULL);
   }

   /* we could just use DesktopObject instead of looking up the handle, but latter
      may be a bit safer (e.g. when the desktop is being destroyed */
   /* switch into the context of the thread we're trying to get the desktop from,
      so we can use the handle */
   KeAttachProcess(&Thread->ThreadsProcess->Pcb);
   Status = ObReferenceObjectByHandle(hThreadDesktop,
                                      GENERIC_ALL,
                                      ExDesktopObjectType,
                                      UserMode,
                                      (PVOID*)&DesktopObject,
                                      &HandleInformation);
   KeDetachProcess();

   /* the handle couldn't be found, there's nothing to get... */
   if(!NT_SUCCESS(Status))
   {
      ObDereferenceObject(Thread);
      RETURN(NULL);
   }

   /* lookup our handle table if we can find a handle to the desktop object,
      if not, create one */
   Ret = IntGetDesktopObjectHandle(DesktopObject);

   /* all done, we got a valid handle to the desktop */
   ObDereferenceObject(DesktopObject);
   ObDereferenceObject(Thread);
   RETURN(Ret);
   
CLEANUP:
   DPRINT("Leave NtUserGetThreadDesktop, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;
}

static NTSTATUS
IntUnmapDesktopView(IN PDESKTOP_OBJECT DesktopObject)
{
    PW32THREADINFO ti;
    PW32HEAP_USER_MAPPING HeapMapping, *PrevLink = &PsGetCurrentProcessWin32Process()->HeapMappings.Next;
    NTSTATUS Status = STATUS_SUCCESS;

    TRACE("DO %p\n");

    /* unmap if we're the last thread using the desktop */
    HeapMapping = *PrevLink;
    while (HeapMapping != NULL)
    {
        if (HeapMapping->KernelMapping == (PVOID)DesktopObject->hDesktopHeap)
        {
            if (--HeapMapping->Count == 0)
            {
                *PrevLink = HeapMapping->Next;

                Status = MmUnmapViewOfSection(PsGetCurrentProcess(),
                                              HeapMapping->UserMapping);

                ObDereferenceObject(DesktopObject);

                UserHeapFree(HeapMapping);
                break;
            }
        }

        PrevLink = &HeapMapping->Next;
        HeapMapping = HeapMapping->Next;
    }

    ti = GetW32ThreadInfo();
    if (ti != NULL)
    {
        if (ti->Desktop == DesktopObject->DesktopInfo)
        {
            ti->Desktop = NULL;
            ti->DesktopHeapDelta = 0;
        }
    }

    return Status;
}

static NTSTATUS
IntMapDesktopView(IN PDESKTOP_OBJECT DesktopObject)
{
    PW32THREADINFO ti;
    PW32HEAP_USER_MAPPING HeapMapping, *PrevLink = &PsGetCurrentProcessWin32Process()->HeapMappings.Next;
    PVOID UserBase = NULL;
    ULONG ViewSize = 0;
    LARGE_INTEGER Offset;
    NTSTATUS Status;

    /* find out if another thread already mapped the desktop heap */
    HeapMapping = *PrevLink;
    while (HeapMapping != NULL)
    {
        if (HeapMapping->KernelMapping == (PVOID)DesktopObject->hDesktopHeap)
        {
            HeapMapping->Count++;
            return STATUS_SUCCESS;
        }

        PrevLink = &HeapMapping->Next;
        HeapMapping = HeapMapping->Next;
    }

    /* we're the first, map the heap */
    DPRINT("Noone mapped the desktop heap %p yet, so - map it!\n", DesktopObject->hDesktopHeap);
    Offset.QuadPart = 0;
    Status = MmMapViewOfSection(DesktopObject->DesktopHeapSection,
                                PsGetCurrentProcess(),
                                &UserBase,
                                0,
                                0,
                                &Offset,
                                &ViewSize,
                                ViewUnmap,
                                SEC_NO_CHANGE,
                                PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("Failed to map desktop\n");
        return Status;
    }

    /* add the mapping */
    HeapMapping = UserHeapAlloc(sizeof(W32HEAP_USER_MAPPING));
    if (HeapMapping == NULL)
    {
        MmUnmapViewOfSection(PsGetCurrentProcess(),
                             UserBase);
        DPRINT1("UserHeapAlloc() failed!\n");
        return STATUS_NO_MEMORY;
    }

    HeapMapping->Next = NULL;
    HeapMapping->KernelMapping = (PVOID)DesktopObject->hDesktopHeap;
    HeapMapping->UserMapping = UserBase;
    HeapMapping->Count = 1;
    *PrevLink = HeapMapping;

    ObReferenceObject(DesktopObject);

    /* create a W32THREADINFO structure if not already done, or update it */
    ti = GetW32ThreadInfo();
    if (ti != NULL)
    {
        if (ti->Desktop == NULL)
        {
            ti->Desktop = DesktopObject->DesktopInfo;
            ti->DesktopHeapDelta = DesktopHeapGetUserDelta();
        }
    }

    return STATUS_SUCCESS;
}

BOOL
IntSetThreadDesktop(IN PDESKTOP_OBJECT DesktopObject,
                    IN BOOL FreeOnFailure)
{
    PDESKTOP_OBJECT OldDesktop;
    PW32THREAD W32Thread;
    NTSTATUS Status;
    BOOL MapHeap;

    DPRINT("IntSetThreadDesktop() DO=%p, FOF=%d\n", DesktopObject, FreeOnFailure);
    MapHeap = (PsGetCurrentProcess() != PsInitialSystemProcess);
    W32Thread = PsGetCurrentThreadWin32Thread();

    if (W32Thread->Desktop != DesktopObject)
    {
        OldDesktop = W32Thread->Desktop;

        if (!IsListEmpty(&W32Thread->WindowListHead))
        {
            DPRINT1("Attempted to change thread desktop although the thread has windows!\n");
            SetLastWin32Error(ERROR_BUSY);
            return FALSE;
        }

        W32Thread->Desktop = DesktopObject;

        if (MapHeap && DesktopObject != NULL)
        {
            Status = IntMapDesktopView(DesktopObject);
            if (!NT_SUCCESS(Status))
            {
                SetLastNtError(Status);
                return FALSE;
            }
        }

        if (OldDesktop != NULL &&
            !IntCheckProcessDesktopClasses(OldDesktop->DesktopInfo,
                                           FreeOnFailure))
        {
            DPRINT1("Failed to move process classes to shared heap!\n");

            /* failed to move desktop classes to the shared heap,
               unmap the view and return the error */
            if (MapHeap && DesktopObject != NULL)
                IntUnmapDesktopView(DesktopObject);

            return FALSE;
        }

        if (DesktopObject != NULL)
        {
            ObReferenceObject(DesktopObject);
        }

        if (OldDesktop != NULL)
        {
            if (MapHeap)
            {
                IntUnmapDesktopView(OldDesktop);
            }

            ObDereferenceObject(OldDesktop);

            /* update the thread info */
            if (W32Thread != NULL && W32Thread->ThreadInfo != NULL &&
                W32Thread->ThreadInfo->Desktop != (DesktopObject != NULL ? DesktopObject->DesktopInfo : NULL))
            {
                if (DesktopObject != NULL)
                {
                    W32Thread->ThreadInfo->Desktop = DesktopObject->DesktopInfo;
                    W32Thread->ThreadInfo->DesktopHeapDelta = DesktopHeapGetUserDelta();
                }
                else
                {
                    W32Thread->ThreadInfo->Desktop = NULL;
                    W32Thread->ThreadInfo->DesktopHeapDelta = 0;
                }
            }
        }
    }

    return TRUE;
}

/*
 * NtUserSetThreadDesktop
 *
 * Status
 *    @implemented
 */

BOOL STDCALL
NtUserSetThreadDesktop(HDESK hDesktop)
{
   PDESKTOP_OBJECT DesktopObject;
   NTSTATUS Status;
   DECLARE_RETURN(BOOL);
   
   UserEnterExclusive();
   DPRINT("Enter NtUserSetThreadDesktop\n");
   
   /* Validate the new desktop. */
   Status = IntValidateDesktopHandle(
               hDesktop,
               UserMode,
               0,
               &DesktopObject);

   if (!NT_SUCCESS(Status))
   {
      DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
      RETURN(FALSE);
   }

   /* FIXME: Should check here to see if the thread has any windows. */

   if (!IntSetThreadDesktop(DesktopObject,
                            FALSE))
   {
       RETURN(FALSE);
   }

   RETURN(TRUE);
   
CLEANUP:
   DPRINT("Leave NtUserSetThreadDesktop, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;
}

/* EOF */

⌨️ 快捷键说明

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