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

📄 desktop.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 *  ReactOS W32 Subsystem
 *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  $Id: desktop.c 27850 2007-07-26 15:13:36Z hpoussin $
 *
 *  COPYRIGHT:        See COPYING in the top level directory
 *  PROJECT:          ReactOS kernel
 *  PURPOSE:          Desktops
 *  FILE:             subsys/win32k/ntuser/desktop.c
 *  PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)
 *  REVISION HISTORY:
 *       06-06-2001  CSH  Created
 */

/* INCLUDES ******************************************************************/

#include <w32k.h>

#define NDEBUG
#include <debug.h>
#define TRACE DPRINT
#define WARN DPRINT1
#define ERR DPRINT1

static
VOID
IntFreeDesktopHeap(
    IN OUT PDESKTOP_OBJECT Desktop
);

/* GLOBALS *******************************************************************/

/* Currently active desktop */
PDESKTOP_OBJECT InputDesktop = NULL;
HDESK InputDesktopHandle = NULL;
HDC ScreenDeviceContext = NULL;
BOOL g_PaintDesktopVersion = FALSE;

GENERIC_MAPPING IntDesktopMapping =
{
      STANDARD_RIGHTS_READ     | DESKTOP_ENUMERATE       |
                                 DESKTOP_READOBJECTS,
      STANDARD_RIGHTS_WRITE    | DESKTOP_CREATEMENU      |
                                 DESKTOP_CREATEWINDOW    |
                                 DESKTOP_HOOKCONTROL     |
                                 DESKTOP_JOURNALPLAYBACK |
                                 DESKTOP_JOURNALRECORD   |
                                 DESKTOP_WRITEOBJECTS,
      STANDARD_RIGHTS_EXECUTE  | DESKTOP_SWITCHDESKTOP,
      STANDARD_RIGHTS_REQUIRED | DESKTOP_CREATEMENU      |
                                 DESKTOP_CREATEWINDOW    |
                                 DESKTOP_ENUMERATE       |
                                 DESKTOP_HOOKCONTROL     |
                                 DESKTOP_JOURNALPLAYBACK |
                                 DESKTOP_JOURNALRECORD   |
                                 DESKTOP_READOBJECTS     |
                                 DESKTOP_SWITCHDESKTOP   |
                                 DESKTOP_WRITEOBJECTS
};

/* OBJECT CALLBACKS **********************************************************/

NTSTATUS
NTAPI
IntDesktopObjectParse(IN PVOID ParseObject,
                      IN PVOID ObjectType,
                      IN OUT PACCESS_STATE AccessState,
                      IN KPROCESSOR_MODE AccessMode,
                      IN ULONG Attributes,
                      IN OUT PUNICODE_STRING CompleteName,
                      IN OUT PUNICODE_STRING RemainingName,
                      IN OUT PVOID Context OPTIONAL,
                      IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
                      OUT PVOID *Object)
{
    NTSTATUS Status;
    PDESKTOP_OBJECT Desktop;
    OBJECT_ATTRIBUTES ObjectAttributes;
    PLIST_ENTRY NextEntry, ListHead;
    PWINSTATION_OBJECT WinStaObject = (PWINSTATION_OBJECT)ParseObject;
    PUNICODE_STRING DesktopName;

    /* Set the list pointers and loop the window station */
    ListHead = &WinStaObject->DesktopListHead;
    NextEntry = ListHead->Flink;
    while (NextEntry != ListHead)
    {
        /* Get the current desktop */
        Desktop = CONTAINING_RECORD(NextEntry, DESKTOP_OBJECT, ListEntry);

        /* Get its name */
        DesktopName = GET_DESKTOP_NAME(Desktop);
        if (DesktopName)
        {
            /* Compare the name */
            if (RtlEqualUnicodeString(RemainingName,
                                      DesktopName,
                                      (Attributes & OBJ_CASE_INSENSITIVE)))
            {
                /* We found a match. Did this come from a create? */
                if (Context)
                {
                    /* Unless OPEN_IF was given, fail with an error */
                    if (!(Attributes & OBJ_OPENIF))
                    {
                        /* Name collision */
                        return STATUS_OBJECT_NAME_COLLISION;
                    }
                    else
                    {
                        /* Otherwise, return with a warning only */
                        Status = STATUS_OBJECT_NAME_EXISTS;
                    }
                }
                else
                {
                    /* This was a real open, so this is OK */
                    Status = STATUS_SUCCESS;
                }

                /* Reference the desktop and return it */
                ObReferenceObject(Desktop);
                *Object = Desktop;
                return Status;
            }
        }

        /* Go to the next desktop */
        NextEntry = NextEntry->Flink;
    }

    /* If we got here but this isn't a create, then fail */
    if (!Context) return STATUS_OBJECT_NAME_NOT_FOUND;

    /* Create the desktop object */
    InitializeObjectAttributes(&ObjectAttributes, RemainingName, 0, NULL, NULL);
    Status = ObCreateObject(KernelMode,
                            ExDesktopObjectType,
                            &ObjectAttributes,
                            KernelMode,
                            NULL,
                            sizeof(DESKTOP_OBJECT),
                            0,
                            0,
                            (PVOID)&Desktop);
    if (!NT_SUCCESS(Status)) return Status;

    /* Initialize shell hook window list and set the parent */
    InitializeListHead(&Desktop->ShellHookWindows);
    Desktop->WindowStation = (PWINSTATION_OBJECT)ParseObject;

    /* Put the desktop on the window station's list of associated desktops */
    InsertTailList(&Desktop->WindowStation->DesktopListHead,
                   &Desktop->ListEntry);

    /* Set the desktop object and return success */
    *Object = Desktop;
    return STATUS_SUCCESS;
}

