- Compile Win32k, GDI, USER32 and CSRSS using W32API.
[reactos.git] / reactos / subsys / win32k / ntuser / misc.c
1 /* $Id: misc.c,v 1.59 2004/04/09 20:03:19 navaraf 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_GETWINDOWINSTANCE:
173 if(!(WindowObject = IntGetWindowObject((HWND)Param)))
174 {
175 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
176 return FALSE;
177 }
178
179 Result = (DWORD)WindowObject->Instance;
180 IntReleaseWindowObject(WindowObject);
181 return Result;
182
183 case ONEPARAM_ROUTINE_SETMESSAGEEXTRAINFO:
184 return (DWORD)MsqSetMessageExtraInfo((LPARAM)Param);
185 }
186 DPRINT1("Calling invalid routine number 0x%x in NtUserCallOneParam()\n Param=0x%x\n",
187 Routine, Param);
188 SetLastWin32Error(ERROR_INVALID_PARAMETER);
189 return 0;
190 }
191
192
193 /*
194 * @implemented
195 */
196 DWORD
197 STDCALL
198 NtUserCallTwoParam(
199 DWORD Param1,
200 DWORD Param2,
201 DWORD Routine)
202 {
203 NTSTATUS Status;
204 PWINDOW_OBJECT WindowObject;
205 PSYSTEM_CURSORINFO CurInfo;
206 PWINSTATION_OBJECT WinStaObject;
207 POINT Pos;
208
209 switch(Routine)
210 {
211 case TWOPARAM_ROUTINE_GETWINDOWRGNBOX:
212 {
213 DWORD Ret;
214 RECT rcRect;
215 Ret = (DWORD)IntGetWindowRgnBox((HWND)Param1, &rcRect);
216 Status = MmCopyToCaller((PVOID)Param2, &rcRect, sizeof(RECT));
217 if(!NT_SUCCESS(Status))
218 {
219 SetLastNtError(Status);
220 return ERROR;
221 }
222 return Ret;
223 }
224 case TWOPARAM_ROUTINE_GETWINDOWRGN:
225 {
226 return (DWORD)IntGetWindowRgn((HWND)Param1, (HRGN)Param2);
227 }
228 case TWOPARAM_ROUTINE_SETMENUBARHEIGHT:
229 {
230 DWORD Ret;
231 PMENU_OBJECT MenuObject = IntGetMenuObject((HMENU)Param1);
232 if(!MenuObject)
233 return 0;
234
235 if(Param2 > 0)
236 {
237 Ret = (MenuObject->MenuInfo.Height == (int)Param2);
238 MenuObject->MenuInfo.Height = (int)Param2;
239 }
240 else
241 Ret = (DWORD)MenuObject->MenuInfo.Height;
242 IntReleaseMenuObject(MenuObject);
243 return Ret;
244 }
245 case TWOPARAM_ROUTINE_SETMENUITEMRECT:
246 {
247 BOOL Ret;
248 SETMENUITEMRECT smir;
249 PMENU_OBJECT MenuObject = IntGetMenuObject((HMENU)Param1);
250 if(!MenuObject)
251 return 0;
252
253 if(!NT_SUCCESS(MmCopyFromCaller(&smir, (PVOID)Param2, sizeof(SETMENUITEMRECT))))
254 {
255 IntReleaseMenuObject(MenuObject);
256 return 0;
257 }
258
259 Ret = IntSetMenuItemRect(MenuObject, smir.uItem, smir.fByPosition, &smir.rcRect);
260
261 IntReleaseMenuObject(MenuObject);
262 return (DWORD)Ret;
263 }
264
265 case TWOPARAM_ROUTINE_SETGUITHRDHANDLE:
266 {
267 HWND *hwnd;
268 PUSER_MESSAGE_QUEUE MsgQueue = PsGetCurrentThread()->Win32Thread->MessageQueue;
269
270 switch(Param1)
271 {
272 case TPR_SGTH_ACTIVE:
273 hwnd = &MsgQueue->ActiveWindow;
274 break;
275 case TPR_SGTH_FOCUS:
276 hwnd = &MsgQueue->FocusWindow;
277 break;
278 case TPR_SGTH_CAPTURE:
279 hwnd = &MsgQueue->CaptureWindow;
280 break;
281 case TPR_SGTH_MENUOWNER:
282 hwnd = &MsgQueue->MenuOwner;
283 break;
284 case TPR_SGTH_MOVESIZE:
285 hwnd = &MsgQueue->MoveSize;
286 break;
287 case TPR_SGTH_CARET:
288 hwnd = &MsgQueue->CaretInfo->hWnd;
289 break;
290 default:
291 return 0;
292 }
293 return (DWORD)(*hwnd = (HWND)Param2);
294 }
295
296 case TWOPARAM_ROUTINE_ENABLEWINDOW:
297 UNIMPLEMENTED
298 return 0;
299
300 case TWOPARAM_ROUTINE_UNKNOWN:
301 UNIMPLEMENTED
302 return 0;
303
304 case TWOPARAM_ROUTINE_SHOWOWNEDPOPUPS:
305 UNIMPLEMENTED
306 return 0;
307
308 case TWOPARAM_ROUTINE_SWITCHTOTHISWINDOW:
309 UNIMPLEMENTED
310 return 0;
311
312 case TWOPARAM_ROUTINE_VALIDATERGN:
313 return (DWORD)NtUserValidateRgn((HWND) Param1, (HRGN) Param2);
314
315 case TWOPARAM_ROUTINE_SETWNDCONTEXTHLPID:
316 WindowObject = IntGetWindowObject((HWND)Param1);
317 if(!WindowObject)
318 {
319 SetLastWin32Error(ERROR_INVALID_HANDLE);
320 return (DWORD)FALSE;
321 }
322
323 WindowObject->ContextHelpId = Param2;
324
325 IntReleaseWindowObject(WindowObject);
326 return (DWORD)TRUE;
327
328 case TWOPARAM_ROUTINE_CURSORPOSITION:
329 if(!Param1)
330 return (DWORD)FALSE;
331 Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
332 KernelMode,
333 0,
334 &WinStaObject);
335 if (!NT_SUCCESS(Status))
336 return (DWORD)FALSE;
337
338 if(Param2)
339 {
340 /* set cursor position */
341
342 Status = MmCopyFromCaller(&Pos, (PPOINT)Param1, sizeof(POINT));
343 if(!NT_SUCCESS(Status))
344 {
345 ObDereferenceObject(WinStaObject);
346 SetLastNtError(Status);
347 return FALSE;
348 }
349
350 CurInfo = &WinStaObject->SystemCursor;
351 /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
352
353 //CheckClipCursor(&Pos->x, &Pos->y, CurInfo);
354 if((Pos.x != CurInfo->x) || (Pos.y != CurInfo->y))
355 {
356 MouseMoveCursor(Pos.x, Pos.y);
357 }
358
359 }
360 else
361 {
362 /* get cursor position */
363 /* FIXME - check if process has WINSTA_READATTRIBUTES */
364 Pos.x = WinStaObject->SystemCursor.x;
365 Pos.y = WinStaObject->SystemCursor.y;
366
367 Status = MmCopyToCaller((PPOINT)Param1, &Pos, sizeof(POINT));
368 if(!NT_SUCCESS(Status))
369 {
370 ObDereferenceObject(WinStaObject);
371 SetLastNtError(Status);
372 return FALSE;
373 }
374
375 }
376
377 ObDereferenceObject(WinStaObject);
378
379 return (DWORD)TRUE;
380
381 case TWOPARAM_ROUTINE_SETCARETPOS:
382 return (DWORD)IntSetCaretPos((int)Param1, (int)Param2);
383
384 case TWOPARAM_ROUTINE_GETWINDOWINFO:
385 {
386 WINDOWINFO wi;
387 DWORD Ret;
388
389 if(!(WindowObject = IntGetWindowObject((HWND)Param1)))
390 {
391 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
392 return FALSE;
393 }
394
395 Status = MmCopyFromCaller(&wi.cbSize, (PVOID)Param2, sizeof(wi.cbSize));
396 if(!NT_SUCCESS(Status))
397 {
398 IntReleaseWindowObject(WindowObject);
399 SetLastNtError(Status);
400 return FALSE;
401 }
402
403 if(wi.cbSize != sizeof(WINDOWINFO))
404 {
405 IntReleaseWindowObject(WindowObject);
406 SetLastWin32Error(ERROR_INVALID_PARAMETER);
407 return FALSE;
408 }
409
410 if((Ret = (DWORD)IntGetWindowInfo(WindowObject, &wi)))
411 {
412 Status = MmCopyToCaller((PVOID)Param2, &wi, sizeof(WINDOWINFO));
413 if(!NT_SUCCESS(Status))
414 {
415 IntReleaseWindowObject(WindowObject);
416 SetLastNtError(Status);
417 return FALSE;
418 }
419 }
420
421 IntReleaseWindowObject(WindowObject);
422 return Ret;
423 }
424 }
425 DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam()\n Param1=0x%x Parm2=0x%x\n",
426 Routine, Param1, Param2);
427 SetLastWin32Error(ERROR_INVALID_PARAMETER);
428 return 0;
429 }
430
431 /*
432 * @unimplemented
433 */
434 BOOL
435 STDCALL
436 NtUserCallHwndLock(
437 HWND hWnd,
438 DWORD Routine)
439 {
440 BOOL Ret = 0;
441 PWINDOW_OBJECT Window;
442
443 Window = IntGetWindowObject(hWnd);
444 if (Window == 0)
445 {
446 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
447 return FALSE;
448 }
449
450 /* FIXME: Routine can be 0x53 - 0x5E */
451 switch (Routine)
452 {
453 case HWNDLOCK_ROUTINE_ARRANGEICONICWINDOWS:
454 /* FIXME */
455 break;
456
457 case HWNDLOCK_ROUTINE_DRAWMENUBAR:
458 /* FIXME */
459 break;
460
461 case HWNDLOCK_ROUTINE_REDRAWFRAME:
462 /* FIXME */
463 break;
464
465 case HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOW:
466 Ret = IntSetForegroundWindow(Window);
467 break;
468
469 case HWNDLOCK_ROUTINE_UPDATEWINDOW:
470 /* FIXME */
471 break;
472 }
473
474 IntReleaseWindowObject(Window);
475
476 return Ret;
477 }
478
479 HWND
480 STDCALL
481 NtUserCallHwndOpt(
482 HWND Param,
483 DWORD Routine)
484 {
485 switch (Routine)
486 {
487 case HWNDOPT_ROUTINE_SETPROGMANWINDOW:
488 /* FIXME */
489 break;
490
491 case HWNDOPT_ROUTINE_SETTASKMANWINDOW:
492 /* FIXME */
493 break;
494 }
495
496 return 0;
497 }
498
499 /*
500 * @unimplemented
501 */
502 DWORD STDCALL
503 NtUserGetThreadState(
504 DWORD Routine)
505 {
506 switch (Routine)
507 {
508 case 0:
509 return (DWORD)IntGetThreadFocusWindow();
510 }
511 return 0;
512 }
513
514 VOID FASTCALL
515 IntGetFontMetricSetting(LPWSTR lpValueName, PLOGFONTW font)
516 {
517 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
518 NTSTATUS Status;
519 static LOGFONTW DefaultFont = {
520 11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
521 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
522 L"Bitstream Vera Sans"
523 };
524
525 RtlZeroMemory(&QueryTable, sizeof(QueryTable));
526
527 QueryTable[0].Name = lpValueName;
528 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
529 QueryTable[0].EntryContext = font;
530
531 Status = RtlQueryRegistryValues(
532 RTL_REGISTRY_USER,
533 L"Control Panel\\Desktop\\WindowMetrics",
534 QueryTable,
535 NULL,
536 NULL);
537
538 if (!NT_SUCCESS(Status))
539 {
540 RtlCopyMemory(font, &DefaultFont, sizeof(LOGFONTW));
541 }
542 }
543
544 /*
545 * @implemented
546 */
547 DWORD
548 STDCALL
549 NtUserSystemParametersInfo(
550 UINT uiAction,
551 UINT uiParam,
552 PVOID pvParam,
553 UINT fWinIni)
554 {
555 static BOOL GradientCaptions = TRUE;
556 NTSTATUS Status;
557 PWINSTATION_OBJECT WinStaObject;
558
559 static BOOL bInitialized = FALSE;
560 static LOGFONTW IconFont;
561 static NONCLIENTMETRICSW pMetrics;
562
563 if (!bInitialized)
564 {
565 ZeroMemory(&IconFont, sizeof(LOGFONTW));
566 ZeroMemory(&pMetrics, sizeof(NONCLIENTMETRICSW));
567
568 IntGetFontMetricSetting(L"CaptionFont", &pMetrics.lfCaptionFont);
569 IntGetFontMetricSetting(L"SmCaptionFont", &pMetrics.lfSmCaptionFont);
570 IntGetFontMetricSetting(L"MenuFont", &pMetrics.lfMenuFont);
571 IntGetFontMetricSetting(L"StatusFont", &pMetrics.lfStatusFont);
572 IntGetFontMetricSetting(L"MessageFont", &pMetrics.lfMessageFont);
573 IntGetFontMetricSetting(L"IconFont", &IconFont);
574
575 pMetrics.iBorderWidth = 1;
576 pMetrics.iScrollWidth = NtUserGetSystemMetrics(SM_CXVSCROLL);
577 pMetrics.iScrollHeight = NtUserGetSystemMetrics(SM_CYHSCROLL);
578 pMetrics.iCaptionWidth = NtUserGetSystemMetrics(SM_CXSIZE);
579 pMetrics.iCaptionHeight = NtUserGetSystemMetrics(SM_CYSIZE);
580 pMetrics.iSmCaptionWidth = NtUserGetSystemMetrics(SM_CXSMSIZE);
581 pMetrics.iSmCaptionHeight = NtUserGetSystemMetrics(SM_CYSMSIZE);
582 pMetrics.iMenuWidth = NtUserGetSystemMetrics(SM_CXMENUSIZE);
583 pMetrics.iMenuHeight = NtUserGetSystemMetrics(SM_CYMENUSIZE);
584 pMetrics.cbSize = sizeof(LPNONCLIENTMETRICSW);
585
586 bInitialized = TRUE;
587 }
588
589 switch(uiAction)
590 {
591 case SPI_SETDOUBLECLKWIDTH:
592 case SPI_SETDOUBLECLKHEIGHT:
593 case SPI_SETDOUBLECLICKTIME:
594 {
595 Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
596 KernelMode,
597 0,
598 &WinStaObject);
599 if (!NT_SUCCESS(Status))
600 return (DWORD)FALSE;
601
602 switch(uiAction)
603 {
604 case SPI_SETDOUBLECLKWIDTH:
605 /* FIXME limit the maximum value? */
606 WinStaObject->SystemCursor.DblClickWidth = uiParam;
607 break;
608 case SPI_SETDOUBLECLKHEIGHT:
609 /* FIXME limit the maximum value? */
610 WinStaObject->SystemCursor.DblClickHeight = uiParam;
611 break;
612 case SPI_SETDOUBLECLICKTIME:
613 /* FIXME limit the maximum time to 1000 ms? */
614 WinStaObject->SystemCursor.DblClickSpeed = uiParam;
615 break;
616 }
617
618 /* FIXME save the value to the registry */
619
620 ObDereferenceObject(WinStaObject);
621 return TRUE;
622 }
623 case SPI_SETWORKAREA:
624 {
625 PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
626
627 if(!Desktop)
628 {
629 /* FIXME - Set last error */
630 return FALSE;
631 }
632
633 Status = MmCopyFromCaller(Desktop->WorkArea, (PRECT)pvParam, sizeof(RECT));
634 if(!NT_SUCCESS(Status))
635 {
636 SetLastNtError(Status);
637 return FALSE;
638 }
639
640 return TRUE;
641 }
642 case SPI_GETWORKAREA:
643 {
644 PRECT Rect;
645 PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
646
647 if(!Desktop)
648 {
649 /* FIXME - Set last error */
650 return FALSE;
651 }
652
653 Rect = IntGetDesktopWorkArea(Desktop);
654
655 Status = MmCopyToCaller((PRECT)pvParam, Desktop->WorkArea, sizeof(RECT));
656 if(!NT_SUCCESS(Status))
657 {
658 SetLastNtError(Status);
659 return FALSE;
660 }
661
662 return TRUE;
663 }
664 case SPI_GETGRADIENTCAPTIONS:
665 {
666 HDC hDC;
667 PDC dc;
668 SURFOBJ *SurfObj;
669 BOOL Ret = GradientCaptions;
670
671 hDC = IntGetScreenDC();
672 if(hDC)
673 {
674 dc = DC_LockDc(hDC);
675 SurfObj = (SURFOBJ*)AccessUserObject((ULONG) dc->Surface);
676 if(SurfObj)
677 Ret = (SurfObj->iBitmapFormat > BMF_8BPP);
678 DC_UnlockDc(hDC);
679 }
680
681 Status = MmCopyToCaller(pvParam, &Ret, sizeof(BOOL));
682 if(!NT_SUCCESS(Status))
683 {
684 SetLastNtError(Status);
685 return FALSE;
686 }
687 return TRUE;
688 }
689 case SPI_SETGRADIENTCAPTIONS:
690 {
691 Status = MmCopyFromCaller(&GradientCaptions, pvParam, sizeof(BOOL));
692 if(!NT_SUCCESS(Status))
693 {
694 SetLastNtError(Status);
695 return FALSE;
696 }
697 return TRUE;
698 }
699 case SPI_SETFONTSMOOTHING:
700 {
701 BOOL Enable;
702
703 Status = MmCopyFromCaller(&Enable, pvParam, sizeof(BOOL));
704 if(!NT_SUCCESS(Status))
705 {
706 SetLastNtError(Status);
707 return FALSE;
708 }
709
710 IntEnableFontRendering(Enable);
711
712 return TRUE;
713 }
714 case SPI_GETFONTSMOOTHING:
715 {
716 BOOL Enabled = IntIsFontRenderingEnabled();
717
718 Status = MmCopyToCaller(pvParam, &Enabled, sizeof(BOOL));
719 if(!NT_SUCCESS(Status))
720 {
721 SetLastNtError(Status);
722 return FALSE;
723 }
724 return TRUE;
725 }
726 case SPI_GETICONTITLELOGFONT:
727 {
728 MmCopyToCaller(pvParam, (PVOID)&IconFont, sizeof(LOGFONTW));
729 return TRUE;
730 }
731 case SPI_GETNONCLIENTMETRICS:
732 {
733 /* FIXME: Is this windows default behavior? */
734 LPNONCLIENTMETRICSW lpMetrics = (LPNONCLIENTMETRICSW)pvParam;
735 if ( lpMetrics->cbSize != sizeof(NONCLIENTMETRICSW) ||
736 uiParam != sizeof(NONCLIENTMETRICSW ))
737 {
738 return FALSE;
739 }
740 DPRINT("FontName: %S, Size: %i\n",pMetrics.lfMessageFont.lfFaceName, pMetrics.lfMessageFont.lfHeight);
741 MmCopyToCaller(pvParam, (PVOID)&pMetrics, sizeof(NONCLIENTMETRICSW));
742 return TRUE;
743 }
744 }
745 return FALSE;
746 }
747
748 UINT
749 STDCALL
750 NtUserGetDoubleClickTime(VOID)
751 {
752 UINT Result;
753 NTSTATUS Status;
754 PWINSTATION_OBJECT WinStaObject;
755
756 Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
757 KernelMode,
758 0,
759 &WinStaObject);
760 if (!NT_SUCCESS(Status))
761 return (DWORD)FALSE;
762
763 Result = WinStaObject->SystemCursor.DblClickSpeed;
764
765 ObDereferenceObject(WinStaObject);
766 return Result;
767 }
768
769 BOOL
770 STDCALL
771 NtUserGetGUIThreadInfo(
772 DWORD idThread,
773 LPGUITHREADINFO lpgui)
774 {
775 NTSTATUS Status;
776 PTHRDCARETINFO CaretInfo;
777 GUITHREADINFO SafeGui;
778 PDESKTOP_OBJECT Desktop;
779 PUSER_MESSAGE_QUEUE MsgQueue;
780 PETHREAD Thread = NULL;
781
782 Status = MmCopyFromCaller(&SafeGui, lpgui, sizeof(DWORD));
783 if(!NT_SUCCESS(Status))
784 {
785 SetLastNtError(Status);
786 return FALSE;
787 }
788
789 if(SafeGui.cbSize != sizeof(GUITHREADINFO))
790 {
791 SetLastWin32Error(ERROR_INVALID_PARAMETER);
792 return FALSE;
793 }
794
795 if(idThread)
796 {
797 Status = PsLookupThreadByThreadId((PVOID)idThread, &Thread);
798 if(!NT_SUCCESS(Status))
799 {
800 SetLastWin32Error(ERROR_ACCESS_DENIED);
801 return FALSE;
802 }
803 Desktop = Thread->Win32Thread->Desktop;
804 }
805 else
806 {
807 /* get the foreground thread */
808 PW32THREAD W32Thread = PsGetCurrentThread()->Win32Thread;
809 Desktop = W32Thread->Desktop;
810 if(Desktop)
811 {
812 MsgQueue = Desktop->ActiveMessageQueue;
813 if(MsgQueue)
814 {
815 Thread = MsgQueue->Thread;
816 }
817 }
818 }
819
820 if(!Thread || !Desktop)
821 {
822 if(idThread && Thread)
823 ObDereferenceObject(Thread);
824 SetLastWin32Error(ERROR_ACCESS_DENIED);
825 return FALSE;
826 }
827
828 MsgQueue = (PUSER_MESSAGE_QUEUE)Desktop->ActiveMessageQueue;
829 CaretInfo = MsgQueue->CaretInfo;
830
831 SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0);
832 if(MsgQueue->MenuOwner)
833 SafeGui.flags |= GUI_INMENUMODE | MsgQueue->MenuState;
834 if(MsgQueue->MoveSize)
835 SafeGui.flags |= GUI_INMOVESIZE;
836
837 /* FIXME add flag GUI_16BITTASK */
838
839 SafeGui.hwndActive = MsgQueue->ActiveWindow;
840 SafeGui.hwndFocus = MsgQueue->FocusWindow;
841 SafeGui.hwndCapture = MsgQueue->CaptureWindow;
842 SafeGui.hwndMenuOwner = MsgQueue->MenuOwner;
843 SafeGui.hwndMoveSize = MsgQueue->MoveSize;
844 SafeGui.hwndCaret = CaretInfo->hWnd;
845
846 SafeGui.rcCaret.left = CaretInfo->Pos.x;
847 SafeGui.rcCaret.top = CaretInfo->Pos.y;
848 SafeGui.rcCaret.right = SafeGui.rcCaret.left + CaretInfo->Size.cx;
849 SafeGui.rcCaret.bottom = SafeGui.rcCaret.top + CaretInfo->Size.cy;
850
851 if(idThread)
852 ObDereferenceObject(Thread);
853
854 Status = MmCopyToCaller(lpgui, &SafeGui, sizeof(GUITHREADINFO));
855 if(!NT_SUCCESS(Status))
856 {
857 SetLastNtError(Status);
858 return FALSE;
859 }
860
861 return TRUE;
862 }
863
864
865 DWORD
866 STDCALL
867 NtUserGetGuiResources(
868 HANDLE hProcess,
869 DWORD uiFlags)
870 {
871 PEPROCESS Process;
872 PW32PROCESS W32Process;
873 NTSTATUS Status;
874 DWORD Ret = 0;
875
876 Status = ObReferenceObjectByHandle(hProcess,
877 PROCESS_QUERY_INFORMATION,
878 PsProcessType,
879 ExGetPreviousMode(),
880 (PVOID*)&Process,
881 NULL);
882
883 if(!NT_SUCCESS(Status))
884 {
885 SetLastNtError(Status);
886 return 0;
887 }
888
889 W32Process = Process->Win32Process;
890 if(!W32Process)
891 {
892 ObDereferenceObject(Process);
893 SetLastWin32Error(ERROR_INVALID_PARAMETER);
894 return 0;
895 }
896
897 switch(uiFlags)
898 {
899 case GR_GDIOBJECTS:
900 {
901 Ret = (DWORD)W32Process->GDIObjects;
902 break;
903 }
904 case GR_USEROBJECTS:
905 {
906 Ret = (DWORD)W32Process->UserObjects;
907 break;
908 }
909 default:
910 {
911 SetLastWin32Error(ERROR_INVALID_PARAMETER);
912 break;
913 }
914 }
915
916 ObDereferenceObject(Process);
917
918 return Ret;
919 }
920
921 NTSTATUS FASTCALL
922 IntSafeCopyUnicodeString(PUNICODE_STRING Dest,
923 PUNICODE_STRING Source)
924 {
925 NTSTATUS Status;
926 PWSTR Src;
927
928 Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING));
929 if(!NT_SUCCESS(Status))
930 {
931 return Status;
932 }
933
934 if(Dest->MaximumLength > 0)
935 {
936 Src = Dest->Buffer;
937
938 Dest->Buffer = ExAllocatePoolWithTag(NonPagedPool, Dest->MaximumLength, TAG_STRING);
939 if(!Dest->Buffer)
940 {
941 return STATUS_NO_MEMORY;
942 }
943
944 Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->MaximumLength);
945 if(!NT_SUCCESS(Status))
946 {
947 ExFreePool(Dest->Buffer);
948 Dest->Buffer = NULL;
949 return Status;
950 }
951
952
953 return STATUS_SUCCESS;
954 }
955 return STATUS_UNSUCCESSFUL;
956 }
957