1 /* $Id: misc.c,v 1.45 2004/01/26 12:46:16 weiden Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * PURPOSE: Misc User funcs
6 * FILE: subsys/win32k/ntuser/misc.c
7 * PROGRAMER: Ge van Geldorp (ge@gse.nl)
11 #include <ddk/ntddk.h>
12 #include <ddk/ntddmou.h>
13 #include <win32k/win32k.h>
14 #include <win32k/dc.h>
15 #include <internal/safe.h>
16 #include <include/error.h>
17 #include <include/window.h>
18 #include <include/menu.h>
19 #include <include/painting.h>
20 #include <include/dce.h>
21 #include <include/mouse.h>
22 #include <include/winsta.h>
23 #include <include/caret.h>
24 #include <include/object.h>
25 #include <include/focus.h>
26 #include <include/clipboard.h>
27 #include <include/msgqueue.h>
28 #include <include/desktop.h>
29 #include <include/text.h>
34 void W32kRegisterPrimitiveMessageQueue() {
35 extern PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue
;
36 if( !pmPrimitiveMessageQueue
) {
38 pThread
= PsGetWin32Thread();
39 if( pThread
&& pThread
->MessageQueue
) {
40 pmPrimitiveMessageQueue
= pThread
->MessageQueue
;
41 DPRINT( "Installed primitive input queue.\n" );
44 DPRINT1( "Alert! Someone is trying to steal the primitive queue.\n" );
48 PUSER_MESSAGE_QUEUE
W32kGetPrimitiveMessageQueue() {
49 extern PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue
;
50 return pmPrimitiveMessageQueue
;
58 NtUserCallNoParam(DWORD Routine
)
64 case NOPARAM_ROUTINE_REGISTER_PRIMITIVE
:
65 W32kRegisterPrimitiveMessageQueue();
69 case NOPARAM_ROUTINE_DESTROY_CARET
:
70 Result
= (DWORD
)IntDestroyCaret(PsGetCurrentThread()->Win32Thread
);
73 case NOPARAM_ROUTINE_INIT_MESSAGE_PUMP
:
74 Result
= (DWORD
)IntInitMessagePumpHook();
77 case NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP
:
78 Result
= (DWORD
)IntUninitMessagePumpHook();
81 case NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO
:
82 Result
= (DWORD
)MsqGetMessageExtraInfo();
86 DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam\n");
87 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
104 PWINSTATION_OBJECT WinStaObject
;
105 PWINDOW_OBJECT WindowObject
;
109 case ONEPARAM_ROUTINE_GETMENU
:
110 WindowObject
= IntGetWindowObject((HWND
)Param
);
113 SetLastWin32Error(ERROR_INVALID_HANDLE
);
117 Result
= (DWORD
)WindowObject
->IDMenu
;
119 IntReleaseWindowObject(WindowObject
);
122 case ONEPARAM_ROUTINE_ISWINDOWUNICODE
:
123 WindowObject
= IntGetWindowObject((HWND
)Param
);
126 SetLastWin32Error(ERROR_INVALID_HANDLE
);
129 Result
= WindowObject
->Unicode
;
130 IntReleaseWindowObject(WindowObject
);
133 case ONEPARAM_ROUTINE_WINDOWFROMDC
:
134 return (DWORD
)IntWindowFromDC((HDC
)Param
);
136 case ONEPARAM_ROUTINE_GETWNDCONTEXTHLPID
:
137 WindowObject
= IntGetWindowObject((HWND
)Param
);
140 SetLastWin32Error(ERROR_INVALID_HANDLE
);
144 Result
= WindowObject
->ContextHelpId
;
146 IntReleaseWindowObject(WindowObject
);
149 case ONEPARAM_ROUTINE_SWAPMOUSEBUTTON
:
150 Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
154 if (!NT_SUCCESS(Status
))
157 Result
= (DWORD
)IntSwapMouseButton(WinStaObject
, (BOOL
)Param
);
159 ObDereferenceObject(WinStaObject
);
162 case ONEPARAM_ROUTINE_SWITCHCARETSHOWING
:
163 return (DWORD
)IntSwitchCaretShowing((PVOID
)Param
);
165 case ONEPARAM_ROUTINE_SETCARETBLINKTIME
:
166 return (DWORD
)IntSetCaretBlinkTime((UINT
)Param
);
168 case ONEPARAM_ROUTINE_ENUMCLIPBOARDFORMATS
:
169 return (DWORD
)IntEnumClipboardFormats((UINT
)Param
);
171 case ONEPARAM_ROUTINE_SETMESSAGEEXTRAINFO
:
172 return (DWORD
)MsqSetMessageExtraInfo((LPARAM
)Param
);
174 DPRINT1("Calling invalid routine number 0x%x in NtUserCallOneParam()\n Param=0x%x\n",
176 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
192 PWINDOW_OBJECT WindowObject
;
193 PSYSTEM_CURSORINFO CurInfo
;
194 PWINSTATION_OBJECT WinStaObject
;
199 case TWOPARAM_ROUTINE_SETMENUBARHEIGHT
:
202 PMENU_OBJECT MenuObject
= IntGetMenuObject((HMENU
)Param1
);
206 MenuObject
->Height
= (int)Param2
;
207 Ret
= (DWORD
)MenuObject
->Height
;
208 IntReleaseMenuObject(MenuObject
);
211 case TWOPARAM_ROUTINE_SETMENUITEMRECT
:
214 SETMENUITEMRECT smir
;
215 PMENU_OBJECT MenuObject
= IntGetMenuObject((HMENU
)Param1
);
219 if(!NT_SUCCESS(MmCopyFromCaller(&smir
, (PVOID
)Param2
, sizeof(SETMENUITEMRECT
))))
221 IntReleaseMenuObject(MenuObject
);
225 Ret
= IntSetMenuItemRect(MenuObject
, smir
.uItem
, smir
.fByPosition
, &smir
.rcRect
);
227 IntReleaseMenuObject(MenuObject
);
231 case TWOPARAM_ROUTINE_SETGUITHRDHANDLE
:
234 PUSER_MESSAGE_QUEUE MsgQueue
= PsGetCurrentThread()->Win32Thread
->MessageQueue
;
238 case TPR_SGTH_ACTIVE
:
239 hwnd
= &MsgQueue
->ActiveWindow
;
242 hwnd
= &MsgQueue
->FocusWindow
;
244 case TPR_SGTH_CAPTURE
:
245 hwnd
= &MsgQueue
->CaptureWindow
;
247 case TPR_SGTH_MENUOWNER
:
248 hwnd
= &MsgQueue
->MenuOwner
;
250 case TPR_SGTH_MOVESIZE
:
251 hwnd
= &MsgQueue
->MoveSize
;
254 hwnd
= &MsgQueue
->CaretInfo
->hWnd
;
259 return (DWORD
)(*hwnd
= (HWND
)Param2
);
262 case TWOPARAM_ROUTINE_ENABLEWINDOW
:
266 case TWOPARAM_ROUTINE_UNKNOWN
:
270 case TWOPARAM_ROUTINE_SHOWOWNEDPOPUPS
:
274 case TWOPARAM_ROUTINE_SWITCHTOTHISWINDOW
:
278 case TWOPARAM_ROUTINE_VALIDATERGN
:
279 return (DWORD
)NtUserValidateRgn((HWND
) Param1
, (HRGN
) Param2
);
281 case TWOPARAM_ROUTINE_SETWNDCONTEXTHLPID
:
282 WindowObject
= IntGetWindowObject((HWND
)Param1
);
285 SetLastWin32Error(ERROR_INVALID_HANDLE
);
289 WindowObject
->ContextHelpId
= Param2
;
291 IntReleaseWindowObject(WindowObject
);
294 case TWOPARAM_ROUTINE_CURSORPOSITION
:
297 Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
301 if (!NT_SUCCESS(Status
))
306 /* set cursor position */
308 Status
= MmCopyFromCaller(&Pos
, (PPOINT
)Param1
, sizeof(POINT
));
309 if(!NT_SUCCESS(Status
))
311 ObDereferenceObject(WinStaObject
);
312 SetLastNtError(Status
);
316 CurInfo
= &WinStaObject
->SystemCursor
;
317 /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
319 //CheckClipCursor(&Pos->x, &Pos->y, CurInfo);
320 if((Pos
.x
!= CurInfo
->x
) || (Pos
.y
!= CurInfo
->y
))
322 MouseMoveCursor(Pos
.x
, Pos
.y
);
328 /* get cursor position */
329 /* FIXME - check if process has WINSTA_READATTRIBUTES */
330 Pos
.x
= WinStaObject
->SystemCursor
.x
;
331 Pos
.y
= WinStaObject
->SystemCursor
.y
;
333 Status
= MmCopyToCaller((PPOINT
)Param1
, &Pos
, sizeof(POINT
));
334 if(!NT_SUCCESS(Status
))
336 ObDereferenceObject(WinStaObject
);
337 SetLastNtError(Status
);
343 ObDereferenceObject(WinStaObject
);
347 case TWOPARAM_ROUTINE_SETCARETPOS
:
348 return (DWORD
)IntSetCaretPos((int)Param1
, (int)Param2
);
350 DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam()\n Param1=0x%x Parm2=0x%x\n",
351 Routine
, Param1
, Param2
);
352 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
366 PWINDOW_OBJECT Window
;
368 Window
= IntGetWindowObject(hWnd
);
371 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
375 /* FIXME: Routine can be 0x53 - 0x5E */
378 case HWNDLOCK_ROUTINE_ARRANGEICONICWINDOWS
:
382 case HWNDLOCK_ROUTINE_DRAWMENUBAR
:
386 case HWNDLOCK_ROUTINE_REDRAWFRAME
:
390 case HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOW
:
391 Ret
= IntSetForegroundWindow(Window
);
394 case HWNDLOCK_ROUTINE_UPDATEWINDOW
:
399 IntReleaseWindowObject(Window
);
412 case HWNDOPT_ROUTINE_SETPROGMANWINDOW
:
416 case HWNDOPT_ROUTINE_SETTASKMANWINDOW
:
428 NtUserGetThreadState(
434 return (DWORD
)IntGetThreadFocusWindow();
444 NtUserSystemParametersInfo(
450 static BOOL GradientCaptions
= TRUE
;
451 /* FIXME: This should be obtained from the registry */
452 static LOGFONTW CaptionFont
=
453 { 12, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
454 0, 0, DEFAULT_QUALITY
, VARIABLE_PITCH
| FF_SWISS
, L
"" };
456 PWINSTATION_OBJECT WinStaObject
;
460 case SPI_SETDOUBLECLKWIDTH
:
461 case SPI_SETDOUBLECLKHEIGHT
:
462 case SPI_SETDOUBLECLICKTIME
:
464 Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
468 if (!NT_SUCCESS(Status
))
473 case SPI_SETDOUBLECLKWIDTH
:
474 /* FIXME limit the maximum value? */
475 WinStaObject
->SystemCursor
.DblClickWidth
= uiParam
;
477 case SPI_SETDOUBLECLKHEIGHT
:
478 /* FIXME limit the maximum value? */
479 WinStaObject
->SystemCursor
.DblClickHeight
= uiParam
;
481 case SPI_SETDOUBLECLICKTIME
:
482 /* FIXME limit the maximum time to 1000 ms? */
483 WinStaObject
->SystemCursor
.DblClickSpeed
= uiParam
;
487 /* FIXME save the value to the registry */
489 ObDereferenceObject(WinStaObject
);
492 case SPI_SETWORKAREA
:
494 PDESKTOP_OBJECT Desktop
= PsGetWin32Thread()->Desktop
;
498 /* FIXME - Set last error */
502 Status
= MmCopyFromCaller(Desktop
->WorkArea
, (PRECT
)pvParam
, sizeof(RECT
));
503 if(!NT_SUCCESS(Status
))
505 SetLastNtError(Status
);
511 case SPI_GETWORKAREA
:
514 PDESKTOP_OBJECT Desktop
= PsGetWin32Thread()->Desktop
;
518 /* FIXME - Set last error */
522 Rect
= IntGetDesktopWorkArea(Desktop
);
524 Status
= MmCopyToCaller((PRECT
)pvParam
, Desktop
->WorkArea
, sizeof(RECT
));
525 if(!NT_SUCCESS(Status
))
527 SetLastNtError(Status
);
533 case SPI_GETICONTITLELOGFONT
:
535 Status
= MmCopyToCaller(pvParam
, &CaptionFont
, sizeof(CaptionFont
));
536 if(!NT_SUCCESS(Status
))
538 SetLastNtError(Status
);
543 case SPI_GETNONCLIENTMETRICS
:
545 /* FIXME - use MmCopyToCaller() !!! */
546 LPNONCLIENTMETRICSW pMetrics
= (LPNONCLIENTMETRICSW
)pvParam
;
548 if (pMetrics
->cbSize
!= sizeof(NONCLIENTMETRICSW
) ||
549 uiParam
!= sizeof(NONCLIENTMETRICSW
))
554 memset((char *)pvParam
+ sizeof(pMetrics
->cbSize
), 0,
555 pMetrics
->cbSize
- sizeof(pMetrics
->cbSize
));
557 pMetrics
->iBorderWidth
= 1;
558 pMetrics
->iScrollWidth
= NtUserGetSystemMetrics(SM_CXVSCROLL
);
559 pMetrics
->iScrollHeight
= NtUserGetSystemMetrics(SM_CYHSCROLL
);
560 pMetrics
->iCaptionWidth
= NtUserGetSystemMetrics(SM_CXSIZE
);
561 pMetrics
->iCaptionHeight
= NtUserGetSystemMetrics(SM_CYSIZE
);
562 memcpy((LPVOID
)&(pMetrics
->lfCaptionFont
), &CaptionFont
, sizeof(CaptionFont
));
563 pMetrics
->lfCaptionFont
.lfWeight
= FW_BOLD
;
564 pMetrics
->iSmCaptionWidth
= NtUserGetSystemMetrics(SM_CXSMSIZE
);
565 pMetrics
->iSmCaptionHeight
= NtUserGetSystemMetrics(SM_CYSMSIZE
);
566 memcpy((LPVOID
)&(pMetrics
->lfSmCaptionFont
), &CaptionFont
, sizeof(CaptionFont
));
567 pMetrics
->iMenuWidth
= NtUserGetSystemMetrics(SM_CXMENUSIZE
);
568 pMetrics
->iMenuHeight
= NtUserGetSystemMetrics(SM_CYMENUSIZE
);
569 memcpy((LPVOID
)&(pMetrics
->lfMenuFont
), &CaptionFont
, sizeof(CaptionFont
));
570 memcpy((LPVOID
)&(pMetrics
->lfStatusFont
), &CaptionFont
, sizeof(CaptionFont
));
571 memcpy((LPVOID
)&(pMetrics
->lfMessageFont
), &CaptionFont
, sizeof(CaptionFont
));
574 case SPI_GETGRADIENTCAPTIONS
:
579 BOOL Ret
= GradientCaptions
;
581 hDC
= IntGetScreenDC();
585 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
587 Ret
= (SurfObj
->iBitmapFormat
> BMF_8BPP
);
591 Status
= MmCopyToCaller(pvParam
, &Ret
, sizeof(BOOL
));
592 if(!NT_SUCCESS(Status
))
594 SetLastNtError(Status
);
599 case SPI_SETGRADIENTCAPTIONS
:
601 Status
= MmCopyFromCaller(&GradientCaptions
, pvParam
, sizeof(BOOL
));
602 if(!NT_SUCCESS(Status
))
604 SetLastNtError(Status
);
609 case SPI_SETFONTSMOOTHING
:
613 Status
= MmCopyFromCaller(&Enable
, pvParam
, sizeof(BOOL
));
614 if(!NT_SUCCESS(Status
))
616 SetLastNtError(Status
);
620 IntEnableFontRendering(Enable
);
624 case SPI_GETFONTSMOOTHING
:
626 BOOL Enabled
= IntIsFontRenderingEnabled();
628 Status
= MmCopyToCaller(pvParam
, &Enabled
, sizeof(BOOL
));
629 if(!NT_SUCCESS(Status
))
631 SetLastNtError(Status
);
642 NtUserGetDoubleClickTime(VOID
)
646 PWINSTATION_OBJECT WinStaObject
;
648 Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
652 if (!NT_SUCCESS(Status
))
655 Result
= WinStaObject
->SystemCursor
.DblClickSpeed
;
657 ObDereferenceObject(WinStaObject
);
663 NtUserGetGUIThreadInfo(
665 LPGUITHREADINFO lpgui
)
668 PTHRDCARETINFO CaretInfo
;
669 GUITHREADINFO SafeGui
;
670 PDESKTOP_OBJECT Desktop
;
671 PUSER_MESSAGE_QUEUE MsgQueue
;
672 PETHREAD Thread
= NULL
;
674 Status
= MmCopyFromCaller(&SafeGui
, lpgui
, sizeof(DWORD
));
675 if(!NT_SUCCESS(Status
))
677 SetLastNtError(Status
);
681 if(SafeGui
.cbSize
!= sizeof(GUITHREADINFO
))
683 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
689 Status
= PsLookupThreadByThreadId((PVOID
)idThread
, &Thread
);
690 if(!NT_SUCCESS(Status
))
692 SetLastWin32Error(ERROR_ACCESS_DENIED
);
695 Desktop
= Thread
->Win32Thread
->Desktop
;
699 /* get the foreground thread */
700 PW32THREAD W32Thread
= PsGetCurrentThread()->Win32Thread
;
701 Desktop
= W32Thread
->Desktop
;
704 MsgQueue
= Desktop
->ActiveMessageQueue
;
707 Thread
= MsgQueue
->Thread
;
712 if(!Thread
|| !Desktop
)
714 if(idThread
&& Thread
)
715 ObDereferenceObject(Thread
);
716 SetLastWin32Error(ERROR_ACCESS_DENIED
);
720 MsgQueue
= (PUSER_MESSAGE_QUEUE
)Desktop
->ActiveMessageQueue
;
721 CaretInfo
= MsgQueue
->CaretInfo
;
723 SafeGui
.flags
= (CaretInfo
->Visible
? GUI_CARETBLINKING
: 0);
724 if(MsgQueue
->MenuOwner
)
725 SafeGui
.flags
|= GUI_INMENUMODE
| MsgQueue
->MenuState
;
726 if(MsgQueue
->MoveSize
)
727 SafeGui
.flags
|= GUI_INMOVESIZE
;
729 /* FIXME add flag GUI_16BITTASK */
731 SafeGui
.hwndActive
= MsgQueue
->ActiveWindow
;
732 SafeGui
.hwndFocus
= MsgQueue
->FocusWindow
;
733 SafeGui
.hwndCapture
= MsgQueue
->CaptureWindow
;
734 SafeGui
.hwndMenuOwner
= MsgQueue
->MenuOwner
;
735 SafeGui
.hwndMoveSize
= MsgQueue
->MoveSize
;
736 SafeGui
.hwndCaret
= CaretInfo
->hWnd
;
738 SafeGui
.rcCaret
.left
= CaretInfo
->Pos
.x
;
739 SafeGui
.rcCaret
.top
= CaretInfo
->Pos
.y
;
740 SafeGui
.rcCaret
.right
= SafeGui
.rcCaret
.left
+ CaretInfo
->Size
.cx
;
741 SafeGui
.rcCaret
.bottom
= SafeGui
.rcCaret
.top
+ CaretInfo
->Size
.cy
;
744 ObDereferenceObject(Thread
);
746 Status
= MmCopyToCaller(lpgui
, &SafeGui
, sizeof(GUITHREADINFO
));
747 if(!NT_SUCCESS(Status
))
749 SetLastNtError(Status
);
759 NtUserGetGuiResources(
764 PW32PROCESS W32Process
;
768 Status
= ObReferenceObjectByHandle(hProcess
,
769 PROCESS_QUERY_INFORMATION
,
775 if(!NT_SUCCESS(Status
))
777 SetLastNtError(Status
);
781 W32Process
= Process
->Win32Process
;
784 ObDereferenceObject(Process
);
785 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
793 Ret
= (DWORD
)W32Process
->GDIObjects
;
798 Ret
= (DWORD
)W32Process
->UserObjects
;
803 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
808 ObDereferenceObject(Process
);
814 IntSafeCopyUnicodeString(PUNICODE_STRING Dest
,
815 PUNICODE_STRING Source
)
820 Status
= MmCopyFromCaller(Dest
, Source
, sizeof(UNICODE_STRING
));
821 if(!NT_SUCCESS(Status
))
826 if(Dest
->MaximumLength
> 0)
830 Dest
->Buffer
= ExAllocatePool(NonPagedPool
, Dest
->MaximumLength
);
833 return STATUS_NO_MEMORY
;
836 Status
= MmCopyFromCaller(Dest
->Buffer
, Src
, Dest
->MaximumLength
);
837 if(!NT_SUCCESS(Status
))
839 ExFreePool(Dest
->Buffer
);
845 return STATUS_SUCCESS
;
847 return STATUS_UNSUCCESSFUL
;