VOID STDCALL
IntDesktopObjectDelete(PWIN32_DELETEMETHOD_PARAMETERS Parameters)
{
   PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)Parameters->Object;

   DPRINT("Deleting desktop (0x%X)\n", Desktop);

   /* Remove the desktop from the window station's list of associcated desktops */
   RemoveEntryList(&Desktop->ListEntry);

   IntFreeDesktopHeap(Desktop);
}

/* PRIVATE FUNCTIONS **********************************************************/

NTSTATUS
FASTCALL
InitDesktopImpl(VOID)
{
    /* Set Desktop Object Attributes */
    ExDesktopObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(DESKTOP_OBJECT);
    ExDesktopObjectType->TypeInfo.GenericMapping = IntDesktopMapping;
    return STATUS_SUCCESS;
}

NTSTATUS
FASTCALL
CleanupDesktopImpl(VOID)
{
    return STATUS_SUCCESS;
}

static int GetSystemVersionString(LPWSTR buffer)
{
   RTL_OSVERSIONINFOEXW versionInfo;
   int len;

   versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);

   if (!NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&versionInfo)))
      return 0;

   if (versionInfo.dwMajorVersion <= 4)
      len = swprintf(buffer,
                     L"ReactOS Version %d.%d %s Build %d",
                     versionInfo.dwMajorVersion, versionInfo.dwMinorVersion,
                     versionInfo.szCSDVersion, versionInfo.dwBuildNumber&0xFFFF);
   else
      len = swprintf(buffer,
                     L"ReactOS %s (Build %d)",
                     versionInfo.szCSDVersion, versionInfo.dwBuildNumber&0xFFFF);

   return len;
}


