Implemented GetWindowRgn() and GetWindowRgnBox()
[reactos.git] / reactos / subsys / win32k / ntuser / misc.c
1 /* $Id: misc.c,v 1.55 2004/03/23 21:47:37 weiden Exp $
2 *
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)
8 * REVISION HISTORY:
9 * 2003/05/22 Created
10 */
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>
31
32 #define NDEBUG
33 #include <debug.h>
34
35 void W32kRegisterPrimitiveMessageQueue() {
36 extern PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue;
37 if( !pmPrimitiveMessageQueue ) {
38 PW32THREAD pThread;
39 pThread = PsGetWin32Thread();
40 if( pThread && pThread->MessageQueue ) {
41 pmPrimitiveMessageQueue = pThread->MessageQueue;
42 DPRINT( "Installed primitive input queue.\n" );
43 }
44 } else {
45 DPRINT1( "Alert! Someone is trying to steal the primitive queue.\n" );
46 }
47 }
48
49 PUSER_MESSAGE_QUEUE W32kGetPrimitiveMessageQueue() {
50 extern PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue;
51 return pmPrimitiveMessageQueue;
52 }
53
54 /*
55 * @unimplemented
56 */
57 DWORD
58 STDCALL
59 NtUserCallNoParam(DWORD Routine)
60 {
61 DWORD Result = 0;
62
63 switch(Routine)
64 {
65 case NOPARAM_ROUTINE_REGISTER_PRIMITIVE:
66 W32kRegisterPrimitiveMessageQueue();
67 Result = (DWORD)TRUE;
68 break;
69
70 case NOPARAM_ROUTINE_DESTROY_CARET:
71 Result = (DWORD)IntDestroyCaret(PsGetCurrentThread()->Win32Thread);
72 break;
73
74 case NOPARAM_ROUTINE_INIT_MESSAGE_PUMP:
75 Result = (DWORD)IntInitMessagePumpHook();
76 break;
77
78 case NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP:
79 Result = (DWORD)IntUninitMessagePumpHook();
80 break;
81
82 case NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO:
83 Result = (DWORD)MsqGetMessageExtraInfo();
84 break;
85
86 default:
87 DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam\n");
88 SetLastWin32Error(ERROR_INVALID_PARAMETER);
89 break;
90 }
91 return Result;
92 }
93
94 /*
95 * @implemented
96 */
97 DWORD
98 STDCALL
99 NtUserCallOneParam(
100 DWORD Param,
101 DWORD Routine)
102 {
103 NTSTATUS Status;
104 DWORD Result = 0;
105 PWINSTATION_OBJECT WinStaObject;
106 PWINDOW_OBJECT WindowObject;
107
108 switch(Routine)
109 {
110 case ONEPARAM_ROUTINE_GETMENU:
111 WindowObject = IntGetWindowObject((HWND)Param);
112 if(!WindowObject)
113 {
114 SetLastWin32Error(ERROR_INVALID_HANDLE);
115 return FALSE;
116 }
117
118 Result = (DWORD)WindowObject->IDMenu;
119
120 IntReleaseWindowObject(WindowObject);
121 return Result;
122
123 case ONEPARAM_ROUTINE_ISWINDOWUNICODE:
124 WindowObject = IntGetWindowObject((HWND)Param);
125 if(!WindowObject)
126 {
127 SetLastWin32Error(ERROR_INVALID_HANDLE);
128 return FALSE;
129 }
130 Result = WindowObject->Unicode;
131 IntReleaseWindowObject(WindowObject);
132 return Result;
133
134 case ONEPARAM_ROUTINE_WINDOWFROMDC:
135 return (DWORD)IntWindowFromDC((HDC)Param);
136
137 case ONEPARAM_ROUTINE_GETWNDCONTEXTHLPID:
138 WindowObject = IntGetWindowObject((HWND)Param);
139 if(!WindowObject)
140 {
141 SetLastWin32Error(ERROR_INVALID_HANDLE);
142 return FALSE;
143 }
144
145 Result = WindowObject->ContextHelpId;
146
147 IntReleaseWindowObject(WindowObject);
148 return Result;
149
150 case ONEPARAM_ROUTINE_SWAPMOUSEBUTTON:
151 Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
152 KernelMode,
153 0,
154 &WinStaObject);
155 if (!NT_SUCCESS(Status))
156 return (DWORD)FALSE;
157
158 Result = (DWORD)IntSwapMouseButton(WinStaObject, (BOOL)Param);
159
160 ObDereferenceObject(WinStaObject);
161 return Result;
162
163 case ONEPARAM_ROUTINE_SWITCHCARETSHOWING:
164 return (DWORD)IntSwitchCaretShowing((PVOID)Param);
165
166 case ONEPARAM_ROUTINE_SETCARETBLINKTIME:
167 return (DWORD)IntSetCaretBlinkTime((UINT)Param);
168
169 case ONEPARAM_ROUTINE_ENUMCLIPBOARDFORMATS:
170 return (DWORD)IntEnumClipboardFormats((UINT)Param);
171
172 case ONEPARAM_ROUTINE_SETMESSAGEEXTRAINFO:
173 return (DWORD)MsqSetMessageExtraInfo((LPARAM)Param);
174 }
175 DPRINT1("Calling invalid routine number 0x%x in NtUserCallOneParam()\n Param=0x%x\n",
176 Routine, Param);
177 SetLastWin32Error(ERROR_INVALID_PARAMETER);
178 return 0;
179 }
180
181
182 /*
183 * @implemented
184 */
185 DWORD
186 STDCALL
187 NtUserCallTwoParam(
188 DWORD Param1,
189 DWORD Param2,
190 DWORD Routine)
191 {
192 NTSTATUS Status;
193 PWINDOW_OBJECT WindowObject;
194 PSYSTEM_CURSORINFO CurInfo;
195 PWINSTATION_OBJECT WinStaObject;
196 POINT Pos;
197
198 switch(Routine)
199 {
200 case TWOPARAM_ROUTINE_GETWINDOWRGNBOX:
201 {
202 DWORD Ret;
203 RECT rcRect;
204 Ret = (DWORD)IntGetWindowRgnBox((HWND)Param1, &rcRect);
205 Status = MmCopyToCaller((PVOID)Param2, &rcRect, sizeof(RECT));
206 if(!NT_SUCCESS(Status))
207 {
208 SetLastNtError(Status);
209 return ERROR;
210 }
211 return Ret;
212 }
213 case TWOPARAM_ROUTINE_GETWINDOWRGN:
214 {
215 return (DWORD)IntGetWindowRgn((HWND)Param1, (HRGN)Param2);
216 }
217 case TWOPARAM_ROUTINE_SETMENUBARHEIGHT:
218 {
219 DWORD Ret;
220 PMENU_OBJECT MenuObject = IntGetMenuObject((HMENU)Param1);
221 if(!MenuObject)
222 return 0;
223
224 if(Param2 > 0)
225 {
226 Ret = (MenuObject->MenuInfo.Height == (int)Param2);
227 MenuObject->MenuInfo.Height = (int)Param2;
228 }
229 else
230 Ret = (DWORD)MenuObject->MenuInfo.Height;
231 IntReleaseMenuObject(MenuObject);
232 return Ret;
233 }
234 case TWOPARAM_ROUTINE_SETMENUITEMRECT:
235 {
236 BOOL Ret;
237 SETMENUITEMRECT smir;
238 PMENU_OBJECT MenuObject = IntGetMenuObject((HMENU)Param1);
239 if(!MenuObject)
240 return 0;
241
242 if(!NT_SUCCESS(MmCopyFromCaller(&smir, (PVOID)Param2, sizeof(SETMENUITEMRECT))))
243 {
244 IntReleaseMenuObject(MenuObject);
245 return 0;
246 }
247
248 Ret = IntSetMenuItemRect(MenuObject, smir.uItem, smir.fByPosition, &smir.rcRect);
249
250 IntReleaseMenuObject(MenuObject);
251 return (DWORD)Ret;
252 }
253
254 case TWOPARAM_ROUTINE_SETGUITHRDHANDLE:
255 {
256 HWND *hwnd;
257 PUSER_MESSAGE_QUEUE MsgQueue = PsGetCurrentThread()->Win32Thread->MessageQueue;
258
259 switch(Param1)
260 {
261 case TPR_SGTH_ACTIVE:
262 hwnd = &MsgQueue->ActiveWindow;
263 break;
264 case TPR_SGTH_FOCUS:
265 hwnd = &MsgQueue->FocusWindow;
266 break;
267 case TPR_SGTH_CAPTURE:
268 hwnd = &MsgQueue->CaptureWindow;
269 break;
270 case TPR_SGTH_MENUOWNER:
271 hwnd = &MsgQueue->MenuOwner;
272 break;
273 case TPR_SGTH_MOVESIZE:
274 hwnd = &MsgQueue->MoveSize;
275 break;
276 case TPR_SGTH_CARET:
277 hwnd = &MsgQueue->CaretInfo->hWnd;
278 break;
279 default:
280 return 0;
281 }
282 return (DWORD)(*hwnd = (HWND)Param2);
283 }
284
285 case TWOPARAM_ROUTINE_ENABLEWINDOW:
286 UNIMPLEMENTED
287 return 0;
288
289 case TWOPARAM_ROUTINE_UNKNOWN:
290 UNIMPLEMENTED
291 return 0;
292
293 case TWOPARAM_ROUTINE_SHOWOWNEDPOPUPS:
294 UNIMPLEMENTED
295 return 0;
296
297 case TWOPARAM_ROUTINE_SWITCHTOTHISWINDOW:
298 UNIMPLEMENTED
299 return 0;
300
301 case TWOPARAM_ROUTINE_VALIDATERGN:
302 return (DWORD)NtUserValidateRgn((HWND) Param1, (HRGN) Param2);
303
304 case TWOPARAM_ROUTINE_SETWNDCONTEXTHLPID:
305 WindowObject = IntGetWindowObject((HWND)Param1);
306 if(!WindowObject)
307 {
308 SetLastWin32Error(ERROR_INVALID_HANDLE);
309 return (DWORD)FALSE;
310 }
311
312 WindowObject->ContextHelpId = Param2;
313
314 IntReleaseWindowObject(WindowObject);
315 return (DWORD)TRUE;
316
317 case TWOPARAM_ROUTINE_CURSORPOSITION:
318 if(!Param1)
319 return (DWORD)FALSE;
320 Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
321 KernelMode,
322 0,
323 &WinStaObject);
324 if (!NT_SUCCESS(Status))
325 return (DWORD)FALSE;
326
327 if(Param2)
328 {
329 /* set cursor position */
330
331 Status = MmCopyFromCaller(&Pos, (PPOINT)Param1, sizeof(POINT));
332 if(!NT_SUCCESS(Status))
333 {
334 ObDereferenceObject(WinStaObject);
335 SetLastNtError(Status);
336 return FALSE;
337 }
338
339 CurInfo = &WinStaObject->SystemCursor;
340 /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
341
342 //CheckClipCursor(&Pos->x, &Pos->y, CurInfo);
343 if((Pos.x != CurInfo->x) || (Pos.y != CurInfo->y))
344 {
345 MouseMoveCursor(Pos.x, Pos.y);
346 }
347
348 }
349 else
350 {
351 /* get cursor position */
352 /* FIXME - check if process has WINSTA_READATTRIBUTES */
353 Pos.x = WinStaObject->SystemCursor.x;
354 Pos.y = WinStaObject->SystemCursor.y;
355
356 Status = MmCopyToCaller((PPOINT)Param1, &Pos, sizeof(POINT));
357 if(!NT_SUCCESS(Status))
358 {
359 ObDereferenceObject(WinStaObject);
360 SetLastNtError(Status);
361 return FALSE;
362 }
363
364 }
365
366 ObDereferenceObject(WinStaObject);
367
368 return (DWORD)TRUE;
369
370 case TWOPARAM_ROUTINE_SETCARETPOS:
371 return (DWORD)IntSetCaretPos((int)Param1, (int)Param2);
372 }
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);
376 return 0;
377 }
378
379 /*
380 * @unimplemented
381 */
382 BOOL
383 STDCALL
384 NtUserCallHwndLock(
385 HWND hWnd,
386 DWORD Routine)
387 {
388 BOOL Ret = 0;
389 PWINDOW_OBJECT Window;
390
391 Window = IntGetWindowObject(hWnd);
392 if (Window == 0)
393 {
394 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
395 return FALSE;
396 }
397
398 /* FIXME: Routine can be 0x53 - 0x5E */
399 switch (Routine)
400 {
401 case HWNDLOCK_ROUTINE_ARRANGEICONICWINDOWS:
402 /* FIXME */
403 break;
404
405 case HWNDLOCK_ROUTINE_DRAWMENUBAR:
406 /* FIXME */
407 break;
408
409 case HWNDLOCK_ROUTINE_REDRAWFRAME:
410 /* FIXME */
411 break;
412
413 case HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOW:
414 Ret = IntSetForegroundWindow(Window);
415 break;
416
417 case HWNDLOCK_ROUTINE_UPDATEWINDOW:
418 /* FIXME */
419 break;
420 }
421
422 IntReleaseWindowObject(Window);
423
424 return Ret;
425 }
426
427 HWND
428 STDCALL
429 NtUserCallHwndOpt(
430 HWND Param,
431 DWORD Routine)
432 {
433 switch (Routine)
434 {
435 case HWNDOPT_ROUTINE_SETPROGMANWINDOW:
436 /* FIXME */
437 break;
438
439 case HWNDOPT_ROUTINE_SETTASKMANWINDOW:
440 /* FIXME */
441 break;
442 }
443
444 return 0;
445 }
446
447 /*
448 * @unimplemented
449 */
450 DWORD STDCALL
451 NtUserGetThreadState(
452 DWORD Routine)
453 {
454 switch (Routine)
455 {
456 case 0:
457 return (DWORD)IntGetThreadFocusWindow();
458 }
459 return 0;
460 }
461
462 VOID FASTCALL
463 IntGetFontMetricSetting(LPWSTR lpValueName, PLOGFONTW font)
464 {
465 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
466 NTSTATUS Status;
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"
471 };
472
473 RtlZeroMemory(&QueryTable, sizeof(QueryTable));
474
475 QueryTable[0].Name = lpValueName;
476 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
477 QueryTable[0].EntryContext = font;
478
479 Status = RtlQueryRegistryValues(
480 RTL_REGISTRY_USER,
481 L"Control Panel\\Desktop\\WindowMetrics",
482 QueryTable,
483 NULL,
484 NULL);
485
486 if (!NT_SUCCESS(Status))
487 {
488 RtlCopyMemory(font, &DefaultFont, sizeof(LOGFONTW));
489 }
490 }
491
492 /*
493 * @implemented
494 */
495 DWORD
496 STDCALL
497 NtUserSystemParametersInfo(
498 UINT uiAction,
499 UINT uiParam,
500 PVOID pvParam,
501 UINT fWinIni)
502 {
503 static BOOL GradientCaptions = TRUE;
504 NTSTATUS Status;
505 PWINSTATION_OBJECT WinStaObject;
506
507 static BOOL bInitialized = FALSE;
508 static LOGFONTW IconFont;
509 static NONCLIENTMETRICSW pMetrics;
510
511 if (!bInitialized)
512 {
513 ZeroMemory(&IconFont, sizeof(LOGFONTW));
514 ZeroMemory(&pMetrics, sizeof(NONCLIENTMETRICSW));
515
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);
522
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);
533
534 bInitialized = TRUE;
535 }
536
537 switch(uiAction)
538 {
539 case SPI_SETDOUBLECLKWIDTH:
540 case SPI_SETDOUBLECLKHEIGHT:
541 case SPI_SETDOUBLECLICKTIME:
542 {
543 Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
544 KernelMode,
545 0,
546 &WinStaObject);
547 if (!NT_SUCCESS(Status))
548 return (DWORD)FALSE;
549
550 switch(uiAction)
551 {
552 case SPI_SETDOUBLECLKWIDTH:
553 /* FIXME limit the maximum value? */
554 WinStaObject->SystemCursor.DblClickWidth = uiParam;
555 break;
556 case SPI_SETDOUBLECLKHEIGHT:
557 /* FIXME limit the maximum value? */
558 WinStaObject->SystemCursor.DblClickHeight = uiParam;
559 break;
560 case SPI_SETDOUBLECLICKTIME:
561 /* FIXME limit the maximum time to 1000 ms? */
562 WinStaObject->SystemCursor.DblClickSpeed = uiParam;
563 break;
564 }
565
566 /* FIXME save the value to the registry */
567
568 ObDereferenceObject(WinStaObject);
569 return TRUE;
570 }
571 case SPI_SETWORKAREA:
572 {
573 PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
574
575 if(!Desktop)
576 {
577 /* FIXME - Set last error */
578 return FALSE;
579 }
580
581 Status = MmCopyFromCaller(Desktop->WorkArea, (PRECT)pvParam, sizeof(RECT));
582 if(!NT_SUCCESS(Status))
583 {
584 SetLastNtError(Status);
585 return FALSE;
586 }
587
588 return TRUE;
589 }
590 case SPI_GETWORKAREA:
591 {
592 PRECT Rect;
593 PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
594
595 if(!Desktop)
596 {
597 /* FIXME - Set last error */
598 return FALSE;
599 }
600
601 Rect = IntGetDesktopWorkArea(Desktop);
602
603 Status = MmCopyToCaller((PRECT)pvParam, Desktop->WorkArea, sizeof(RECT));
604 if(!NT_SUCCESS(Status))
605 {
606 SetLastNtError(Status);
607 return FALSE;
608 }
609
610 return TRUE;
611 }
612 case SPI_GETGRADIENTCAPTIONS:
613 {
614 HDC hDC;
615 PDC dc;
616 PSURFOBJ SurfObj;
617 BOOL Ret = GradientCaptions;
618
619 hDC = IntGetScreenDC();
620 if(hDC)
621 {
622 dc = DC_LockDc(hDC);
623 SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface);
624 if(SurfObj)
625 Ret = (SurfObj->iBitmapFormat > BMF_8BPP);
626 DC_UnlockDc(hDC);
627 }
628
629 Status = MmCopyToCaller(pvParam, &Ret, sizeof(BOOL));
630 if(!NT_SUCCESS(Status))
631 {
632 SetLastNtError(Status);
633 return FALSE;
634 }
635 return TRUE;
636 }
637 case SPI_SETGRADIENTCAPTIONS:
638 {
639 Status = MmCopyFromCaller(&GradientCaptions, pvParam, sizeof(BOOL));
640 if(!NT_SUCCESS(Status))
641 {
642 SetLastNtError(Status);
643 return FALSE;
644 }
645 return TRUE;
646 }
647 case SPI_SETFONTSMOOTHING:
648 {
649 BOOL Enable;
650
651 Status = MmCopyFromCaller(&Enable, pvParam, sizeof(BOOL));
652 if(!NT_SUCCESS(Status))
653 {
654 SetLastNtError(Status);
655 return FALSE;
656 }
657
658 IntEnableFontRendering(Enable);
659
660 return TRUE;
661 }
662 case SPI_GETFONTSMOOTHING:
663 {
664 BOOL Enabled = IntIsFontRenderingEnabled();
665
666 Status = MmCopyToCaller(pvParam, &Enabled, sizeof(BOOL));
667 if(!NT_SUCCESS(Status))
668 {
669 SetLastNtError(Status);
670 return FALSE;
671 }
672 return TRUE;
673 }
674 case SPI_GETICONTITLELOGFONT:
675 {
676 MmCopyToCaller(pvParam, (PVOID)&IconFont, sizeof(LOGFONTW));
677 return TRUE;
678 }
679 case SPI_GETNONCLIENTMETRICS:
680 {
681 /* FIXME: Is this windows default behavior? */
682 LPNONCLIENTMETRICSW lpMetrics = (LPNONCLIENTMETRICSW)pvParam;
683 if ( lpMetrics->cbSize != sizeof(NONCLIENTMETRICSW) ||
684 uiParam != sizeof(NONCLIENTMETRICSW ))
685 {
686 return FALSE;
687 }
688 DPRINT("FontName: %S, Size: %i\n",pMetrics.lfMessageFont.lfFaceName, pMetrics.lfMessageFont.lfHeight);
689 MmCopyToCaller(pvParam, (PVOID)&pMetrics, sizeof(NONCLIENTMETRICSW));
690 return TRUE;
691 }
692 }
693 return FALSE;
694 }
695
696 UINT
697 STDCALL
698 NtUserGetDoubleClickTime(VOID)
699 {
700 UINT Result;
701 NTSTATUS Status;
702 PWINSTATION_OBJECT WinStaObject;
703
704 Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
705 KernelMode,
706 0,
707 &WinStaObject);
708 if (!NT_SUCCESS(Status))
709 return (DWORD)FALSE;
710
711 Result = WinStaObject->SystemCursor.DblClickSpeed;
712
713 ObDereferenceObject(WinStaObject);
714 return Result;
715 }
716
717 BOOL
718 STDCALL
719 NtUserGetGUIThreadInfo(
720 DWORD idThread,
721 LPGUITHREADINFO lpgui)
722 {
723 NTSTATUS Status;
724 PTHRDCARETINFO CaretInfo;
725 GUITHREADINFO SafeGui;
726 PDESKTOP_OBJECT Desktop;
727 PUSER_MESSAGE_QUEUE MsgQueue;
728 PETHREAD Thread = NULL;
729
730 Status = MmCopyFromCaller(&SafeGui, lpgui, sizeof(DWORD));
731 if(!NT_SUCCESS(Status))
732 {
733 SetLastNtError(Status);
734 return FALSE;
735 }
736
737 if(SafeGui.cbSize != sizeof(GUITHREADINFO))
738 {
739 SetLastWin32Error(ERROR_INVALID_PARAMETER);
740 return FALSE;
741 }
742
743 if(idThread)
744 {
745 Status = PsLookupThreadByThreadId((PVOID)idThread, &Thread);
746 if(!NT_SUCCESS(Status))
747 {
748 SetLastWin32Error(ERROR_ACCESS_DENIED);
749 return FALSE;
750 }
751 Desktop = Thread->Win32Thread->Desktop;
752 }
753 else
754 {
755 /* get the foreground thread */
756 PW32THREAD W32Thread = PsGetCurrentThread()->Win32Thread;
757 Desktop = W32Thread->Desktop;
758 if(Desktop)
759 {
760 MsgQueue = Desktop->ActiveMessageQueue;
761 if(MsgQueue)
762 {
763 Thread = MsgQueue->Thread;
764 }
765 }
766 }
767
768 if(!Thread || !Desktop)
769 {
770 if(idThread && Thread)
771 ObDereferenceObject(Thread);
772 SetLastWin32Error(ERROR_ACCESS_DENIED);
773 return FALSE;
774 }
775
776 MsgQueue = (PUSER_MESSAGE_QUEUE)Desktop->ActiveMessageQueue;
777 CaretInfo = MsgQueue->CaretInfo;
778
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;
784
785 /* FIXME add flag GUI_16BITTASK */
786
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;
793
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;
798
799 if(idThread)
800 ObDereferenceObject(Thread);
801
802 Status = MmCopyToCaller(lpgui, &SafeGui, sizeof(GUITHREADINFO));
803 if(!NT_SUCCESS(Status))
804 {
805 SetLastNtError(Status);
806 return FALSE;
807 }
808
809 return TRUE;
810 }
811
812
813 DWORD
814 STDCALL
815 NtUserGetGuiResources(
816 HANDLE hProcess,
817 DWORD uiFlags)
818 {
819 PEPROCESS Process;
820 PW32PROCESS W32Process;
821 NTSTATUS Status;
822 DWORD Ret = 0;
823
824 Status = ObReferenceObjectByHandle(hProcess,
825 PROCESS_QUERY_INFORMATION,
826 PsProcessType,
827 ExGetPreviousMode(),
828 (PVOID*)&Process,
829 NULL);
830
831 if(!NT_SUCCESS(Status))
832 {
833 SetLastNtError(Status);
834 return 0;
835 }
836
837 W32Process = Process->Win32Process;
838 if(!W32Process)
839 {
840 ObDereferenceObject(Process);
841 SetLastWin32Error(ERROR_INVALID_PARAMETER);
842 return 0;
843 }
844
845 switch(uiFlags)
846 {
847 case GR_GDIOBJECTS:
848 {
849 Ret = (DWORD)W32Process->GDIObjects;
850 break;
851 }
852 case GR_USEROBJECTS:
853 {
854 Ret = (DWORD)W32Process->UserObjects;
855 break;
856 }
857 default:
858 {
859 SetLastWin32Error(ERROR_INVALID_PARAMETER);
860 break;
861 }
862 }
863
864 ObDereferenceObject(Process);
865
866 return Ret;
867 }
868
869 NTSTATUS FASTCALL
870 IntSafeCopyUnicodeString(PUNICODE_STRING Dest,
871 PUNICODE_STRING Source)
872 {
873 NTSTATUS Status;
874 PWSTR Src;
875
876 Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING));
877 if(!NT_SUCCESS(Status))
878 {
879 return Status;
880 }
881
882 if(Dest->MaximumLength > 0)
883 {
884 Src = Dest->Buffer;
885
886 Dest->Buffer = ExAllocatePoolWithTag(NonPagedPool, Dest->MaximumLength, TAG_STRING);
887 if(!Dest->Buffer)
888 {
889 return STATUS_NO_MEMORY;
890 }
891
892 Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->MaximumLength);
893 if(!NT_SUCCESS(Status))
894 {
895 ExFreePool(Dest->Buffer);
896 Dest->Buffer = NULL;
897 return Status;
898 }
899
900
901 return STATUS_SUCCESS;
902 }
903 return STATUS_UNSUCCESSFUL;
904 }
905