1 /* $Id: misc.c,v 1.55 2004/03/23 21:47:37 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>
30 #include <include/tags.h>
35 void W32kRegisterPrimitiveMessageQueue() {
36 extern PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue
;
37 if( !pmPrimitiveMessageQueue
) {
39 pThread
= PsGetWin32Thread();
40 if( pThread
&& pThread
->MessageQueue
) {
41 pmPrimitiveMessageQueue
= pThread
->MessageQueue
;
42 DPRINT( "Installed primitive input queue.\n" );
45 DPRINT1( "Alert! Someone is trying to steal the primitive queue.\n" );
49 PUSER_MESSAGE_QUEUE
W32kGetPrimitiveMessageQueue() {
50 extern PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue
;
51 return pmPrimitiveMessageQueue
;
59 NtUserCallNoParam(DWORD Routine
)
65 case NOPARAM_ROUTINE_REGISTER_PRIMITIVE
:
66 W32kRegisterPrimitiveMessageQueue();
70 case NOPARAM_ROUTINE_DESTROY_CARET
:
71 Result
= (DWORD
)IntDestroyCaret(PsGetCurrentThread()->Win32Thread
);
74 case NOPARAM_ROUTINE_INIT_MESSAGE_PUMP
:
75 Result
= (DWORD
)IntInitMessagePumpHook();
78 case NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP
:
79 Result
= (DWORD
)IntUninitMessagePumpHook();
82 case NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO
:
83 Result
= (DWORD
)MsqGetMessageExtraInfo();
87 DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam\n");
88 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
105 PWINSTATION_OBJECT WinStaObject
;
106 PWINDOW_OBJECT WindowObject
;
110 case ONEPARAM_ROUTINE_GETMENU
:
111 WindowObject
= IntGetWindowObject((HWND
)Param
);
114 SetLastWin32Error(ERROR_INVALID_HANDLE
);
118 Result
= (DWORD
)WindowObject
->IDMenu
;
120 IntReleaseWindowObject(WindowObject
);
123 case ONEPARAM_ROUTINE_ISWINDOWUNICODE
:
124 WindowObject
= IntGetWindowObject((HWND
)Param
);
127 SetLastWin32Error(ERROR_INVALID_HANDLE
);
130 Result
= WindowObject
->Unicode
;
131 IntReleaseWindowObject(WindowObject
);
134 case ONEPARAM_ROUTINE_WINDOWFROMDC
:
135 return (DWORD
)IntWindowFromDC((HDC
)Param
);
137 case ONEPARAM_ROUTINE_GETWNDCONTEXTHLPID
:
138 WindowObject
= IntGetWindowObject((HWND
)Param
);
141 SetLastWin32Error(ERROR_INVALID_HANDLE
);
145 Result
= WindowObject
->ContextHelpId
;
147 IntReleaseWindowObject(WindowObject
);
150 case ONEPARAM_ROUTINE_SWAPMOUSEBUTTON
:
151 Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
155 if (!NT_SUCCESS(Status
))
158 Result
= (DWORD
)IntSwapMouseButton(WinStaObject
, (BOOL
)Param
);
160 ObDereferenceObject(WinStaObject
);
163 case ONEPARAM_ROUTINE_SWITCHCARETSHOWING
:
164 return (DWORD
)IntSwitchCaretShowing((PVOID
)Param
);
166 case ONEPARAM_ROUTINE_SETCARETBLINKTIME
:
167 return (DWORD
)IntSetCaretBlinkTime((UINT
)Param
);
169 case ONEPARAM_ROUTINE_ENUMCLIPBOARDFORMATS
:
170 return (DWORD
)IntEnumClipboardFormats((UINT
)Param
);
172 case ONEPARAM_ROUTINE_SETMESSAGEEXTRAINFO
:
173 return (DWORD
)MsqSetMessageExtraInfo((LPARAM
)Param
);
175 DPRINT1("Calling invalid routine number 0x%x in NtUserCallOneParam()\n Param=0x%x\n",
177 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
193 PWINDOW_OBJECT WindowObject
;
194 PSYSTEM_CURSORINFO CurInfo
;
195 PWINSTATION_OBJECT WinStaObject
;
200 case TWOPARAM_ROUTINE_GETWINDOWRGNBOX
:
204 Ret
= (DWORD
)IntGetWindowRgnBox((HWND
)Param1
, &rcRect
);
205 Status
= MmCopyToCaller((PVOID
)Param2
, &rcRect
, sizeof(RECT
));
206 if(!NT_SUCCESS(Status
))
208 SetLastNtError(Status
);
213 case TWOPARAM_ROUTINE_GETWINDOWRGN
:
215 return (DWORD
)IntGetWindowRgn((HWND
)Param1
, (HRGN
)Param2
);
217 case TWOPARAM_ROUTINE_SETMENUBARHEIGHT
:
220 PMENU_OBJECT MenuObject
= IntGetMenuObject((HMENU
)Param1
);
226 Ret
= (MenuObject
->MenuInfo
.Height
== (int)Param2
);
227 MenuObject
->MenuInfo
.Height
= (int)Param2
;
230 Ret
= (DWORD
)MenuObject
->MenuInfo
.Height
;
231 IntReleaseMenuObject(MenuObject
);
234 case TWOPARAM_ROUTINE_SETMENUITEMRECT
:
237 SETMENUITEMRECT smir
;
238 PMENU_OBJECT MenuObject
= IntGetMenuObject((HMENU
)Param1
);
242 if(!NT_SUCCESS(MmCopyFromCaller(&smir
, (PVOID
)Param2
, sizeof(SETMENUITEMRECT
))))
244 IntReleaseMenuObject(MenuObject
);
248 Ret
= IntSetMenuItemRect(MenuObject
, smir
.uItem
, smir
.fByPosition
, &smir
.rcRect
);
250 IntReleaseMenuObject(MenuObject
);
254 case TWOPARAM_ROUTINE_SETGUITHRDHANDLE
:
257 PUSER_MESSAGE_QUEUE MsgQueue
= PsGetCurrentThread()->Win32Thread
->MessageQueue
;
261 case TPR_SGTH_ACTIVE
:
262 hwnd
= &MsgQueue
->ActiveWindow
;
265 hwnd
= &MsgQueue
->FocusWindow
;
267 case TPR_SGTH_CAPTURE
:
268 hwnd
= &MsgQueue
->CaptureWindow
;
270 case TPR_SGTH_MENUOWNER
:
271 hwnd
= &MsgQueue
->MenuOwner
;
273 case TPR_SGTH_MOVESIZE
:
274 hwnd
= &MsgQueue
->MoveSize
;
277 hwnd
= &MsgQueue
->CaretInfo
->hWnd
;
282 return (DWORD
)(*hwnd
= (HWND
)Param2
);
285 case TWOPARAM_ROUTINE_ENABLEWINDOW
:
289 case TWOPARAM_ROUTINE_UNKNOWN
:
293 case TWOPARAM_ROUTINE_SHOWOWNEDPOPUPS
:
297 case TWOPARAM_ROUTINE_SWITCHTOTHISWINDOW
:
301 case TWOPARAM_ROUTINE_VALIDATERGN
:
302 return (DWORD
)NtUserValidateRgn((HWND
) Param1
, (HRGN
) Param2
);
304 case TWOPARAM_ROUTINE_SETWNDCONTEXTHLPID
:
305 WindowObject
= IntGetWindowObject((HWND
)Param1
);
308 SetLastWin32Error(ERROR_INVALID_HANDLE
);
312 WindowObject
->ContextHelpId
= Param2
;
314 IntReleaseWindowObject(WindowObject
);
317 case TWOPARAM_ROUTINE_CURSORPOSITION
:
320 Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
324 if (!NT_SUCCESS(Status
))
329 /* set cursor position */
331 Status
= MmCopyFromCaller(&Pos
, (PPOINT
)Param1
, sizeof(POINT
));
332 if(!NT_SUCCESS(Status
))
334 ObDereferenceObject(WinStaObject
);
335 SetLastNtError(Status
);
339 CurInfo
= &WinStaObject
->SystemCursor
;
340 /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
342 //CheckClipCursor(&Pos->x, &Pos->y, CurInfo);
343 if((Pos
.x
!= CurInfo
->x
) || (Pos
.y
!= CurInfo
->y
))
345 MouseMoveCursor(Pos
.x
, Pos
.y
);
351 /* get cursor position */
352 /* FIXME - check if process has WINSTA_READATTRIBUTES */
353 Pos
.x
= WinStaObject
->SystemCursor
.x
;
354 Pos
.y
= WinStaObject
->SystemCursor
.y
;
356 Status
= MmCopyToCaller((PPOINT
)Param1
, &Pos
, sizeof(POINT
));
357 if(!NT_SUCCESS(Status
))
359 ObDereferenceObject(WinStaObject
);
360 SetLastNtError(Status
);
366 ObDereferenceObject(WinStaObject
);
370 case TWOPARAM_ROUTINE_SETCARETPOS
:
371 return (DWORD
)IntSetCaretPos((int)Param1
, (int)Param2
);
373 DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam()\n Param1=0x%x Parm2=0x%x\n",
374 Routine
, Param1
, Param2
);
375 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
389 PWINDOW_OBJECT Window
;
391 Window
= IntGetWindowObject(hWnd
);
394 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
398 /* FIXME: Routine can be 0x53 - 0x5E */
401 case HWNDLOCK_ROUTINE_ARRANGEICONICWINDOWS
:
405 case HWNDLOCK_ROUTINE_DRAWMENUBAR
:
409 case HWNDLOCK_ROUTINE_REDRAWFRAME
:
413 case HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOW
:
414 Ret
= IntSetForegroundWindow(Window
);
417 case HWNDLOCK_ROUTINE_UPDATEWINDOW
:
422 IntReleaseWindowObject(Window
);
435 case HWNDOPT_ROUTINE_SETPROGMANWINDOW
:
439 case HWNDOPT_ROUTINE_SETTASKMANWINDOW
:
451 NtUserGetThreadState(
457 return (DWORD
)IntGetThreadFocusWindow();
463 IntGetFontMetricSetting(LPWSTR lpValueName
, PLOGFONTW font
)
465 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
467 static LOGFONTW DefaultFont
= {
468 11, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
469 0, 0, DEFAULT_QUALITY
, VARIABLE_PITCH
| FF_SWISS
,
470 L
"Bitstream Vera Sans"
473 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
475 QueryTable
[0].Name
= lpValueName
;
476 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
477 QueryTable
[0].EntryContext
= font
;
479 Status
= RtlQueryRegistryValues(
481 L
"Control Panel\\Desktop\\WindowMetrics",
486 if (!NT_SUCCESS(Status
))
488 RtlCopyMemory(font
, &DefaultFont
, sizeof(LOGFONTW
));
497 NtUserSystemParametersInfo(
503 static BOOL GradientCaptions
= TRUE
;
505 PWINSTATION_OBJECT WinStaObject
;
507 static BOOL bInitialized
= FALSE
;
508 static LOGFONTW IconFont
;
509 static NONCLIENTMETRICSW pMetrics
;
513 ZeroMemory(&IconFont
, sizeof(LOGFONTW
));
514 ZeroMemory(&pMetrics
, sizeof(NONCLIENTMETRICSW
));
516 IntGetFontMetricSetting(L
"CaptionFont", &pMetrics
.lfCaptionFont
);
517 IntGetFontMetricSetting(L
"SmCaptionFont", &pMetrics
.lfSmCaptionFont
);
518 IntGetFontMetricSetting(L
"MenuFont", &pMetrics
.lfMenuFont
);
519 IntGetFontMetricSetting(L
"StatusFont", &pMetrics
.lfStatusFont
);
520 IntGetFontMetricSetting(L
"MessageFont", &pMetrics
.lfMessageFont
);
521 IntGetFontMetricSetting(L
"IconFont", &IconFont
);
523 pMetrics
.iBorderWidth
= 1;
524 pMetrics
.iScrollWidth
= NtUserGetSystemMetrics(SM_CXVSCROLL
);
525 pMetrics
.iScrollHeight
= NtUserGetSystemMetrics(SM_CYHSCROLL
);
526 pMetrics
.iCaptionWidth
= NtUserGetSystemMetrics(SM_CXSIZE
);
527 pMetrics
.iCaptionHeight
= NtUserGetSystemMetrics(SM_CYSIZE
);
528 pMetrics
.iSmCaptionWidth
= NtUserGetSystemMetrics(SM_CXSMSIZE
);
529 pMetrics
.iSmCaptionHeight
= NtUserGetSystemMetrics(SM_CYSMSIZE
);
530 pMetrics
.iMenuWidth
= NtUserGetSystemMetrics(SM_CXMENUSIZE
);
531 pMetrics
.iMenuHeight
= NtUserGetSystemMetrics(SM_CYMENUSIZE
);
532 pMetrics
.cbSize
= sizeof(LPNONCLIENTMETRICSW
);
539 case SPI_SETDOUBLECLKWIDTH
:
540 case SPI_SETDOUBLECLKHEIGHT
:
541 case SPI_SETDOUBLECLICKTIME
:
543 Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
547 if (!NT_SUCCESS(Status
))
552 case SPI_SETDOUBLECLKWIDTH
:
553 /* FIXME limit the maximum value? */
554 WinStaObject
->SystemCursor
.DblClickWidth
= uiParam
;
556 case SPI_SETDOUBLECLKHEIGHT
:
557 /* FIXME limit the maximum value? */
558 WinStaObject
->SystemCursor
.DblClickHeight
= uiParam
;
560 case SPI_SETDOUBLECLICKTIME
:
561 /* FIXME limit the maximum time to 1000 ms? */
562 WinStaObject
->SystemCursor
.DblClickSpeed
= uiParam
;
566 /* FIXME save the value to the registry */
568 ObDereferenceObject(WinStaObject
);
571 case SPI_SETWORKAREA
:
573 PDESKTOP_OBJECT Desktop
= PsGetWin32Thread()->Desktop
;
577 /* FIXME - Set last error */
581 Status
= MmCopyFromCaller(Desktop
->WorkArea
, (PRECT
)pvParam
, sizeof(RECT
));
582 if(!NT_SUCCESS(Status
))
584 SetLastNtError(Status
);
590 case SPI_GETWORKAREA
:
593 PDESKTOP_OBJECT Desktop
= PsGetWin32Thread()->Desktop
;
597 /* FIXME - Set last error */
601 Rect
= IntGetDesktopWorkArea(Desktop
);
603 Status
= MmCopyToCaller((PRECT
)pvParam
, Desktop
->WorkArea
, sizeof(RECT
));
604 if(!NT_SUCCESS(Status
))
606 SetLastNtError(Status
);
612 case SPI_GETGRADIENTCAPTIONS
:
617 BOOL Ret
= GradientCaptions
;
619 hDC
= IntGetScreenDC();
623 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
625 Ret
= (SurfObj
->iBitmapFormat
> BMF_8BPP
);
629 Status
= MmCopyToCaller(pvParam
, &Ret
, sizeof(BOOL
));
630 if(!NT_SUCCESS(Status
))
632 SetLastNtError(Status
);
637 case SPI_SETGRADIENTCAPTIONS
:
639 Status
= MmCopyFromCaller(&GradientCaptions
, pvParam
, sizeof(BOOL
));
640 if(!NT_SUCCESS(Status
))
642 SetLastNtError(Status
);
647 case SPI_SETFONTSMOOTHING
:
651 Status
= MmCopyFromCaller(&Enable
, pvParam
, sizeof(BOOL
));
652 if(!NT_SUCCESS(Status
))
654 SetLastNtError(Status
);
658 IntEnableFontRendering(Enable
);
662 case SPI_GETFONTSMOOTHING
:
664 BOOL Enabled
= IntIsFontRenderingEnabled();
666 Status
= MmCopyToCaller(pvParam
, &Enabled
, sizeof(BOOL
));
667 if(!NT_SUCCESS(Status
))
669 SetLastNtError(Status
);
674 case SPI_GETICONTITLELOGFONT
:
676 MmCopyToCaller(pvParam
, (PVOID
)&IconFont
, sizeof(LOGFONTW
));
679 case SPI_GETNONCLIENTMETRICS
:
681 /* FIXME: Is this windows default behavior? */
682 LPNONCLIENTMETRICSW lpMetrics
= (LPNONCLIENTMETRICSW
)pvParam
;
683 if ( lpMetrics
->cbSize
!= sizeof(NONCLIENTMETRICSW
) ||
684 uiParam
!= sizeof(NONCLIENTMETRICSW
))
688 DPRINT("FontName: %S, Size: %i\n",pMetrics
.lfMessageFont
.lfFaceName
, pMetrics
.lfMessageFont
.lfHeight
);
689 MmCopyToCaller(pvParam
, (PVOID
)&pMetrics
, sizeof(NONCLIENTMETRICSW
));
698 NtUserGetDoubleClickTime(VOID
)
702 PWINSTATION_OBJECT WinStaObject
;
704 Status
= IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
708 if (!NT_SUCCESS(Status
))
711 Result
= WinStaObject
->SystemCursor
.DblClickSpeed
;
713 ObDereferenceObject(WinStaObject
);
719 NtUserGetGUIThreadInfo(
721 LPGUITHREADINFO lpgui
)
724 PTHRDCARETINFO CaretInfo
;
725 GUITHREADINFO SafeGui
;
726 PDESKTOP_OBJECT Desktop
;
727 PUSER_MESSAGE_QUEUE MsgQueue
;
728 PETHREAD Thread
= NULL
;
730 Status
= MmCopyFromCaller(&SafeGui
, lpgui
, sizeof(DWORD
));
731 if(!NT_SUCCESS(Status
))
733 SetLastNtError(Status
);
737 if(SafeGui
.cbSize
!= sizeof(GUITHREADINFO
))
739 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
745 Status
= PsLookupThreadByThreadId((PVOID
)idThread
, &Thread
);
746 if(!NT_SUCCESS(Status
))
748 SetLastWin32Error(ERROR_ACCESS_DENIED
);
751 Desktop
= Thread
->Win32Thread
->Desktop
;
755 /* get the foreground thread */
756 PW32THREAD W32Thread
= PsGetCurrentThread()->Win32Thread
;
757 Desktop
= W32Thread
->Desktop
;
760 MsgQueue
= Desktop
->ActiveMessageQueue
;
763 Thread
= MsgQueue
->Thread
;
768 if(!Thread
|| !Desktop
)
770 if(idThread
&& Thread
)
771 ObDereferenceObject(Thread
);
772 SetLastWin32Error(ERROR_ACCESS_DENIED
);
776 MsgQueue
= (PUSER_MESSAGE_QUEUE
)Desktop
->ActiveMessageQueue
;
777 CaretInfo
= MsgQueue
->CaretInfo
;
779 SafeGui
.flags
= (CaretInfo
->Visible
? GUI_CARETBLINKING
: 0);
780 if(MsgQueue
->MenuOwner
)
781 SafeGui
.flags
|= GUI_INMENUMODE
| MsgQueue
->MenuState
;
782 if(MsgQueue
->MoveSize
)
783 SafeGui
.flags
|= GUI_INMOVESIZE
;
785 /* FIXME add flag GUI_16BITTASK */
787 SafeGui
.hwndActive
= MsgQueue
->ActiveWindow
;
788 SafeGui
.hwndFocus
= MsgQueue
->FocusWindow
;
789 SafeGui
.hwndCapture
= MsgQueue
->CaptureWindow
;
790 SafeGui
.hwndMenuOwner
= MsgQueue
->MenuOwner
;
791 SafeGui
.hwndMoveSize
= MsgQueue
->MoveSize
;
792 SafeGui
.hwndCaret
= CaretInfo
->hWnd
;
794 SafeGui
.rcCaret
.left
= CaretInfo
->Pos
.x
;
795 SafeGui
.rcCaret
.top
= CaretInfo
->Pos
.y
;
796 SafeGui
.rcCaret
.right
= SafeGui
.rcCaret
.left
+ CaretInfo
->Size
.cx
;
797 SafeGui
.rcCaret
.bottom
= SafeGui
.rcCaret
.top
+ CaretInfo
->Size
.cy
;
800 ObDereferenceObject(Thread
);
802 Status
= MmCopyToCaller(lpgui
, &SafeGui
, sizeof(GUITHREADINFO
));
803 if(!NT_SUCCESS(Status
))
805 SetLastNtError(Status
);
815 NtUserGetGuiResources(
820 PW32PROCESS W32Process
;
824 Status
= ObReferenceObjectByHandle(hProcess
,
825 PROCESS_QUERY_INFORMATION
,
831 if(!NT_SUCCESS(Status
))
833 SetLastNtError(Status
);
837 W32Process
= Process
->Win32Process
;
840 ObDereferenceObject(Process
);
841 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
849 Ret
= (DWORD
)W32Process
->GDIObjects
;
854 Ret
= (DWORD
)W32Process
->UserObjects
;
859 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
864 ObDereferenceObject(Process
);
870 IntSafeCopyUnicodeString(PUNICODE_STRING Dest
,
871 PUNICODE_STRING Source
)
876 Status
= MmCopyFromCaller(Dest
, Source
, sizeof(UNICODE_STRING
));
877 if(!NT_SUCCESS(Status
))
882 if(Dest
->MaximumLength
> 0)
886 Dest
->Buffer
= ExAllocatePoolWithTag(NonPagedPool
, Dest
->MaximumLength
, TAG_STRING
);
889 return STATUS_NO_MEMORY
;
892 Status
= MmCopyFromCaller(Dest
->Buffer
, Src
, Dest
->MaximumLength
);
893 if(!NT_SUCCESS(Status
))
895 ExFreePool(Dest
->Buffer
);
901 return STATUS_SUCCESS
;
903 return STATUS_UNSUCCESSFUL
;