From 7c98a98880fbb15a72ebfa88107ada0eeb17947d Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Sun, 7 Dec 2003 19:29:33 +0000 Subject: [PATCH] moved desktop code to desktop.c svn path=/trunk/; revision=6904 --- reactos/subsys/win32k/eng/mouse.c | 3 +- reactos/subsys/win32k/include/desktop.h | 39 ++ reactos/subsys/win32k/include/winsta.h | 33 +- reactos/subsys/win32k/main/dllmain.c | 3 +- reactos/subsys/win32k/makefile | 4 +- reactos/subsys/win32k/ntuser/callback.c | 3 +- reactos/subsys/win32k/ntuser/desktop.c | 731 +++++++++++++++++++++ reactos/subsys/win32k/ntuser/focus.c | 3 +- reactos/subsys/win32k/ntuser/input.c | 3 +- reactos/subsys/win32k/ntuser/msgqueue.c | 3 +- reactos/subsys/win32k/ntuser/window.c | 3 +- reactos/subsys/win32k/ntuser/winpos.c | 3 +- reactos/subsys/win32k/ntuser/winsta.c | 676 +------------------ reactos/subsys/win32k/objects/cursoricon.c | 3 +- reactos/subsys/win32k/objects/dc.c | 3 +- 15 files changed, 800 insertions(+), 713 deletions(-) create mode 100644 reactos/subsys/win32k/include/desktop.h create mode 100644 reactos/subsys/win32k/ntuser/desktop.c diff --git a/reactos/subsys/win32k/eng/mouse.c b/reactos/subsys/win32k/eng/mouse.c index 12cdcb57d88..b32b66ced9a 100644 --- a/reactos/subsys/win32k/eng/mouse.c +++ b/reactos/subsys/win32k/eng/mouse.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: mouse.c,v 1.46 2003/11/21 16:36:26 weiden Exp $ +/* $Id: mouse.c,v 1.47 2003/12/07 19:29:33 weiden Exp $ * * PROJECT: ReactOS kernel * PURPOSE: Mouse @@ -36,6 +36,7 @@ #include "include/msgqueue.h" #include "include/object.h" #include "include/winsta.h" +#include "include/desktop.h" #include "include/window.h" #include "include/cursoricon.h" #include "include/callback.h" diff --git a/reactos/subsys/win32k/include/desktop.h b/reactos/subsys/win32k/include/desktop.h new file mode 100644 index 00000000000..b9e52e97795 --- /dev/null +++ b/reactos/subsys/win32k/include/desktop.h @@ -0,0 +1,39 @@ +#ifndef _WIN32K_DESKTOP_H +#define _WIN32K_DESKTOP_H + +#include +#include +#include +#include +#include "msgqueue.h" +#include "window.h" + +extern PDESKTOP_OBJECT InputDesktop; +extern HDESK InputDesktopHandle; +extern PWNDCLASS_OBJECT DesktopWindowClass; +extern HDC ScreenDeviceContext; + +NTSTATUS FASTCALL +InitDesktopImpl(VOID); + +NTSTATUS FASTCALL +CleanupDesktopImpl(VOID); + +LRESULT CALLBACK +IntDesktopWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +HDC FASTCALL +IntGetScreenDC(VOID); + +PUSER_MESSAGE_QUEUE FASTCALL +IntGetFocusMessageQueue(VOID); + +VOID FASTCALL +IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue); + +PDESKTOP_OBJECT FASTCALL +IntGetActiveDesktop(VOID); + +#endif /* _WIN32K_DESKTOP_H */ + +/* EOF */ diff --git a/reactos/subsys/win32k/include/winsta.h b/reactos/subsys/win32k/include/winsta.h index 0412d416b64..d51d691dd14 100644 --- a/reactos/subsys/win32k/include/winsta.h +++ b/reactos/subsys/win32k/include/winsta.h @@ -24,12 +24,6 @@ InitWindowStationImpl(VOID); NTSTATUS FASTCALL CleanupWindowStationImpl(VOID); -NTSTATUS FASTCALL -InitDesktopImpl(VOID); - -NTSTATUS FASTCALL -CleanupDesktopImpl(VOID); - NTSTATUS FASTCALL IntValidateWindowStationHandle( HWINSTA WindowStation, @@ -40,34 +34,17 @@ IntValidateWindowStationHandle( BOOL FASTCALL IntGetWindowStationObject(PWINSTATION_OBJECT Object); -LRESULT CALLBACK -IntDesktopWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - -HDC FASTCALL -IntGetScreenDC(VOID); - BOOL FASTCALL IntInitializeDesktopGraphics(VOID); VOID FASTCALL IntEndDesktopGraphics(VOID); -/* -struct _WINDOW_OBJECT* FASTCALL -IntGetCaptureWindow(VOID); - -VOID FASTCALL -IntSetCaptureWindow(struct _WINDOW_OBJECT* Window); -*/ - -PUSER_MESSAGE_QUEUE FASTCALL -IntGetFocusMessageQueue(VOID); - -VOID FASTCALL -IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue); - -PDESKTOP_OBJECT FASTCALL -IntGetActiveDesktop(VOID); +BOOL FASTCALL +IntGetFullWindowStationName( + OUT PUNICODE_STRING FullName, + IN PUNICODE_STRING WinStaName, + IN OPTIONAL PUNICODE_STRING DesktopName); #endif /* _WIN32K_WINSTA_H */ diff --git a/reactos/subsys/win32k/main/dllmain.c b/reactos/subsys/win32k/main/dllmain.c index 1ffd9c846e1..05d3ea4046b 100644 --- a/reactos/subsys/win32k/main/dllmain.c +++ b/reactos/subsys/win32k/main/dllmain.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: dllmain.c,v 1.57 2003/12/07 12:59:34 chorns Exp $ +/* $Id: dllmain.c,v 1.58 2003/12/07 19:29:33 weiden Exp $ * * Entry Point for win32k.sys */ @@ -31,6 +31,7 @@ #include #include +#include #include #include #include diff --git a/reactos/subsys/win32k/makefile b/reactos/subsys/win32k/makefile index 05faed30dd5..4d7803601b6 100644 --- a/reactos/subsys/win32k/makefile +++ b/reactos/subsys/win32k/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.86 2003/12/07 12:59:34 chorns Exp $ +# $Id: makefile,v 1.87 2003/12/07 19:29:33 weiden Exp $ PATH_TO_TOP = ../.. @@ -49,7 +49,7 @@ MISC_OBJECTS = misc/driver.o misc/error.o misc/math.o misc/object.o LDR_OBJECTS = ldr/loader.o NTUSER_OBJECTS = ntuser/accelerator.o ntuser/callback.o ntuser/caret.o ntuser/class.o ntuser/focus.o \ - ntuser/guicheck.o ntuser/hook.o ntuser/hotkey.o ntuser/input.o \ + ntuser/desktop.o ntuser/guicheck.o ntuser/hook.o ntuser/hotkey.o ntuser/input.o \ ntuser/keyboard.o ntuser/menu.o ntuser/message.o ntuser/metric.o \ ntuser/misc.o ntuser/msgqueue.o ntuser/painting.o ntuser/prop.o \ ntuser/scrollbar.o ntuser/stubs.o ntuser/timer.o ntuser/userobj.o \ diff --git a/reactos/subsys/win32k/ntuser/callback.c b/reactos/subsys/win32k/ntuser/callback.c index 87daf21ae0d..713a1fdd2ca 100644 --- a/reactos/subsys/win32k/ntuser/callback.c +++ b/reactos/subsys/win32k/ntuser/callback.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: callback.c,v 1.16 2003/11/23 12:24:20 weiden Exp $ +/* $Id: callback.c,v 1.17 2003/12/07 19:29:33 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include diff --git a/reactos/subsys/win32k/ntuser/desktop.c b/reactos/subsys/win32k/ntuser/desktop.c new file mode 100644 index 00000000000..2333d1d173b --- /dev/null +++ b/reactos/subsys/win32k/ntuser/desktop.c @@ -0,0 +1,731 @@ +/* + * 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,v 1.1 2003/12/07 19:29:33 weiden Exp $ + * + * 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 ******************************************************************/ + +#define __WIN32K__ +#define NTOS_MODE_KERNEL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +/* Currently active desktop */ +PDESKTOP_OBJECT InputDesktop = NULL; +HDESK InputDesktopHandle = NULL; +PWNDCLASS_OBJECT DesktopWindowClass; +HDC ScreenDeviceContext = NULL; + +/* INITALIZATION FUNCTIONS ****************************************************/ + +NTSTATUS FASTCALL +InitDesktopImpl(VOID) +{ + WNDCLASSEXW wcx; + + /* + * Create the desktop window class + */ + wcx.style = 0; + wcx.lpfnWndProc = IntDesktopWindowProc; + wcx.cbClsExtra = wcx.cbWndExtra = 0; + wcx.hInstance = wcx.hIcon = wcx.hCursor = NULL; + wcx.hbrBackground = NULL; + wcx.lpszMenuName = NULL; + wcx.lpszClassName = L"DesktopWindowClass"; + DesktopWindowClass = IntCreateClass(&wcx, TRUE, IntDesktopWindowProc, + (RTL_ATOM)32880); + + return STATUS_SUCCESS; +} + +NTSTATUS FASTCALL +CleanupDesktopImpl(VOID) +{ + /* FIXME: Unregister the desktop window class */ + + return STATUS_SUCCESS; +} + +/* PRIVATE FUNCTIONS **********************************************************/ + +LRESULT CALLBACK +IntDesktopWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_CREATE: + return 0; + + case WM_NCCREATE: + return 1; + + case WM_ERASEBKGND: + return NtUserPaintDesktop((HDC)wParam); + + default: + return 0; + } +} + +/* + * 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; +} + +PDESKTOP_OBJECT FASTCALL +IntGetActiveDesktop(VOID) +{ + return InputDesktop; +} + +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) +{ + PDESKTOP_OBJECT pdo = IntGetActiveDesktop(); + if (!pdo) + { + DPRINT("No active desktop\n"); + return; + } + pdo->ActiveMessageQueue = NewQueue; +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +/* + * 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; + + Status = IntValidateWindowStationHandle( + hWindowStation, + KernelMode, + 0, + &WinStaObject); + + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed validation of window station handle (0x%X)\n", + hWindowStation); + SetLastNtError(Status); + return 0; + } + + if (!IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name, + lpszDesktopName)) + { + SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); + ObDereferenceObject(WinStaObject); + return 0; + } + + 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, + NULL, + UserMode, + dwDesiredAccess, + NULL, + &Desktop); + + if (NT_SUCCESS(Status)) + { + DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName); + ExFreePool(DesktopName.Buffer); + return Desktop; + } + + /* + * No existing desktop found, try to create new one + */ + + Status = ObCreateObject( + ExGetPreviousMode(), + ExDesktopObjectType, + &ObjectAttributes, + ExGetPreviousMode(), + NULL, + sizeof(DESKTOP_OBJECT), + 0, + 0, + (PVOID*)&DesktopObject); + + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed creating desktop (%wZ)\n", &DesktopName); + ExFreePool(DesktopName.Buffer); + SetLastNtError(STATUS_UNSUCCESSFUL); + return((HDESK)0); + } + + /* FIXME: Set correct dimensions. */ + DesktopObject->WorkArea.left = 0; + DesktopObject->WorkArea.top = 0; + DesktopObject->WorkArea.right = 640; + DesktopObject->WorkArea.bottom = 480; + + /* Initialize some local (to win32k) desktop state. */ + DesktopObject->ActiveMessageQueue = NULL; + DesktopObject->DesktopWindow = IntCreateDesktopWindow( + DesktopObject->WindowStation, + DesktopWindowClass, + DesktopObject->WorkArea.right, + DesktopObject->WorkArea.bottom); + + DPRINT("Created Desktop Window: %08x\n", DesktopObject->DesktopWindow); + + Status = ObInsertObject( + (PVOID)DesktopObject, + NULL, + STANDARD_RIGHTS_REQUIRED, + 0, + NULL, + &Desktop); + + ObDereferenceObject(DesktopObject); + ExFreePool(DesktopName.Buffer); + + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed to create desktop handle\n"); + SetLastNtError(STATUS_UNSUCCESSFUL); + return 0; + } + + return Desktop; +} + +/* + * NtUserOpenDesktop + * + * Opens an existing desktop. + * + * Parameters + * lpszDesktopName + * Name of the existing desktop. + * + * dwFlags + * Interaction flags. + * + * dwDesiredAccess + * Requested type of access. + * + * Return Value + * Handle to the desktop or zero on failure. + * + * Status + * @implemented + */ + +HDESK STDCALL +NtUserOpenDesktop( + PUNICODE_STRING lpszDesktopName, + DWORD dwFlags, + ACCESS_MASK dwDesiredAccess) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + PWINSTATION_OBJECT WinStaObject; + UNICODE_STRING DesktopName; + NTSTATUS Status; + HDESK Desktop; + + /* + * Validate the window station handle and compose the fully + * qualified desktop name + */ + + Status = IntValidateWindowStationHandle( + PROCESS_WINDOW_STATION(), + KernelMode, + 0, + &WinStaObject); + + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed validation of window station handle (0x%X)\n", + PROCESS_WINDOW_STATION()); + SetLastNtError(Status); + return 0; + } + + if (!IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name, + lpszDesktopName)) + { + SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); + ObDereferenceObject(WinStaObject); + return 0; + } + + ObDereferenceObject(WinStaObject); + + DPRINT("Trying to open desktop station (%wZ)\n", &DesktopName); + + /* Initialize ObjectAttributes for the desktop object */ + InitializeObjectAttributes( + &ObjectAttributes, + &DesktopName, + 0, + NULL, + NULL); + + Status = ObOpenObjectByName( + &ObjectAttributes, + ExDesktopObjectType, + NULL, + UserMode, + dwDesiredAccess, + NULL, + &Desktop); + + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + ExFreePool(DesktopName.Buffer); + return 0; + } + + DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName); + ExFreePool(DesktopName.Buffer); + + return Desktop; +} + +/* + * NtUserOpenInputDesktop + * + * Opens the input (interactive) desktop. + * + * Parameters + * dwFlags + * Interaction flags. + * + * fInherit + * Inheritance option. + * + * dwDesiredAccess + * Requested type of access. + * + * Return Value + * Handle to the input desktop or zero on failure. + * + * Status + * @implemented + */ + +HDESK STDCALL +NtUserOpenInputDesktop( + DWORD dwFlags, + BOOL fInherit, + ACCESS_MASK dwDesiredAccess) +{ + PDESKTOP_OBJECT Object; + NTSTATUS Status; + HDESK Desktop; + + DPRINT("About to open input desktop\n"); + + /* Get a pointer to the desktop object */ + + Status = IntValidateDesktopHandle( + InputDesktop, + KernelMode, + 0, + &Object); + + if (!NT_SUCCESS(Status)) + { + DPRINT("Validation of input desktop handle (0x%X) failed\n", InputDesktop); + return (HDESK)0; + } + + /* Create a new handle to the object */ + + Status = ObOpenObjectByPointer( + Object, + 0, + NULL, + dwDesiredAccess, + ExDesktopObjectType, + UserMode, + &Desktop); + + ObDereferenceObject(Object); + + if (NT_SUCCESS(Status)) + { + DPRINT("Successfully opened input desktop\n"); + return (HDESK)Desktop; + } + + SetLastNtError(Status); + return (HDESK)0; +} + +/* + * NtUserCloseDesktop + * + * Closes a desktop handle. + * + * Parameters + * hDesktop + * Handle to the desktop. + * + * Return Value + * Status + * + * Remarks + * The desktop handle can be created with NtUserCreateDesktop or + * NtUserOpenDesktop. This function will fail if any thread in the calling + * process is using the specified desktop handle or if the handle refers + * to the initial desktop of the calling process. + * + * Status + * @implemented + */ + +BOOL STDCALL +NtUserCloseDesktop(HDESK hDesktop) +{ + PDESKTOP_OBJECT Object; + NTSTATUS Status; + + DPRINT("About to close desktop handle (0x%X)\n", hDesktop); + + Status = IntValidateDesktopHandle( + hDesktop, + KernelMode, + 0, + &Object); + + if (!NT_SUCCESS(Status)) + { + DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop); + return FALSE; + } + + ObDereferenceObject(Object); + + DPRINT("Closing desktop handle (0x%X)\n", hDesktop); + + Status = ZwClose(hDesktop); + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + return FALSE; + } + + return TRUE; +} + +/* + * NtUserPaintDesktop + * + * The NtUserPaintDesktop function fills the clipping region in the + * specified device context with the desktop pattern or wallpaper. The + * function is provided primarily for shell desktops. + * + * Parameters + * hdc + * Handle to the device context. + * + * Status + * @implemented + */ + +BOOL STDCALL +NtUserPaintDesktop(HDC hDC) +{ + HWND hwnd = IntGetDesktopWindow(); + + /* + * Check for an owning thread, otherwise don't paint anything + * (non-desktop mode) + */ + + if (NtUserGetWindowThreadProcessId(hwnd, NULL)) + { + RECT Rect; + HBRUSH PreviousBrush; + + NtUserGetClientRect(hwnd, &Rect); + + /* + * Paint desktop background + */ + + PreviousBrush = NtGdiSelectObject(hDC, NtGdiGetSysColorBrush(COLOR_BACKGROUND)); + NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY); + NtGdiSelectObject(hDC, PreviousBrush); + } + + return TRUE; +} + +/* + * 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; + + DPRINT("About to switch desktop (0x%X)\n", hDesktop); + + Status = IntValidateDesktopHandle( + hDesktop, + KernelMode, + 0, + &DesktopObject); + + if (!NT_SUCCESS(Status)) + { + DPRINT("Validation of desktop handle (0x%X) failed\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; +} + +/* + * NtUserResolveDesktopForWOW + * + * Status + * @unimplemented + */ + +DWORD STDCALL +NtUserResolveDesktopForWOW(DWORD Unknown0) +{ + UNIMPLEMENTED + return 0; +} + +/* + * NtUserGetThreadDesktop + * + * Status + * @unimplemented + */ + +HDESK STDCALL +NtUserGetThreadDesktop(DWORD dwThreadId, DWORD Unknown1) +{ + UNIMPLEMENTED + return 0; +} + +/* + * NtUserSetThreadDesktop + * + * Status + * @implemented + */ + +BOOL STDCALL +NtUserSetThreadDesktop(HDESK hDesktop) +{ + PDESKTOP_OBJECT DesktopObject; + NTSTATUS Status; + + /* Validate the new desktop. */ + Status = IntValidateDesktopHandle( + hDesktop, + KernelMode, + 0, + &DesktopObject); + + if (!NT_SUCCESS(Status)) + { + DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop); + return FALSE; + } + + /* Check for setting the same desktop as before. */ + if (DesktopObject == PsGetWin32Thread()->Desktop) + { + ObDereferenceObject(DesktopObject); + return TRUE; + } + + /* FIXME: Should check here to see if the thread has any windows. */ + + if (PsGetWin32Thread()->Desktop != NULL) + { + ObDereferenceObject(PsGetWin32Thread()->Desktop); + } + + PsGetWin32Thread()->Desktop = DesktopObject; + + return TRUE; +} + +/* EOF */ diff --git a/reactos/subsys/win32k/ntuser/focus.c b/reactos/subsys/win32k/ntuser/focus.c index 52068c515ec..aecb32d5d31 100644 --- a/reactos/subsys/win32k/ntuser/focus.c +++ b/reactos/subsys/win32k/ntuser/focus.c @@ -16,11 +16,12 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: focus.c,v 1.3 2003/12/02 19:58:54 navaraf Exp $ + * $Id: focus.c,v 1.4 2003/12/07 19:29:33 weiden Exp $ */ #include #include +#include #include #include #include diff --git a/reactos/subsys/win32k/ntuser/input.c b/reactos/subsys/win32k/ntuser/input.c index c1b4124bc4d..3c96da17977 100644 --- a/reactos/subsys/win32k/ntuser/input.c +++ b/reactos/subsys/win32k/ntuser/input.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: input.c,v 1.23 2003/11/30 20:03:47 navaraf Exp $ +/* $Id: input.c,v 1.24 2003/12/07 19:29:33 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include diff --git a/reactos/subsys/win32k/ntuser/msgqueue.c b/reactos/subsys/win32k/ntuser/msgqueue.c index 227dbcf444c..6d3938f57c6 100644 --- a/reactos/subsys/win32k/ntuser/msgqueue.c +++ b/reactos/subsys/win32k/ntuser/msgqueue.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: msgqueue.c,v 1.39 2003/11/30 20:03:47 navaraf Exp $ +/* $Id: msgqueue.c,v 1.40 2003/12/07 19:29:33 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include diff --git a/reactos/subsys/win32k/ntuser/window.c b/reactos/subsys/win32k/ntuser/window.c index 0f376c1e237..38ab3f8ff8d 100644 --- a/reactos/subsys/win32k/ntuser/window.c +++ b/reactos/subsys/win32k/ntuser/window.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: window.c,v 1.151 2003/12/07 10:31:22 navaraf Exp $ +/* $Id: window.c,v 1.152 2003/12/07 19:29:33 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include diff --git a/reactos/subsys/win32k/ntuser/winpos.c b/reactos/subsys/win32k/ntuser/winpos.c index 0e2f00f5e53..a14eaf5e7e8 100644 --- a/reactos/subsys/win32k/ntuser/winpos.c +++ b/reactos/subsys/win32k/ntuser/winpos.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: winpos.c,v 1.50 2003/12/02 19:58:54 navaraf Exp $ +/* $Id: winpos.c,v 1.51 2003/12/07 19:29:33 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include diff --git a/reactos/subsys/win32k/ntuser/winsta.c b/reactos/subsys/win32k/ntuser/winsta.c index 05c6e2d354e..97399bb50a7 100644 --- a/reactos/subsys/win32k/ntuser/winsta.c +++ b/reactos/subsys/win32k/ntuser/winsta.c @@ -16,11 +16,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: winsta.c,v 1.49 2003/11/30 20:03:47 navaraf Exp $ + * $Id: winsta.c,v 1.50 2003/12/07 19:29:33 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * PURPOSE: Window stations and Desktops + * PURPOSE: Window stations * FILE: subsys/win32k/ntuser/winsta.c * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) * REVISION HISTORY: @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -58,16 +59,10 @@ /* Currently active window station */ PWINSTATION_OBJECT InputWindowStation = NULL; -/* Currently active desktop */ -STATIC PDESKTOP_OBJECT InputDesktop = NULL; -STATIC HDESK InputDesktopHandle = NULL; LRESULT CALLBACK IntDesktopWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); -STATIC PWNDCLASS_OBJECT DesktopWindowClass; -HDC ScreenDeviceContext = NULL; - /* INITALIZATION FUNCTIONS ****************************************************/ NTSTATUS FASTCALL @@ -103,35 +98,6 @@ CleanupWindowStationImpl(VOID) return STATUS_SUCCESS; } -NTSTATUS FASTCALL -InitDesktopImpl(VOID) -{ - WNDCLASSEXW wcx; - - /* - * Create the desktop window class - */ - wcx.style = 0; - wcx.lpfnWndProc = IntDesktopWindowProc; - wcx.cbClsExtra = wcx.cbWndExtra = 0; - wcx.hInstance = wcx.hIcon = wcx.hCursor = NULL; - wcx.hbrBackground = NULL; - wcx.lpszMenuName = NULL; - wcx.lpszClassName = L"DesktopWindowClass"; - DesktopWindowClass = IntCreateClass(&wcx, TRUE, IntDesktopWindowProc, - (RTL_ATOM)32880); - - return STATUS_SUCCESS; -} - -NTSTATUS FASTCALL -CleanupDesktopImpl(VOID) -{ - /* FIXME: Unregister the desktop window class */ - - return STATUS_SUCCESS; -} - /* PRIVATE FUNCTIONS **********************************************************/ /* @@ -228,58 +194,6 @@ IntGetWindowStationObject(PWINSTATION_OBJECT Object) return NT_SUCCESS(Status); } -LRESULT CALLBACK -IntDesktopWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) - { - case WM_CREATE: - return 0; - - case WM_NCCREATE: - return 1; - - case WM_ERASEBKGND: - return NtUserPaintDesktop((HDC)wParam); - - default: - return 0; - } -} - -/* - * 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; -} - BOOL FASTCALL IntInitializeDesktopGraphics(VOID) { @@ -322,36 +236,6 @@ IntGetScreenDC(VOID) return ScreenDeviceContext; } -PDESKTOP_OBJECT FASTCALL -IntGetActiveDesktop(VOID) -{ - return InputDesktop; -} - -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) -{ - PDESKTOP_OBJECT pdo = IntGetActiveDesktop(); - if (!pdo) - { - DPRINT("No active desktop\n"); - return; - } - pdo->ActiveMessageQueue = NewQueue; -} - /* PUBLIC FUNCTIONS ***********************************************************/ /* @@ -893,560 +777,6 @@ NtUserSetWindowStationUser( return 0; } -/* - * 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; - - Status = IntValidateWindowStationHandle( - hWindowStation, - KernelMode, - 0, - &WinStaObject); - - if (!NT_SUCCESS(Status)) - { - DPRINT("Failed validation of window station handle (0x%X)\n", - hWindowStation); - SetLastNtError(Status); - return 0; - } - - if (!IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name, - lpszDesktopName)) - { - SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); - ObDereferenceObject(WinStaObject); - return 0; - } - - 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, - NULL, - UserMode, - dwDesiredAccess, - NULL, - &Desktop); - - if (NT_SUCCESS(Status)) - { - DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName); - ExFreePool(DesktopName.Buffer); - return Desktop; - } - - /* - * No existing desktop found, try to create new one - */ - - Status = ObCreateObject( - ExGetPreviousMode(), - ExDesktopObjectType, - &ObjectAttributes, - ExGetPreviousMode(), - NULL, - sizeof(DESKTOP_OBJECT), - 0, - 0, - (PVOID*)&DesktopObject); - - if (!NT_SUCCESS(Status)) - { - DPRINT("Failed creating desktop (%wZ)\n", &DesktopName); - ExFreePool(DesktopName.Buffer); - SetLastNtError(STATUS_UNSUCCESSFUL); - return((HDESK)0); - } - - /* FIXME: Set correct dimensions. */ - DesktopObject->WorkArea.left = 0; - DesktopObject->WorkArea.top = 0; - DesktopObject->WorkArea.right = 640; - DesktopObject->WorkArea.bottom = 480; - - /* Initialize some local (to win32k) desktop state. */ - DesktopObject->ActiveMessageQueue = NULL; - DesktopObject->DesktopWindow = IntCreateDesktopWindow( - DesktopObject->WindowStation, - DesktopWindowClass, - DesktopObject->WorkArea.right, - DesktopObject->WorkArea.bottom); - - DPRINT("Created Desktop Window: %08x\n", DesktopObject->DesktopWindow); - - Status = ObInsertObject( - (PVOID)DesktopObject, - NULL, - STANDARD_RIGHTS_REQUIRED, - 0, - NULL, - &Desktop); - - ObDereferenceObject(DesktopObject); - ExFreePool(DesktopName.Buffer); - - if (!NT_SUCCESS(Status)) - { - DPRINT("Failed to create desktop handle\n"); - SetLastNtError(STATUS_UNSUCCESSFUL); - return 0; - } - - return Desktop; -} - -/* - * NtUserOpenDesktop - * - * Opens an existing desktop. - * - * Parameters - * lpszDesktopName - * Name of the existing desktop. - * - * dwFlags - * Interaction flags. - * - * dwDesiredAccess - * Requested type of access. - * - * Return Value - * Handle to the desktop or zero on failure. - * - * Status - * @implemented - */ - -HDESK STDCALL -NtUserOpenDesktop( - PUNICODE_STRING lpszDesktopName, - DWORD dwFlags, - ACCESS_MASK dwDesiredAccess) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - PWINSTATION_OBJECT WinStaObject; - UNICODE_STRING DesktopName; - NTSTATUS Status; - HDESK Desktop; - - /* - * Validate the window station handle and compose the fully - * qualified desktop name - */ - - Status = IntValidateWindowStationHandle( - PROCESS_WINDOW_STATION(), - KernelMode, - 0, - &WinStaObject); - - if (!NT_SUCCESS(Status)) - { - DPRINT("Failed validation of window station handle (0x%X)\n", - PROCESS_WINDOW_STATION()); - SetLastNtError(Status); - return 0; - } - - if (!IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name, - lpszDesktopName)) - { - SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); - ObDereferenceObject(WinStaObject); - return 0; - } - - ObDereferenceObject(WinStaObject); - - DPRINT("Trying to open desktop station (%wZ)\n", &DesktopName); - - /* Initialize ObjectAttributes for the desktop object */ - InitializeObjectAttributes( - &ObjectAttributes, - &DesktopName, - 0, - NULL, - NULL); - - Status = ObOpenObjectByName( - &ObjectAttributes, - ExDesktopObjectType, - NULL, - UserMode, - dwDesiredAccess, - NULL, - &Desktop); - - if (!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - ExFreePool(DesktopName.Buffer); - return 0; - } - - DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName); - ExFreePool(DesktopName.Buffer); - - return Desktop; -} - -/* - * NtUserOpenInputDesktop - * - * Opens the input (interactive) desktop. - * - * Parameters - * dwFlags - * Interaction flags. - * - * fInherit - * Inheritance option. - * - * dwDesiredAccess - * Requested type of access. - * - * Return Value - * Handle to the input desktop or zero on failure. - * - * Status - * @implemented - */ - -HDESK STDCALL -NtUserOpenInputDesktop( - DWORD dwFlags, - BOOL fInherit, - ACCESS_MASK dwDesiredAccess) -{ - PDESKTOP_OBJECT Object; - NTSTATUS Status; - HDESK Desktop; - - DPRINT("About to open input desktop\n"); - - /* Get a pointer to the desktop object */ - - Status = IntValidateDesktopHandle( - InputDesktop, - KernelMode, - 0, - &Object); - - if (!NT_SUCCESS(Status)) - { - DPRINT("Validation of input desktop handle (0x%X) failed\n", InputDesktop); - return (HDESK)0; - } - - /* Create a new handle to the object */ - - Status = ObOpenObjectByPointer( - Object, - 0, - NULL, - dwDesiredAccess, - ExDesktopObjectType, - UserMode, - &Desktop); - - ObDereferenceObject(Object); - - if (NT_SUCCESS(Status)) - { - DPRINT("Successfully opened input desktop\n"); - return (HDESK)Desktop; - } - - SetLastNtError(Status); - return (HDESK)0; -} - -/* - * NtUserCloseDesktop - * - * Closes a desktop handle. - * - * Parameters - * hDesktop - * Handle to the desktop. - * - * Return Value - * Status - * - * Remarks - * The desktop handle can be created with NtUserCreateDesktop or - * NtUserOpenDesktop. This function will fail if any thread in the calling - * process is using the specified desktop handle or if the handle refers - * to the initial desktop of the calling process. - * - * Status - * @implemented - */ - -BOOL STDCALL -NtUserCloseDesktop(HDESK hDesktop) -{ - PDESKTOP_OBJECT Object; - NTSTATUS Status; - - DPRINT("About to close desktop handle (0x%X)\n", hDesktop); - - Status = IntValidateDesktopHandle( - hDesktop, - KernelMode, - 0, - &Object); - - if (!NT_SUCCESS(Status)) - { - DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop); - return FALSE; - } - - ObDereferenceObject(Object); - - DPRINT("Closing desktop handle (0x%X)\n", hDesktop); - - Status = ZwClose(hDesktop); - if (!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - return FALSE; - } - - return TRUE; -} - -/* - * NtUserPaintDesktop - * - * The NtUserPaintDesktop function fills the clipping region in the - * specified device context with the desktop pattern or wallpaper. The - * function is provided primarily for shell desktops. - * - * Parameters - * hdc - * Handle to the device context. - * - * Status - * @implemented - */ - -BOOL STDCALL -NtUserPaintDesktop(HDC hDC) -{ - HWND hwnd = IntGetDesktopWindow(); - - /* - * Check for an owning thread, otherwise don't paint anything - * (non-desktop mode) - */ - - if (NtUserGetWindowThreadProcessId(hwnd, NULL)) - { - RECT Rect; - HBRUSH PreviousBrush; - - NtUserGetClientRect(hwnd, &Rect); - - /* - * Paint desktop background - */ - - PreviousBrush = NtGdiSelectObject(hDC, NtGdiGetSysColorBrush(COLOR_BACKGROUND)); - NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY); - NtGdiSelectObject(hDC, PreviousBrush); - } - - return TRUE; -} - -/* - * 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; - - DPRINT("About to switch desktop (0x%X)\n", hDesktop); - - Status = IntValidateDesktopHandle( - hDesktop, - KernelMode, - 0, - &DesktopObject); - - if (!NT_SUCCESS(Status)) - { - DPRINT("Validation of desktop handle (0x%X) failed\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; -} - -/* - * NtUserResolveDesktopForWOW - * - * Status - * @unimplemented - */ - -DWORD STDCALL -NtUserResolveDesktopForWOW(DWORD Unknown0) -{ - UNIMPLEMENTED - return 0; -} - -/* - * NtUserGetThreadDesktop - * - * Status - * @unimplemented - */ - -HDESK STDCALL -NtUserGetThreadDesktop(DWORD dwThreadId, DWORD Unknown1) -{ - UNIMPLEMENTED - return 0; -} - -/* - * NtUserSetThreadDesktop - * - * Status - * @implemented - */ - -BOOL STDCALL -NtUserSetThreadDesktop(HDESK hDesktop) -{ - PDESKTOP_OBJECT DesktopObject; - NTSTATUS Status; - - /* Validate the new desktop. */ - Status = IntValidateDesktopHandle( - hDesktop, - KernelMode, - 0, - &DesktopObject); - - if (!NT_SUCCESS(Status)) - { - DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop); - return FALSE; - } - - /* Check for setting the same desktop as before. */ - if (DesktopObject == PsGetWin32Thread()->Desktop) - { - ObDereferenceObject(DesktopObject); - return TRUE; - } - - /* FIXME: Should check here to see if the thread has any windows. */ - - if (PsGetWin32Thread()->Desktop != NULL) - { - ObDereferenceObject(PsGetWin32Thread()->Desktop); - } - - PsGetWin32Thread()->Desktop = DesktopObject; - - return TRUE; -} - /* * NtUserBuildNameList * diff --git a/reactos/subsys/win32k/objects/cursoricon.c b/reactos/subsys/win32k/objects/cursoricon.c index 99d71abd851..ff2a448c001 100644 --- a/reactos/subsys/win32k/objects/cursoricon.c +++ b/reactos/subsys/win32k/objects/cursoricon.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: cursoricon.c,v 1.27 2003/12/03 21:38:14 gvg Exp $ */ +/* $Id: cursoricon.c,v 1.28 2003/12/07 19:29:33 weiden Exp $ */ #undef WIN32_LEAN_AND_MEAN @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/reactos/subsys/win32k/objects/dc.c b/reactos/subsys/win32k/objects/dc.c index 09498790b7d..5308cc9831d 100644 --- a/reactos/subsys/win32k/objects/dc.c +++ b/reactos/subsys/win32k/objects/dc.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: dc.c,v 1.106 2003/12/03 21:37:34 gvg Exp $ +/* $Id: dc.c,v 1.107 2003/12/07 19:29:33 weiden Exp $ * * DC.C - Device context functions * @@ -48,6 +48,7 @@ #include #include #include +#include #define NDEBUG #include