NTSTATUS FASTCALL
IntParseDesktopPath(PEPROCESS Process,
                    PUNICODE_STRING DesktopPath,
                    HWINSTA *hWinSta,
                    HDESK *hDesktop)
{
   OBJECT_ATTRIBUTES ObjectAttributes;
   UNICODE_STRING WinSta, Desktop, FullName;
   BOOL DesktopPresent = FALSE;
   BOOL WinStaPresent = FALSE;
   NTSTATUS Status;

   ASSERT(hWinSta);

   *hWinSta = NULL;

   if(hDesktop != NULL)
   {
      *hDesktop = NULL;
   }

   RtlInitUnicodeString(&WinSta, NULL);
   RtlInitUnicodeString(&Desktop, NULL);

   if(DesktopPath != NULL && DesktopPath->Buffer != NULL && DesktopPath->Length > sizeof(WCHAR))
   {
      PWCHAR c = DesktopPath->Buffer;
      USHORT wl = 0;
      USHORT l = DesktopPath->Length;

      /*
       * Parse the desktop path string which can be in the form "WinSta\Desktop"
       * or just "Desktop". In latter case WinSta0 will be used.
       */

      while(l > 0)
      {
         if(*c == L'\\')
         {
            wl = (ULONG_PTR)c - (ULONG_PTR)DesktopPath->Buffer;
            break;
         }
         l -= sizeof(WCHAR);
         c++;
      }

      if(wl > 0)
      {
         WinSta.Length = wl;
         WinSta.MaximumLength = wl + sizeof(WCHAR);
         WinSta.Buffer = DesktopPath->Buffer;

         WinStaPresent = TRUE;
         c++;
      }

      Desktop.Length = DesktopPath->Length - wl;
      if(wl > 0)
      {
         Desktop.Length -= sizeof(WCHAR);
      }
      if(Desktop.Length > 0)
      {
         Desktop.MaximumLength = Desktop.Length + sizeof(WCHAR);
         Desktop.Buffer = ((wl > 0) ? c : DesktopPath->Buffer);
         DesktopPresent = TRUE;
      }
   }

   if(!WinStaPresent)
   {
#if 0
      /* search the process handle table for (inherited) window station
         handles, use a more appropriate one than WinSta0 if possible. */
      if (!ObFindHandleForObject(Process,
                                 NULL,
                                 ExWindowStationObjectType,
                                 NULL,
                                 (PHANDLE)hWinSta))
#endif
      {
            /* we had no luck searching for opened handles, use WinSta0 now */
            RtlInitUnicodeString(&WinSta, L"WinSta0");
      }
   }

   if(!DesktopPresent && hDesktop != NULL)
   {
#if 0
      /* search the process handle table for (inherited) desktop
         handles, use a more appropriate one than Default if possible. */
      if (!ObFindHandleForObject(Process,
                                 NULL,
                                 ExDesktopObjectType,
                                 NULL,
                                 (PHANDLE)hDesktop))
#endif
      {
         /* we had no luck searching for opened handles, use Desktop now */
         RtlInitUnicodeString(&Desktop, L"Default");
      }
   }

   if(*hWinSta == NULL)
   {
      if(!IntGetFullWindowStationName(&FullName, &WinSta, NULL))
      {
         return STATUS_INSUFFICIENT_RESOURCES;
      }

      /* open the window station */
      InitializeObjectAttributes(&ObjectAttributes,
                                 &FullName,
                                 OBJ_CASE_INSENSITIVE,
                                 NULL,
                                 NULL);

      Status = ObOpenObjectByName(&ObjectAttributes,
                                  ExWindowStationObjectType,
                                  KernelMode,
                                  NULL,
                                  0,
                                  NULL,
                                  (HANDLE*)hWinSta);

      RtlFreeUnicodeString(&FullName);

      if(!NT_SUCCESS(Status))
      {
         SetLastNtError(Status);
         DPRINT("Failed to reference window station %wZ PID: %d!\n", &WinSta, PsGetCurrentProcessId());
         return Status;
      }
   }

   if(hDesktop != NULL && *hDesktop == NULL)
   {
      if(!IntGetFullWindowStationName(&FullName, &WinSta, &Desktop))
      {
         NtClose(*hWinSta);
         *hWinSta = NULL;
         return STATUS_INSUFFICIENT_RESOURCES;
      }

      /* open the desktop object */
      InitializeObjectAttributes(&ObjectAttributes,
                                 &FullName,
                                 OBJ_CASE_INSENSITIVE,
                                 NULL,
                                 NULL);

      Status = ObOpenObjectByName(&ObjectAttributes,
                                  ExDesktopObjectType,
                                  KernelMode,
                                  NULL,
                                  0,
                                  NULL,
                                  (HANDLE*)hDesktop);

      RtlFreeUnicodeString(&FullName);

      if(!NT_SUCCESS(Status))
      {
         *hDesktop = NULL;
         NtClose(*hWinSta);
         *hWinSta = NULL;
         SetLastNtError(Status);
         DPRINT("Failed to reference desktop %wZ PID: %d!\n", &Desktop, PsGetCurrentProcessId());
         return Status;
      }
   }

   return STATUS_SUCCESS;
}

/*
 * IntValidateDesktopHandle
 *
 * Validates the desktop handle.
 *
 * Remarks
 *    If the function succeeds, the handle remains referenced. If the
 *    fucntion fails, last error is set.
 */

NTSTATUS FASTCALL
IntValidateDesktopHandle(
   HDESK Desktop,
   KPROCESSOR_MODE AccessMode,
   ACCESS_MASK DesiredAccess,
   PDESKTOP_OBJECT *Object)
{
   NTSTATUS Status;

   Status = ObReferenceObjectByHandle(
               Desktop,
               DesiredAccess,
               ExDesktopObjectType,
               AccessMode,
               (PVOID*)Object,
               NULL);

   if (!NT_SUCCESS(Status))
      SetLastNtError(Status);

   return Status;
}

VOID FASTCALL
IntGetDesktopWorkArea(PDESKTOP_OBJECT Desktop, PRECT Rect)
{
   PRECT Ret;

   ASSERT(Desktop);

   Ret = &Desktop->WorkArea;
   if((Ret->right == -1) && ScreenDeviceContext)
   {
      PDC dc;
      BITMAPOBJ *BitmapObj;
      dc = DC_LockDc(ScreenDeviceContext);
      /* FIXME - Handle dc == NULL!!!! */
      BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
      if(BitmapObj)
      {
         Ret->right = BitmapObj->SurfObj.sizlBitmap.cx;
         Ret->bottom = BitmapObj->SurfObj.sizlBitmap.cy;
         BITMAPOBJ_UnlockBitmap(BitmapObj);
      }
      DC_UnlockDc(dc);
   }

   if(Rect)
   {
      *Rect = *Ret;
   }
}

PDESKTOP_OBJECT FASTCALL
IntGetActiveDesktop(VOID)
{
   return InputDesktop;
}

/*
 * returns or creates a handle to the desktop object
 */
HDESK FASTCALL
IntGetDesktopObjectHandle(PDESKTOP_OBJECT DesktopObject)
{
   NTSTATUS Status;
   HDESK Ret;

   ASSERT(DesktopObject);

   if (!ObFindHandleForObject(PsGetCurrentProcess(),
                              DesktopObject,
                              ExDesktopObjectType,

⌨️ 快捷键说明

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