implement SPI_SETNONCLIENTMETRICS in IntSystemParametersInfo and UserSystemParametersInfo
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / misc.c
1 /* $Id$
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
12 #include <w32k.h>
13
14 #define NDEBUG
15 #include <debug.h>
16
17 /* registered Logon process */
18 PW32PROCESS LogonProcess = NULL;
19
20 BOOL FASTCALL
21 co_IntRegisterLogonProcess(HANDLE ProcessId, BOOL Register)
22 {
23 PEPROCESS Process;
24 NTSTATUS Status;
25 CSR_API_MESSAGE Request;
26
27 Status = PsLookupProcessByProcessId(ProcessId,
28 &Process);
29 if (!NT_SUCCESS(Status))
30 {
31 SetLastWin32Error(RtlNtStatusToDosError(Status));
32 return FALSE;
33 }
34
35 if (Register)
36 {
37 /* Register the logon process */
38 if (LogonProcess != NULL)
39 {
40 ObDereferenceObject(Process);
41 return FALSE;
42 }
43
44 LogonProcess = (PW32PROCESS)Process->Win32Process;
45 }
46 else
47 {
48 /* Deregister the logon process */
49 if (LogonProcess != (PW32PROCESS)Process->Win32Process)
50 {
51 ObDereferenceObject(Process);
52 return FALSE;
53 }
54
55 LogonProcess = NULL;
56 }
57
58 ObDereferenceObject(Process);
59
60 Request.Type = MAKE_CSR_API(REGISTER_LOGON_PROCESS, CSR_GUI);
61 Request.Data.RegisterLogonProcessRequest.ProcessId = ProcessId;
62 Request.Data.RegisterLogonProcessRequest.Register = Register;
63
64 Status = co_CsrNotify(&Request);
65 if (! NT_SUCCESS(Status))
66 {
67 DPRINT1("Failed to register logon process with CSRSS\n");
68 return FALSE;
69 }
70
71 return TRUE;
72 }
73
74 /*
75 * @unimplemented
76 */
77 DWORD
78 STDCALL
79 NtUserCallNoParam(DWORD Routine)
80 {
81 DWORD Result = 0;
82 DECLARE_RETURN(DWORD);
83
84 DPRINT("Enter NtUserCallNoParam\n");
85 UserEnterExclusive();
86
87 switch(Routine)
88 {
89 case NOPARAM_ROUTINE_DESTROY_CARET:
90 Result = (DWORD)co_IntDestroyCaret(PsGetCurrentThread()->Tcb.Win32Thread);
91 break;
92
93 case NOPARAM_ROUTINE_INIT_MESSAGE_PUMP:
94 Result = (DWORD)IntInitMessagePumpHook();
95 break;
96
97 case NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP:
98 Result = (DWORD)IntUninitMessagePumpHook();
99 break;
100
101 case NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO:
102 Result = (DWORD)MsqGetMessageExtraInfo();
103 break;
104
105 case NOPARAM_ROUTINE_ANYPOPUP:
106 Result = (DWORD)IntAnyPopup();
107 break;
108
109 case NOPARAM_ROUTINE_CSRSS_INITIALIZED:
110 Result = (DWORD)CsrInit();
111 break;
112
113 case NOPARAM_ROUTINE_MSQCLEARWAKEMASK:
114 RETURN( (DWORD)IntMsqClearWakeMask());
115
116 default:
117 DPRINT1("Calling invalid routine number 0x%x in NtUserCallNoParam\n", Routine);
118 SetLastWin32Error(ERROR_INVALID_PARAMETER);
119 break;
120 }
121 RETURN(Result);
122
123 CLEANUP:
124 DPRINT("Leave NtUserCallNoParam, ret=%i\n",_ret_);
125 UserLeave();
126 END_CLEANUP;
127 }
128
129
130 /*
131 * @implemented
132 */
133 DWORD
134 STDCALL
135 NtUserCallOneParam(
136 DWORD Param,
137 DWORD Routine)
138 {
139 DECLARE_RETURN(DWORD);
140 PDC dc;
141
142 DPRINT("Enter NtUserCallOneParam\n");
143
144
145 if (Routine == ONEPARAM_ROUTINE_SHOWCURSOR)
146 {
147 PWINSTATION_OBJECT WinSta = PsGetCurrentThreadWin32Thread()->Desktop->WindowStation;
148 PSYSTEM_CURSORINFO CurInfo;
149
150 HDC Screen;
151 HBITMAP dcbmp;
152 SURFOBJ *SurfObj;
153 BITMAPOBJ *BitmapObj;
154 GDIDEVICE *ppdev;
155 GDIPOINTER *pgp;
156 int showpointer=0;
157
158 if(!(Screen = IntGetScreenDC()))
159 {
160 return showpointer; /* No mouse */
161 }
162
163 dc = DC_LockDc(Screen);
164
165 if (!dc)
166 {
167 return showpointer; /* No mouse */
168 }
169
170 dcbmp = dc->w.hBitmap;
171 DC_UnlockDc(dc);
172
173 BitmapObj = BITMAPOBJ_LockBitmap(dcbmp);
174 if ( !BitmapObj )
175 {
176 BITMAPOBJ_UnlockBitmap(BitmapObj);
177 return showpointer; /* No Mouse */
178 }
179
180 SurfObj = &BitmapObj->SurfObj;
181 if (SurfObj == NULL)
182 {
183 BITMAPOBJ_UnlockBitmap(BitmapObj);
184 return showpointer; /* No mouse */
185 }
186
187 ppdev = GDIDEV(SurfObj);
188
189 if(ppdev == NULL)
190 {
191 BITMAPOBJ_UnlockBitmap(BitmapObj);
192 return showpointer; /* No mouse */
193 }
194
195 pgp = &ppdev->Pointer;
196
197 CurInfo = IntGetSysCursorInfo(WinSta);
198
199 if (Param == FALSE)
200 {
201 pgp->ShowPointer--;
202 showpointer = pgp->ShowPointer;
203
204 if (showpointer >= 0)
205 {
206 //ppdev->SafetyRemoveCount = 1;
207 //ppdev->SafetyRemoveLevel = 1;
208 EngMovePointer(SurfObj,-1,-1,NULL);
209 CurInfo->ShowingCursor = 0;
210 }
211
212 }
213 else
214 {
215 pgp->ShowPointer++;
216 showpointer = pgp->ShowPointer;
217
218 /* Show Cursor */
219 if (showpointer < 0)
220 {
221 //ppdev->SafetyRemoveCount = 0;
222 //ppdev->SafetyRemoveLevel = 0;
223 EngMovePointer(SurfObj,-1,-1,NULL);
224 CurInfo->ShowingCursor = CURSOR_SHOWING;
225 }
226 }
227
228 BITMAPOBJ_UnlockBitmap(BitmapObj);
229 return showpointer;
230 }
231
232
233 UserEnterExclusive();
234
235 switch(Routine)
236 {
237 case ONEPARAM_ROUTINE_GETMENU:
238 {
239 PWINDOW_OBJECT Window;
240 DWORD Result;
241
242 if(!(Window = UserGetWindowObject((HWND)Param)))
243 {
244 RETURN( FALSE);
245 }
246
247 Result = (DWORD)Window->IDMenu;
248
249 RETURN( Result);
250 }
251
252 case ONEPARAM_ROUTINE_ISWINDOWUNICODE:
253 {
254 PWINDOW_OBJECT Window;
255 DWORD Result;
256
257 Window = UserGetWindowObject((HWND)Param);
258 if(!Window)
259 {
260 RETURN( FALSE);
261 }
262 Result = Window->Unicode;
263 RETURN( Result);
264 }
265
266 case ONEPARAM_ROUTINE_WINDOWFROMDC:
267 RETURN( (DWORD)IntWindowFromDC((HDC)Param));
268
269 case ONEPARAM_ROUTINE_GETWNDCONTEXTHLPID:
270 {
271 PWINDOW_OBJECT Window;
272 DWORD Result;
273
274 Window = UserGetWindowObject((HWND)Param);
275 if(!Window)
276 {
277 RETURN( FALSE);
278 }
279
280 Result = Window->ContextHelpId;
281
282 RETURN( Result);
283 }
284
285 case ONEPARAM_ROUTINE_SWAPMOUSEBUTTON:
286 {
287 PWINSTATION_OBJECT WinSta;
288 NTSTATUS Status;
289 DWORD Result;
290
291 Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
292 KernelMode,
293 0,
294 &WinSta);
295 if (!NT_SUCCESS(Status))
296 RETURN( (DWORD)FALSE);
297
298 /* FIXME
299 Result = (DWORD)IntSwapMouseButton(WinStaObject, (BOOL)Param); */
300 Result = 0;
301
302 ObDereferenceObject(WinSta);
303 RETURN( Result);
304 }
305
306 case ONEPARAM_ROUTINE_SWITCHCARETSHOWING:
307 RETURN( (DWORD)IntSwitchCaretShowing((PVOID)Param));
308
309 case ONEPARAM_ROUTINE_SETCARETBLINKTIME:
310 RETURN( (DWORD)IntSetCaretBlinkTime((UINT)Param));
311
312 case ONEPARAM_ROUTINE_ENUMCLIPBOARDFORMATS:
313 RETURN( (DWORD)IntEnumClipboardFormats((UINT)Param));
314
315 case ONEPARAM_ROUTINE_GETWINDOWINSTANCE:
316 {
317 PWINDOW_OBJECT Window;
318 DWORD Result;
319
320 if(!(Window = UserGetWindowObject((HWND)Param)))
321 {
322 RETURN( FALSE);
323 }
324
325 Result = (DWORD)Window->Instance;
326 RETURN( Result);
327 }
328
329 case ONEPARAM_ROUTINE_SETMESSAGEEXTRAINFO:
330 RETURN( (DWORD)MsqSetMessageExtraInfo((LPARAM)Param));
331
332 case ONEPARAM_ROUTINE_GETCURSORPOSITION:
333 {
334 PWINSTATION_OBJECT WinSta;
335 NTSTATUS Status;
336 POINT Pos;
337
338 if(!Param)
339 RETURN( (DWORD)FALSE);
340 Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
341 KernelMode,
342 0,
343 &WinSta);
344 if (!NT_SUCCESS(Status))
345 RETURN( (DWORD)FALSE);
346
347 /* FIXME - check if process has WINSTA_READATTRIBUTES */
348 IntGetCursorLocation(WinSta, &Pos);
349
350 Status = MmCopyToCaller((PPOINT)Param, &Pos, sizeof(POINT));
351 if(!NT_SUCCESS(Status))
352 {
353 ObDereferenceObject(WinSta);
354 SetLastNtError(Status);
355 RETURN( FALSE);
356 }
357
358 ObDereferenceObject(WinSta);
359
360 RETURN( (DWORD)TRUE);
361 }
362
363 case ONEPARAM_ROUTINE_ISWINDOWINDESTROY:
364 {
365 PWINDOW_OBJECT Window;
366 DWORD Result;
367
368 if(!(Window = UserGetWindowObject((HWND)Param)))
369 {
370 RETURN( FALSE);
371 }
372
373 Result = (DWORD)IntIsWindowInDestroy(Window);
374
375 RETURN( Result);
376 }
377
378 case ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING:
379 {
380 BOOL Enable;
381 PW32PROCESS Process = PsGetCurrentProcessWin32Process();
382
383 if(Process != NULL)
384 {
385 Enable = (BOOL)(Param != 0);
386
387 if(Enable)
388 {
389 Process->Flags &= ~W32PF_NOWINDOWGHOSTING;
390 }
391 else
392 {
393 Process->Flags |= W32PF_NOWINDOWGHOSTING;
394 }
395
396 RETURN( TRUE);
397 }
398
399 RETURN( FALSE);
400 }
401
402 case ONEPARAM_ROUTINE_MSQSETWAKEMASK:
403 RETURN( (DWORD)IntMsqSetWakeMask(Param));
404
405 case ONEPARAM_ROUTINE_GETKEYBOARDTYPE:
406 RETURN( UserGetKeyboardType(Param));
407
408 case ONEPARAM_ROUTINE_GETKEYBOARDLAYOUT:
409 RETURN( (DWORD)UserGetKeyboardLayout(Param));
410 }
411 DPRINT1("Calling invalid routine number 0x%x in NtUserCallOneParam(), Param=0x%x\n",
412 Routine, Param);
413 SetLastWin32Error(ERROR_INVALID_PARAMETER);
414 RETURN( 0);
415
416 CLEANUP:
417 DPRINT("Leave NtUserCallOneParam, ret=%i\n",_ret_);
418 UserLeave();
419 END_CLEANUP;
420 }
421
422
423 /*
424 * @implemented
425 */
426 DWORD
427 STDCALL
428 NtUserCallTwoParam(
429 DWORD Param1,
430 DWORD Param2,
431 DWORD Routine)
432 {
433 NTSTATUS Status;
434 PWINDOW_OBJECT Window;
435 DECLARE_RETURN(DWORD);
436
437 DPRINT("Enter NtUserCallTwoParam\n");
438 UserEnterExclusive();
439
440 switch(Routine)
441 {
442 case TWOPARAM_ROUTINE_SETDCPENCOLOR:
443 {
444 RETURN( (DWORD)IntSetDCColor((HDC)Param1, OBJ_PEN, (COLORREF)Param2));
445 }
446 case TWOPARAM_ROUTINE_SETDCBRUSHCOLOR:
447 {
448 RETURN( (DWORD)IntSetDCColor((HDC)Param1, OBJ_BRUSH, (COLORREF)Param2));
449 }
450 case TWOPARAM_ROUTINE_GETDCCOLOR:
451 {
452 RETURN( (DWORD)IntGetDCColor((HDC)Param1, (ULONG)Param2));
453 }
454 case TWOPARAM_ROUTINE_GETWINDOWRGNBOX:
455 {
456 DWORD Ret;
457 RECT rcRect;
458 Window = UserGetWindowObject((HWND)Param1);
459 if (!Window) RETURN(ERROR);
460
461 Ret = (DWORD)IntGetWindowRgnBox(Window, &rcRect);
462 Status = MmCopyToCaller((PVOID)Param2, &rcRect, sizeof(RECT));
463 if(!NT_SUCCESS(Status))
464 {
465 SetLastNtError(Status);
466 RETURN( ERROR);
467 }
468 RETURN( Ret);
469 }
470 case TWOPARAM_ROUTINE_GETWINDOWRGN:
471 {
472 Window = UserGetWindowObject((HWND)Param1);
473 if (!Window) RETURN(ERROR);
474
475 RETURN( (DWORD)IntGetWindowRgn(Window, (HRGN)Param2));
476 }
477 case TWOPARAM_ROUTINE_SETMENUBARHEIGHT:
478 {
479 DWORD Ret;
480 PMENU_OBJECT MenuObject = IntGetMenuObject((HMENU)Param1);
481 if(!MenuObject)
482 RETURN( 0);
483
484 if(Param2 > 0)
485 {
486 Ret = (MenuObject->MenuInfo.Height == (int)Param2);
487 MenuObject->MenuInfo.Height = (int)Param2;
488 }
489 else
490 Ret = (DWORD)MenuObject->MenuInfo.Height;
491 IntReleaseMenuObject(MenuObject);
492 RETURN( Ret);
493 }
494 case TWOPARAM_ROUTINE_SETMENUITEMRECT:
495 {
496 BOOL Ret;
497 SETMENUITEMRECT smir;
498 PMENU_OBJECT MenuObject = IntGetMenuObject((HMENU)Param1);
499 if(!MenuObject)
500 RETURN( 0);
501
502 if(!NT_SUCCESS(MmCopyFromCaller(&smir, (PVOID)Param2, sizeof(SETMENUITEMRECT))))
503 {
504 IntReleaseMenuObject(MenuObject);
505 RETURN( 0);
506 }
507
508 Ret = IntSetMenuItemRect(MenuObject, smir.uItem, smir.fByPosition, &smir.rcRect);
509
510 IntReleaseMenuObject(MenuObject);
511 RETURN( (DWORD)Ret);
512 }
513
514 case TWOPARAM_ROUTINE_SETGUITHRDHANDLE:
515 {
516 PUSER_MESSAGE_QUEUE MsgQueue = ((PW32THREAD)PsGetCurrentThread()->Tcb.Win32Thread)->MessageQueue;
517
518 ASSERT(MsgQueue);
519 RETURN( (DWORD)MsqSetStateWindow(MsgQueue, (ULONG)Param1, (HWND)Param2));
520 }
521
522 case TWOPARAM_ROUTINE_ENABLEWINDOW:
523 UNIMPLEMENTED
524 RETURN( 0);
525
526 case TWOPARAM_ROUTINE_UNKNOWN:
527 UNIMPLEMENTED
528 RETURN( 0);
529
530 case TWOPARAM_ROUTINE_SHOWOWNEDPOPUPS:
531 {
532 Window = UserGetWindowObject((HWND)Param1);
533 if (!Window) RETURN(0);
534
535 RETURN( (DWORD)IntShowOwnedPopups(Window, (BOOL) Param2));
536 }
537
538 case TWOPARAM_ROUTINE_ROS_SHOWWINDOW:
539 {
540 #define WIN_NEEDS_SHOW_OWNEDPOPUP (0x00000040)
541 DPRINT1("ROS_SHOWWINDOW\n");
542
543 if (!(Window = UserGetWindowObject((HWND)Param1)))
544 {
545 RETURN( 1 );
546 }
547
548 if (Param2)
549 {
550 if (!(Window->Flags & WIN_NEEDS_SHOW_OWNEDPOPUP))
551 {
552 RETURN( -1 );
553 }
554 Window->Flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
555 }
556 else
557 Window->Flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
558
559 DPRINT1("ROS_SHOWWINDOW ---> 0x%x\n",Window->Flags);
560 RETURN( 0 );
561 }
562
563 case TWOPARAM_ROUTINE_SWITCHTOTHISWINDOW:
564 UNIMPLEMENTED
565 RETURN( 0);
566
567 case TWOPARAM_ROUTINE_SETWNDCONTEXTHLPID:
568
569 if(!(Window = UserGetWindowObject((HWND)Param1)))
570 {
571 RETURN( (DWORD)FALSE);
572 }
573
574 Window->ContextHelpId = Param2;
575
576 RETURN( (DWORD)TRUE);
577
578 case TWOPARAM_ROUTINE_SETCARETPOS:
579 RETURN( (DWORD)co_IntSetCaretPos((int)Param1, (int)Param2));
580
581 case TWOPARAM_ROUTINE_GETWINDOWINFO:
582 {
583 WINDOWINFO wi;
584 DWORD Ret;
585
586 if(!(Window = UserGetWindowObject((HWND)Param1)))
587 {
588 RETURN( FALSE);
589 }
590
591 #if 0
592 /*
593 * According to WINE, Windows' doesn't check the cbSize field
594 */
595
596 Status = MmCopyFromCaller(&wi.cbSize, (PVOID)Param2, sizeof(wi.cbSize));
597 if(!NT_SUCCESS(Status))
598 {
599 SetLastNtError(Status);
600 RETURN( FALSE);
601 }
602
603 if(wi.cbSize != sizeof(WINDOWINFO))
604 {
605 SetLastWin32Error(ERROR_INVALID_PARAMETER);
606 RETURN( FALSE);
607 }
608 #endif
609
610 if((Ret = (DWORD)IntGetWindowInfo(Window, &wi)))
611 {
612 Status = MmCopyToCaller((PVOID)Param2, &wi, sizeof(WINDOWINFO));
613 if(!NT_SUCCESS(Status))
614 {
615 SetLastNtError(Status);
616 RETURN( FALSE);
617 }
618 }
619
620 RETURN( Ret);
621 }
622
623 case TWOPARAM_ROUTINE_REGISTERLOGONPROC:
624 RETURN( (DWORD)co_IntRegisterLogonProcess((HANDLE)Param1, (BOOL)Param2));
625
626 case TWOPARAM_ROUTINE_SETSYSCOLORS:
627 {
628 DWORD Ret = 0;
629 PVOID Buffer;
630 struct
631 {
632 INT *Elements;
633 COLORREF *Colors;
634 }
635 ChangeSysColors;
636
637 /* FIXME - we should make use of SEH here... */
638
639 Status = MmCopyFromCaller(&ChangeSysColors, (PVOID)Param1, sizeof(ChangeSysColors));
640 if(!NT_SUCCESS(Status))
641 {
642 SetLastNtError(Status);
643 RETURN( 0);
644 }
645
646 Buffer = ExAllocatePool(PagedPool, (Param2 * sizeof(INT)) + (Param2 * sizeof(COLORREF)));
647 if(Buffer != NULL)
648 {
649 INT *Elements = (INT*)Buffer;
650 COLORREF *Colors = (COLORREF*)Buffer + Param2;
651
652 Status = MmCopyFromCaller(Elements, ChangeSysColors.Elements, Param2 * sizeof(INT));
653 if(NT_SUCCESS(Status))
654 {
655 Status = MmCopyFromCaller(Colors, ChangeSysColors.Colors, Param2 * sizeof(COLORREF));
656 if(NT_SUCCESS(Status))
657 {
658 Ret = (DWORD)IntSetSysColors((UINT)Param2, Elements, Colors);
659 }
660 else
661 SetLastNtError(Status);
662 }
663 else
664 SetLastNtError(Status);
665
666 ExFreePool(Buffer);
667 }
668
669
670 RETURN( Ret);
671 }
672
673 case TWOPARAM_ROUTINE_GETSYSCOLORBRUSHES:
674 case TWOPARAM_ROUTINE_GETSYSCOLORPENS:
675 case TWOPARAM_ROUTINE_GETSYSCOLORS:
676 {
677 DWORD Ret = 0;
678 union
679 {
680 PVOID Pointer;
681 HBRUSH *Brushes;
682 HPEN *Pens;
683 COLORREF *Colors;
684 } Buffer;
685
686 /* FIXME - we should make use of SEH here... */
687
688 Buffer.Pointer = ExAllocatePool(PagedPool, Param2 * sizeof(HANDLE));
689 if(Buffer.Pointer != NULL)
690 {
691 switch(Routine)
692 {
693 case TWOPARAM_ROUTINE_GETSYSCOLORBRUSHES:
694 Ret = (DWORD)IntGetSysColorBrushes(Buffer.Brushes, (UINT)Param2);
695 break;
696 case TWOPARAM_ROUTINE_GETSYSCOLORPENS:
697 Ret = (DWORD)IntGetSysColorPens(Buffer.Pens, (UINT)Param2);
698 break;
699 case TWOPARAM_ROUTINE_GETSYSCOLORS:
700 Ret = (DWORD)IntGetSysColors(Buffer.Colors, (UINT)Param2);
701 break;
702 default:
703 Ret = 0;
704 break;
705 }
706
707 if(Ret > 0)
708 {
709 Status = MmCopyToCaller((PVOID)Param1, Buffer.Pointer, Param2 * sizeof(HANDLE));
710 if(!NT_SUCCESS(Status))
711 {
712 SetLastNtError(Status);
713 Ret = 0;
714 }
715 }
716
717 ExFreePool(Buffer.Pointer);
718 }
719 RETURN( Ret);
720 }
721
722 }
723 DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam(), Param1=0x%x Parm2=0x%x\n",
724 Routine, Param1, Param2);
725 SetLastWin32Error(ERROR_INVALID_PARAMETER);
726 RETURN( 0);
727
728 CLEANUP:
729 DPRINT("Leave NtUserCallTwoParam, ret=%i\n",_ret_);
730 UserLeave();
731 END_CLEANUP;
732 }
733
734
735 /*
736 * @unimplemented
737 */
738 BOOL
739 STDCALL
740 NtUserCallHwndLock(
741 HWND hWnd,
742 DWORD Routine)
743 {
744 BOOL Ret = 0;
745 PWINDOW_OBJECT Window;
746 USER_REFERENCE_ENTRY Ref;
747 DECLARE_RETURN(BOOLEAN);
748
749 DPRINT("Enter NtUserCallHwndLock\n");
750 UserEnterExclusive();
751
752 if (!(Window = UserGetWindowObject(hWnd)))
753 {
754 RETURN( FALSE);
755 }
756 UserRefObjectCo(Window, &Ref);
757
758 /* FIXME: Routine can be 0x53 - 0x5E */
759 switch (Routine)
760 {
761 case HWNDLOCK_ROUTINE_ARRANGEICONICWINDOWS:
762 co_WinPosArrangeIconicWindows(Window);
763 break;
764
765 case HWNDLOCK_ROUTINE_DRAWMENUBAR:
766 {
767 PMENU_OBJECT Menu;
768 DPRINT("HWNDLOCK_ROUTINE_DRAWMENUBAR\n");
769 Ret = FALSE;
770 if (!((Window->Style & (WS_CHILD | WS_POPUP)) != WS_CHILD))
771 break;
772
773 if(!(Menu = UserGetMenuObject((HMENU) Window->IDMenu)))
774 break;
775
776 Menu->MenuInfo.WndOwner = hWnd;
777 Menu->MenuInfo.Height = 0;
778
779 co_WinPosSetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
780 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
781
782 Ret = TRUE;
783 break;
784 }
785
786 case HWNDLOCK_ROUTINE_REDRAWFRAME:
787 /* FIXME */
788 break;
789
790 case HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOW:
791 Ret = co_IntSetForegroundWindow(Window);
792 break;
793
794 case HWNDLOCK_ROUTINE_UPDATEWINDOW:
795 /* FIXME */
796 break;
797 }
798
799 UserDerefObjectCo(Window);
800
801 RETURN( Ret);
802
803 CLEANUP:
804 DPRINT("Leave NtUserCallHwndLock, ret=%i\n",_ret_);
805 UserLeave();
806 END_CLEANUP;
807 }
808
809 /*
810 * @unimplemented
811 */
812 HWND
813 STDCALL
814 NtUserCallHwndOpt(
815 HWND Param,
816 DWORD Routine)
817 {
818 switch (Routine)
819 {
820 case HWNDOPT_ROUTINE_SETPROGMANWINDOW:
821 GetW32ThreadInfo()->Desktop->hProgmanWindow = Param;
822 break;
823
824 case HWNDOPT_ROUTINE_SETTASKMANWINDOW:
825 GetW32ThreadInfo()->Desktop->hTaskManWindow = Param;
826 break;
827 }
828
829 return Param;
830 }
831
832 /*
833 * @unimplemented
834 */
835 DWORD STDCALL
836 NtUserGetThreadState(
837 DWORD Routine)
838 {
839 DECLARE_RETURN(DWORD);
840
841 DPRINT("Enter NtUserGetThreadState\n");
842 if (Routine != THREADSTATE_GETTHREADINFO)
843 {
844 UserEnterShared();
845 }
846 else
847 {
848 UserEnterExclusive();
849 }
850
851 switch (Routine)
852 {
853 case THREADSTATE_GETTHREADINFO:
854 GetW32ThreadInfo();
855 RETURN(0);
856
857 case THREADSTATE_FOCUSWINDOW:
858 RETURN( (DWORD)IntGetThreadFocusWindow());
859 case THREADSTATE_PROGMANWINDOW:
860 RETURN( (DWORD)GetW32ThreadInfo()->Desktop->hProgmanWindow);
861 case THREADSTATE_TASKMANWINDOW:
862 RETURN( (DWORD)GetW32ThreadInfo()->Desktop->hTaskManWindow);
863 }
864 RETURN( 0);
865
866 CLEANUP:
867 DPRINT("Leave NtUserGetThreadState, ret=%i\n",_ret_);
868 UserLeave();
869 END_CLEANUP;
870 }
871
872 VOID FASTCALL
873 IntGetFontMetricSetting(LPWSTR lpValueName, PLOGFONTW font)
874 {
875 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
876 NTSTATUS Status;
877 /* Firefox 1.0.7 depends on the lfHeight value being negative */
878 static LOGFONTW DefaultFont = {
879 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
880 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
881 L"MS Sans Serif"
882 };
883
884 RtlZeroMemory(&QueryTable, sizeof(QueryTable));
885
886 QueryTable[0].Name = lpValueName;
887 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
888 QueryTable[0].EntryContext = font;
889
890 Status = RtlQueryRegistryValues(
891 RTL_REGISTRY_USER,
892 L"Control Panel\\Desktop\\WindowMetrics",
893 QueryTable,
894 NULL,
895 NULL);
896
897 if (!NT_SUCCESS(Status))
898 {
899 RtlCopyMemory(font, &DefaultFont, sizeof(LOGFONTW));
900 }
901 }
902
903 ULONG FASTCALL
904 IntSystemParametersInfo(
905 UINT uiAction,
906 UINT uiParam,
907 PVOID pvParam,
908 UINT fWinIni)
909 {
910 PWINSTATION_OBJECT WinStaObject;
911 NTSTATUS Status;
912
913 static BOOL bInitialized = FALSE;
914 static LOGFONTW IconFont;
915 static NONCLIENTMETRICSW pMetrics;
916 static BOOL GradientCaptions = TRUE;
917 static UINT FocusBorderHeight = 1;
918 static UINT FocusBorderWidth = 1;
919
920 if (!bInitialized)
921 {
922 RtlZeroMemory(&IconFont, sizeof(LOGFONTW));
923 RtlZeroMemory(&pMetrics, sizeof(NONCLIENTMETRICSW));
924
925 IntGetFontMetricSetting(L"CaptionFont", &pMetrics.lfCaptionFont);
926 IntGetFontMetricSetting(L"SmCaptionFont", &pMetrics.lfSmCaptionFont);
927 IntGetFontMetricSetting(L"MenuFont", &pMetrics.lfMenuFont);
928 IntGetFontMetricSetting(L"StatusFont", &pMetrics.lfStatusFont);
929 IntGetFontMetricSetting(L"MessageFont", &pMetrics.lfMessageFont);
930 IntGetFontMetricSetting(L"IconFont", &IconFont);
931
932 pMetrics.iBorderWidth = 1;
933 pMetrics.iScrollWidth = UserGetSystemMetrics(SM_CXVSCROLL);
934 pMetrics.iScrollHeight = UserGetSystemMetrics(SM_CYHSCROLL);
935 pMetrics.iCaptionWidth = UserGetSystemMetrics(SM_CXSIZE);
936 pMetrics.iCaptionHeight = UserGetSystemMetrics(SM_CYSIZE);
937 pMetrics.iSmCaptionWidth = UserGetSystemMetrics(SM_CXSMSIZE);
938 pMetrics.iSmCaptionHeight = UserGetSystemMetrics(SM_CYSMSIZE);
939 pMetrics.iMenuWidth = UserGetSystemMetrics(SM_CXMENUSIZE);
940 pMetrics.iMenuHeight = UserGetSystemMetrics(SM_CYMENUSIZE);
941 pMetrics.cbSize = sizeof(NONCLIENTMETRICSW);
942
943 bInitialized = TRUE;
944 }
945
946 switch(uiAction)
947 {
948 case SPI_SETDOUBLECLKWIDTH:
949 case SPI_SETDOUBLECLKHEIGHT:
950 case SPI_SETDOUBLECLICKTIME:
951 case SPI_SETDESKWALLPAPER:
952 case SPI_GETDESKWALLPAPER:
953 case SPI_GETWHEELSCROLLLINES:
954 case SPI_GETWHEELSCROLLCHARS:
955 case SPI_SETSCREENSAVERRUNNING:
956 case SPI_GETSCREENSAVERRUNNING:
957 case SPI_GETSCREENSAVETIMEOUT:
958 case SPI_SETSCREENSAVETIMEOUT:
959 case SPI_GETSCREENSAVEACTIVE:
960 case SPI_GETFLATMENU:
961 case SPI_SETFLATMENU:
962 {
963 PSYSTEM_CURSORINFO CurInfo;
964
965 Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
966 KernelMode,
967 0,
968 &WinStaObject);
969 if(!NT_SUCCESS(Status))
970 {
971 SetLastNtError(Status);
972 return (DWORD)FALSE;
973 }
974
975 switch(uiAction)
976 {
977 case SPI_GETFLATMENU:
978 if (pvParam != NULL) *((UINT*)pvParam) = WinStaObject->FlatMenu;
979 return TRUE;
980 break;
981 case SPI_SETFLATMENU:
982 WinStaObject->FlatMenu = uiParam;
983 break;
984 case SPI_GETSCREENSAVETIMEOUT:
985 if (pvParam != NULL) *((UINT*)pvParam) = WinStaObject->ScreenSaverTimeOut;
986 return TRUE;
987 break;
988 case SPI_SETSCREENSAVETIMEOUT:
989 WinStaObject->ScreenSaverTimeOut = uiParam;
990 break;
991 case SPI_GETSCREENSAVERRUNNING:
992 if (pvParam != NULL) *((BOOL*)pvParam) = WinStaObject->ScreenSaverRunning;
993 return TRUE;
994 break;
995 case SPI_SETSCREENSAVERRUNNING:
996 if (pvParam != NULL) *((BOOL*)pvParam) = WinStaObject->ScreenSaverRunning;
997 WinStaObject->ScreenSaverRunning = uiParam;
998 break;
999 case SPI_GETSCREENSAVEACTIVE:
1000 /* FIXME: how to disable the screensaver? */
1001 if (pvParam != NULL) *((BOOL*)pvParam) = TRUE;
1002 return TRUE;
1003 break;
1004 case SPI_GETWHEELSCROLLLINES:
1005 CurInfo = IntGetSysCursorInfo(WinStaObject);
1006 if (pvParam != NULL) *((UINT*)pvParam) = CurInfo->WheelScroLines;
1007 /* FIXME add this value to scroll list as scroll value ?? */
1008 return TRUE;
1009 break;
1010 case SPI_GETWHEELSCROLLCHARS:
1011 CurInfo = IntGetSysCursorInfo(WinStaObject);
1012 if (pvParam != NULL) *((UINT*)pvParam) = CurInfo->WheelScroChars;
1013 // FIXME add this value to scroll list as scroll value ??
1014 return TRUE;
1015 break;
1016 case SPI_SETDOUBLECLKWIDTH:
1017 CurInfo = IntGetSysCursorInfo(WinStaObject);
1018 /* FIXME limit the maximum value? */
1019 CurInfo->DblClickWidth = uiParam;
1020 break;
1021 case SPI_SETDOUBLECLKHEIGHT:
1022 CurInfo = IntGetSysCursorInfo(WinStaObject);
1023 /* FIXME limit the maximum value? */
1024 CurInfo->DblClickHeight = uiParam;
1025 break;
1026 case SPI_SETDOUBLECLICKTIME:
1027 CurInfo = IntGetSysCursorInfo(WinStaObject);
1028 /* FIXME limit the maximum time to 1000 ms? */
1029 CurInfo->DblClickSpeed = uiParam;
1030 break;
1031 case SPI_SETDESKWALLPAPER:
1032 {
1033 /* This function expects different parameters than the user mode version!
1034
1035 We let the user mode code load the bitmap, it passed the handle to
1036 the bitmap. We'll change it's ownership to system and replace it with
1037 the current wallpaper bitmap */
1038 HBITMAP hOldBitmap, hNewBitmap;
1039 UNICODE_STRING Key = RTL_CONSTANT_STRING(L"Control Panel\\Desktop");
1040 UNICODE_STRING Tile = RTL_CONSTANT_STRING(L"TileWallpaper");
1041 UNICODE_STRING Style = RTL_CONSTANT_STRING(L"WallpaperStyle");
1042 UNICODE_STRING KeyPath;
1043 OBJECT_ATTRIBUTES KeyAttributes;
1044 OBJECT_ATTRIBUTES ObjectAttributes;
1045 NTSTATUS Status;
1046 HANDLE CurrentUserKey = NULL;
1047 HANDLE KeyHandle = NULL;
1048 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
1049 ULONG Length = 0;
1050 ULONG ResLength = 0;
1051 ULONG TileNum = 0;
1052 ULONG StyleNum = 0;
1053 ASSERT(pvParam);
1054
1055 hNewBitmap = *(HBITMAP*)pvParam;
1056 if(hNewBitmap != NULL)
1057 {
1058 BITMAPOBJ *bmp;
1059 /* try to get the size of the wallpaper */
1060 if(!(bmp = BITMAPOBJ_LockBitmap(hNewBitmap)))
1061 {
1062 ObDereferenceObject(WinStaObject);
1063 return FALSE;
1064 }
1065 WinStaObject->cxWallpaper = bmp->SurfObj.sizlBitmap.cx;
1066 WinStaObject->cyWallpaper = bmp->SurfObj.sizlBitmap.cy;
1067
1068 BITMAPOBJ_UnlockBitmap(bmp);
1069
1070 /* change the bitmap's ownership */
1071 GDIOBJ_SetOwnership(GdiHandleTable, hNewBitmap, NULL);
1072 }
1073 hOldBitmap = (HBITMAP)InterlockedExchange((LONG*)&WinStaObject->hbmWallpaper, (LONG)hNewBitmap);
1074 if(hOldBitmap != NULL)
1075 {
1076 /* delete the old wallpaper */
1077 NtGdiDeleteObject(hOldBitmap);
1078 }
1079
1080 /* Set the style */
1081
1082 /*default value is center */
1083 WinStaObject->WallpaperMode = wmCenter;
1084
1085
1086
1087 /* Get a handle to the current users settings */
1088 RtlFormatCurrentUserKeyPath(&KeyPath);
1089 InitializeObjectAttributes(&ObjectAttributes,&KeyPath,OBJ_CASE_INSENSITIVE,NULL,NULL);
1090 ZwOpenKey(&CurrentUserKey, KEY_READ, &ObjectAttributes);
1091 RtlFreeUnicodeString(&KeyPath);
1092
1093 /* open up the settings to read the values */
1094 InitializeObjectAttributes(&KeyAttributes, &Key, OBJ_CASE_INSENSITIVE,
1095 CurrentUserKey, NULL);
1096 ZwOpenKey(&KeyHandle, KEY_READ, &KeyAttributes);
1097 ZwClose(CurrentUserKey);
1098
1099 /* read the tile value in the registry */
1100 Status = ZwQueryValueKey(KeyHandle, &Tile, KeyValuePartialInformation,
1101 0, 0, &ResLength);
1102
1103 /* fall back to .DEFAULT if we didnt find values */
1104 if(Status == STATUS_INVALID_HANDLE)
1105 {
1106 RtlInitUnicodeString (&KeyPath,L"\\Registry\\User\\.Default\\Control Panel\\Desktop");
1107 InitializeObjectAttributes(&KeyAttributes, &KeyPath, OBJ_CASE_INSENSITIVE,
1108 NULL, NULL);
1109 ZwOpenKey(&KeyHandle, KEY_READ, &KeyAttributes);
1110 ZwQueryValueKey(KeyHandle, &Tile, KeyValuePartialInformation,
1111 0, 0, &ResLength);
1112 }
1113
1114 ResLength += sizeof(KEY_VALUE_PARTIAL_INFORMATION);
1115 KeyValuePartialInfo = ExAllocatePoolWithTag(PagedPool, ResLength, TAG_STRING);
1116 Length = ResLength;
1117
1118 if(!KeyValuePartialInfo)
1119 {
1120 NtClose(KeyHandle);
1121 return 0;
1122 }
1123
1124 Status = ZwQueryValueKey(KeyHandle, &Tile, KeyValuePartialInformation,
1125 (PVOID)KeyValuePartialInfo, Length, &ResLength);
1126 if(!NT_SUCCESS(Status) || (KeyValuePartialInfo->Type != REG_SZ))
1127 {
1128 ZwClose(KeyHandle);
1129 ExFreePool(KeyValuePartialInfo);
1130 return 0;
1131 }
1132
1133 Tile.Length = KeyValuePartialInfo->DataLength;
1134 Tile.MaximumLength = KeyValuePartialInfo->DataLength;
1135 Tile.Buffer = (PWSTR)KeyValuePartialInfo->Data;
1136
1137 Status = RtlUnicodeStringToInteger(&Tile, 0, &TileNum);
1138 if(!NT_SUCCESS(Status))
1139 {
1140 TileNum = 0;
1141 }
1142 ExFreePool(KeyValuePartialInfo);
1143
1144 /* start over again and look for the style*/
1145 ResLength = 0;
1146 Status = ZwQueryValueKey(KeyHandle, &Style, KeyValuePartialInformation,
1147 0, 0, &ResLength);
1148
1149 ResLength += sizeof(KEY_VALUE_PARTIAL_INFORMATION);
1150 KeyValuePartialInfo = ExAllocatePoolWithTag(PagedPool, ResLength, TAG_STRING);
1151 Length = ResLength;
1152
1153 if(!KeyValuePartialInfo)
1154 {
1155 ZwClose(KeyHandle);
1156 return 0;
1157 }
1158
1159 Status = ZwQueryValueKey(KeyHandle, &Style, KeyValuePartialInformation,
1160 (PVOID)KeyValuePartialInfo, Length, &ResLength);
1161 if(!NT_SUCCESS(Status) || (KeyValuePartialInfo->Type != REG_SZ))
1162 {
1163 ZwClose(KeyHandle);
1164 ExFreePool(KeyValuePartialInfo);
1165 return 0;
1166 }
1167
1168 Style.Length = KeyValuePartialInfo->DataLength;
1169 Style.MaximumLength = KeyValuePartialInfo->DataLength;
1170 Style.Buffer = (PWSTR)KeyValuePartialInfo->Data;
1171
1172 Status = RtlUnicodeStringToInteger(&Style, 0, &StyleNum);
1173 if(!NT_SUCCESS(Status))
1174 {
1175 StyleNum = 0;
1176 }
1177 ExFreePool(KeyValuePartialInfo);
1178
1179 /* Check the values we found in the registry */
1180 if(TileNum && !StyleNum)
1181 {
1182 WinStaObject->WallpaperMode = wmTile;
1183 }
1184 else if(!TileNum && StyleNum == 2)
1185 {
1186 WinStaObject->WallpaperMode = wmStretch;
1187 }
1188
1189 ZwClose(KeyHandle);
1190 break;
1191 }
1192 case SPI_GETDESKWALLPAPER:
1193 /* This function expects different parameters than the user mode version!
1194
1195 We basically return the current wallpaper handle - if any. The user
1196 mode version should load the string from the registry and return it
1197 without calling this function */
1198 ASSERT(pvParam);
1199 *(HBITMAP*)pvParam = (HBITMAP)WinStaObject->hbmWallpaper;
1200 break;
1201 }
1202
1203 /* FIXME save the value to the registry */
1204
1205 ObDereferenceObject(WinStaObject);
1206 return TRUE;
1207 }
1208 case SPI_SETWORKAREA:
1209 {
1210 RECT *rc;
1211 PDESKTOP_OBJECT Desktop = PsGetCurrentThreadWin32Thread()->Desktop;
1212
1213 if(!Desktop)
1214 {
1215 /* FIXME - Set last error */
1216 return FALSE;
1217 }
1218
1219 ASSERT(pvParam);
1220 rc = (RECT*)pvParam;
1221 Desktop->WorkArea = *rc;
1222
1223 return TRUE;
1224 }
1225 case SPI_GETWORKAREA:
1226 {
1227 PDESKTOP_OBJECT Desktop = PsGetCurrentThreadWin32Thread()->Desktop;
1228
1229 if(!Desktop)
1230 {
1231 /* FIXME - Set last error */
1232 return FALSE;
1233 }
1234
1235 ASSERT(pvParam);
1236 IntGetDesktopWorkArea(Desktop, (PRECT)pvParam);
1237
1238 return TRUE;
1239 }
1240 case SPI_SETGRADIENTCAPTIONS:
1241 {
1242 GradientCaptions = (pvParam != NULL);
1243 /* FIXME - should be checked if the color depth is higher than 8bpp? */
1244 return TRUE;
1245 }
1246 case SPI_GETGRADIENTCAPTIONS:
1247 {
1248 HDC hDC;
1249 BOOL Ret = GradientCaptions;
1250
1251 hDC = IntGetScreenDC();
1252 if(hDC)
1253 {
1254 Ret = (NtGdiGetDeviceCaps(hDC, BITSPIXEL) > 8) && Ret;
1255
1256 ASSERT(pvParam);
1257 *((PBOOL)pvParam) = Ret;
1258 return TRUE;
1259 }
1260 return FALSE;
1261 }
1262 case SPI_SETFONTSMOOTHING:
1263 {
1264 IntEnableFontRendering(uiParam != 0);
1265 return TRUE;
1266 }
1267 case SPI_GETFONTSMOOTHING:
1268 {
1269 ASSERT(pvParam);
1270 *((BOOL*)pvParam) = IntIsFontRenderingEnabled();
1271 return TRUE;
1272 }
1273 case SPI_GETICONTITLELOGFONT:
1274 {
1275 ASSERT(pvParam);
1276 *((LOGFONTW*)pvParam) = IconFont;
1277 return TRUE;
1278 }
1279 case SPI_GETNONCLIENTMETRICS:
1280 {
1281 ASSERT(pvParam);
1282 *((NONCLIENTMETRICSW*)pvParam) = pMetrics;
1283 return TRUE;
1284 }
1285 case SPI_SETNONCLIENTMETRICS:
1286 {
1287 ASSERT(pvParam);
1288 pMetrics = *((NONCLIENTMETRICSW*)pvParam);
1289 return TRUE;
1290 }
1291 case SPI_GETFOCUSBORDERHEIGHT:
1292 {
1293 ASSERT(pvParam);
1294 *((UINT*)pvParam) = FocusBorderHeight;
1295 return TRUE;
1296 }
1297 case SPI_GETFOCUSBORDERWIDTH:
1298 {
1299 ASSERT(pvParam);
1300 *((UINT*)pvParam) = FocusBorderWidth;
1301 return TRUE;
1302 }
1303 case SPI_SETFOCUSBORDERHEIGHT:
1304 {
1305 FocusBorderHeight = (UINT)pvParam;
1306 return TRUE;
1307 }
1308 case SPI_SETFOCUSBORDERWIDTH:
1309 {
1310 FocusBorderWidth = (UINT)pvParam;
1311 return TRUE;
1312 }
1313
1314 default:
1315 {
1316 DPRINT1("SystemParametersInfo: Unsupported Action 0x%x (uiParam: 0x%x, pvParam: 0x%x, fWinIni: 0x%x)\n",
1317 uiAction, uiParam, pvParam, fWinIni);
1318 return FALSE;
1319 }
1320 }
1321 return FALSE;
1322 }
1323
1324 /*
1325 * @implemented
1326 */
1327 BOOL FASTCALL
1328 UserSystemParametersInfo(
1329 UINT uiAction,
1330 UINT uiParam,
1331 PVOID pvParam,
1332 UINT fWinIni)
1333 {
1334 NTSTATUS Status;
1335
1336 switch(uiAction)
1337 {
1338 case SPI_SETDOUBLECLKWIDTH:
1339 case SPI_SETDOUBLECLKHEIGHT:
1340 case SPI_SETDOUBLECLICKTIME:
1341 case SPI_SETGRADIENTCAPTIONS:
1342 case SPI_SETFONTSMOOTHING:
1343 case SPI_SETFOCUSBORDERHEIGHT:
1344 case SPI_SETFOCUSBORDERWIDTH:
1345 {
1346 return (DWORD)IntSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni);
1347 }
1348 case SPI_SETWORKAREA:
1349 {
1350 RECT rc;
1351 Status = MmCopyFromCaller(&rc, (PRECT)pvParam, sizeof(RECT));
1352 if(!NT_SUCCESS(Status))
1353 {
1354 SetLastNtError(Status);
1355 return( FALSE);
1356 }
1357 return( (DWORD)IntSystemParametersInfo(uiAction, uiParam, &rc, fWinIni));
1358 }
1359 case SPI_GETWORKAREA:
1360 {
1361 RECT rc;
1362
1363 if(!IntSystemParametersInfo(uiAction, uiParam, &rc, fWinIni))
1364 {
1365 return( FALSE);
1366 }
1367
1368 Status = MmCopyToCaller((PRECT)pvParam, &rc, sizeof(RECT));
1369 if(!NT_SUCCESS(Status))
1370 {
1371 SetLastNtError(Status);
1372 return( FALSE);
1373 }
1374 return( TRUE);
1375 }
1376 case SPI_GETFONTSMOOTHING:
1377 case SPI_GETGRADIENTCAPTIONS:
1378 case SPI_GETFOCUSBORDERHEIGHT:
1379 case SPI_GETFOCUSBORDERWIDTH:
1380 case SPI_GETWHEELSCROLLLINES:
1381 case SPI_GETWHEELSCROLLCHARS:
1382 case SPI_GETSCREENSAVERRUNNING:
1383 case SPI_SETSCREENSAVERRUNNING:
1384 case SPI_GETSCREENSAVETIMEOUT:
1385 case SPI_SETSCREENSAVETIMEOUT:
1386 case SPI_GETSCREENSAVEACTIVE:
1387 case SPI_GETFLATMENU:
1388 case SPI_SETFLATMENU:
1389 {
1390 BOOL Ret;
1391
1392 if(!IntSystemParametersInfo(uiAction, uiParam, &Ret, fWinIni))
1393 {
1394 return( FALSE);
1395 }
1396
1397 Status = MmCopyToCaller(pvParam, &Ret, sizeof(BOOL));
1398 if(!NT_SUCCESS(Status))
1399 {
1400 SetLastNtError(Status);
1401 return( FALSE);
1402 }
1403 return( TRUE);
1404 }
1405 case SPI_SETDESKWALLPAPER:
1406 {
1407 /* !!! As opposed to the user mode version this version accepts a handle
1408 to the bitmap! */
1409 HBITMAP hbmWallpaper;
1410
1411 Status = MmCopyFromCaller(&hbmWallpaper, pvParam, sizeof(HBITMAP));
1412 if(!NT_SUCCESS(Status))
1413 {
1414 SetLastNtError(Status);
1415 return( FALSE);
1416 }
1417 return( IntSystemParametersInfo(SPI_SETDESKWALLPAPER, 0, &hbmWallpaper, fWinIni));
1418 }
1419 case SPI_GETDESKWALLPAPER:
1420 {
1421 /* !!! As opposed to the user mode version this version returns a handle
1422 to the bitmap! */
1423 HBITMAP hbmWallpaper;
1424 BOOL Ret;
1425
1426 Ret = IntSystemParametersInfo(SPI_GETDESKWALLPAPER, 0, &hbmWallpaper, fWinIni);
1427
1428 Status = MmCopyToCaller(pvParam, &hbmWallpaper, sizeof(HBITMAP));
1429 if(!NT_SUCCESS(Status))
1430 {
1431 SetLastNtError(Status);
1432 return( FALSE);
1433 }
1434 return( Ret);
1435 }
1436 case SPI_GETICONTITLELOGFONT:
1437 {
1438 LOGFONTW IconFont;
1439
1440 if(!IntSystemParametersInfo(uiAction, uiParam, &IconFont, fWinIni))
1441 {
1442 return( FALSE);
1443 }
1444
1445 Status = MmCopyToCaller(pvParam, &IconFont, sizeof(LOGFONTW));
1446 if(!NT_SUCCESS(Status))
1447 {
1448 SetLastNtError(Status);
1449 return( FALSE);
1450 }
1451 return( TRUE);
1452 }
1453 case SPI_GETNONCLIENTMETRICS:
1454 case SPI_SETNONCLIENTMETRICS:
1455 {
1456 NONCLIENTMETRICSW metrics;
1457
1458 Status = MmCopyFromCaller(&metrics, pvParam, sizeof(NONCLIENTMETRICSW));
1459 if(!NT_SUCCESS(Status))
1460 {
1461 SetLastNtError(Status);
1462 return( FALSE);
1463 }
1464 if(metrics.cbSize != sizeof(NONCLIENTMETRICSW))
1465 {
1466 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1467 return( FALSE);
1468 }
1469
1470 if(!IntSystemParametersInfo(uiAction, uiParam, &metrics, fWinIni))
1471 {
1472 return( FALSE);
1473 }
1474
1475 Status = MmCopyToCaller(pvParam, &metrics, sizeof(NONCLIENTMETRICSW));
1476 if(!NT_SUCCESS(Status))
1477 {
1478 SetLastNtError(Status);
1479 return( FALSE);
1480 }
1481 return( TRUE);
1482 }
1483 default :
1484 {
1485 DPRINT1("FIXME: UNIMPLEMENTED SPI Code: %lx \n",uiAction );
1486 break;
1487 }
1488 }
1489 return( FALSE);
1490 }
1491
1492
1493
1494
1495 /*
1496 * @implemented
1497 */
1498 BOOL
1499 STDCALL
1500 NtUserSystemParametersInfo(
1501 UINT uiAction,
1502 UINT uiParam,
1503 PVOID pvParam,
1504 UINT fWinIni)
1505 {
1506 DECLARE_RETURN(BOOLEAN);
1507
1508 DPRINT("Enter NtUserSystemParametersInfo\n");
1509 UserEnterExclusive();
1510
1511 RETURN( UserSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni));
1512
1513 CLEANUP:
1514 DPRINT("Leave NtUserSystemParametersInfo, ret=%i\n",_ret_);
1515 UserLeave();
1516 END_CLEANUP;
1517 }
1518
1519
1520
1521 UINT
1522 STDCALL
1523 NtUserGetDoubleClickTime(VOID)
1524 {
1525 UINT Result;
1526 NTSTATUS Status;
1527 PWINSTATION_OBJECT WinStaObject;
1528 PSYSTEM_CURSORINFO CurInfo;
1529 DECLARE_RETURN(UINT);
1530
1531 DPRINT("Enter NtUserGetDoubleClickTime\n");
1532 UserEnterShared();
1533
1534 Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
1535 KernelMode,
1536 0,
1537 &WinStaObject);
1538 if (!NT_SUCCESS(Status))
1539 RETURN( (DWORD)FALSE);
1540
1541 CurInfo = IntGetSysCursorInfo(WinStaObject);
1542 Result = CurInfo->DblClickSpeed;
1543
1544 ObDereferenceObject(WinStaObject);
1545 RETURN( Result);
1546
1547 CLEANUP:
1548 DPRINT("Leave NtUserGetDoubleClickTime, ret=%i\n",_ret_);
1549 UserLeave();
1550 END_CLEANUP;
1551 }
1552
1553 BOOL
1554 STDCALL
1555 NtUserGetGUIThreadInfo(
1556 DWORD idThread, /* if NULL use foreground thread */
1557 LPGUITHREADINFO lpgui)
1558 {
1559 NTSTATUS Status;
1560 PTHRDCARETINFO CaretInfo;
1561 GUITHREADINFO SafeGui;
1562 PDESKTOP_OBJECT Desktop;
1563 PUSER_MESSAGE_QUEUE MsgQueue;
1564 PETHREAD Thread = NULL;
1565 DECLARE_RETURN(BOOLEAN);
1566
1567 DPRINT("Enter NtUserGetGUIThreadInfo\n");
1568 UserEnterShared();
1569
1570 Status = MmCopyFromCaller(&SafeGui, lpgui, sizeof(DWORD));
1571 if(!NT_SUCCESS(Status))
1572 {
1573 SetLastNtError(Status);
1574 RETURN( FALSE);
1575 }
1576
1577 if(SafeGui.cbSize != sizeof(GUITHREADINFO))
1578 {
1579 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1580 RETURN( FALSE);
1581 }
1582
1583 if(idThread)
1584 {
1585 Status = PsLookupThreadByThreadId((HANDLE)idThread, &Thread);
1586 if(!NT_SUCCESS(Status))
1587 {
1588 SetLastWin32Error(ERROR_ACCESS_DENIED);
1589 RETURN( FALSE);
1590 }
1591 Desktop = ((PW32THREAD)Thread->Tcb.Win32Thread)->Desktop;
1592 }
1593 else
1594 {
1595 /* get the foreground thread */
1596 PW32THREAD W32Thread = (PW32THREAD)PsGetCurrentThread()->Tcb.Win32Thread;
1597 Desktop = W32Thread->Desktop;
1598 if(Desktop)
1599 {
1600 MsgQueue = Desktop->ActiveMessageQueue;
1601 if(MsgQueue)
1602 {
1603 Thread = MsgQueue->Thread;
1604 }
1605 }
1606 }
1607
1608 if(!Thread || !Desktop)
1609 {
1610 if(idThread && Thread)
1611 ObDereferenceObject(Thread);
1612 SetLastWin32Error(ERROR_ACCESS_DENIED);
1613 RETURN( FALSE);
1614 }
1615
1616 MsgQueue = (PUSER_MESSAGE_QUEUE)Desktop->ActiveMessageQueue;
1617 CaretInfo = MsgQueue->CaretInfo;
1618
1619 SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0);
1620 if(MsgQueue->MenuOwner)
1621 SafeGui.flags |= GUI_INMENUMODE | MsgQueue->MenuState;
1622 if(MsgQueue->MoveSize)
1623 SafeGui.flags |= GUI_INMOVESIZE;
1624
1625 /* FIXME add flag GUI_16BITTASK */
1626
1627 SafeGui.hwndActive = MsgQueue->ActiveWindow;
1628 SafeGui.hwndFocus = MsgQueue->FocusWindow;
1629 SafeGui.hwndCapture = MsgQueue->CaptureWindow;
1630 SafeGui.hwndMenuOwner = MsgQueue->MenuOwner;
1631 SafeGui.hwndMoveSize = MsgQueue->MoveSize;
1632 SafeGui.hwndCaret = CaretInfo->hWnd;
1633
1634 SafeGui.rcCaret.left = CaretInfo->Pos.x;
1635 SafeGui.rcCaret.top = CaretInfo->Pos.y;
1636 SafeGui.rcCaret.right = SafeGui.rcCaret.left + CaretInfo->Size.cx;
1637 SafeGui.rcCaret.bottom = SafeGui.rcCaret.top + CaretInfo->Size.cy;
1638
1639 if(idThread)
1640 ObDereferenceObject(Thread);
1641
1642 Status = MmCopyToCaller(lpgui, &SafeGui, sizeof(GUITHREADINFO));
1643 if(!NT_SUCCESS(Status))
1644 {
1645 SetLastNtError(Status);
1646 RETURN( FALSE);
1647 }
1648
1649 RETURN( TRUE);
1650
1651 CLEANUP:
1652 DPRINT("Leave NtUserGetGUIThreadInfo, ret=%i\n",_ret_);
1653 UserLeave();
1654 END_CLEANUP;
1655 }
1656
1657
1658 DWORD
1659 STDCALL
1660 NtUserGetGuiResources(
1661 HANDLE hProcess,
1662 DWORD uiFlags)
1663 {
1664 PEPROCESS Process;
1665 PW32PROCESS W32Process;
1666 NTSTATUS Status;
1667 DWORD Ret = 0;
1668 DECLARE_RETURN(DWORD);
1669
1670 DPRINT("Enter NtUserGetGuiResources\n");
1671 UserEnterShared();
1672
1673 Status = ObReferenceObjectByHandle(hProcess,
1674 PROCESS_QUERY_INFORMATION,
1675 PsProcessType,
1676 ExGetPreviousMode(),
1677 (PVOID*)&Process,
1678 NULL);
1679
1680 if(!NT_SUCCESS(Status))
1681 {
1682 SetLastNtError(Status);
1683 RETURN( 0);
1684 }
1685
1686 W32Process = (PW32PROCESS)Process->Win32Process;
1687 if(!W32Process)
1688 {
1689 ObDereferenceObject(Process);
1690 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1691 RETURN( 0);
1692 }
1693
1694 switch(uiFlags)
1695 {
1696 case GR_GDIOBJECTS:
1697 {
1698 Ret = (DWORD)W32Process->GDIObjects;
1699 break;
1700 }
1701 case GR_USEROBJECTS:
1702 {
1703 Ret = (DWORD)W32Process->UserObjects;
1704 break;
1705 }
1706 default:
1707 {
1708 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1709 break;
1710 }
1711 }
1712
1713 ObDereferenceObject(Process);
1714
1715 RETURN( Ret);
1716
1717 CLEANUP:
1718 DPRINT("Leave NtUserGetGuiResources, ret=%i\n",_ret_);
1719 UserLeave();
1720 END_CLEANUP;
1721 }
1722
1723 NTSTATUS FASTCALL
1724 IntSafeCopyUnicodeString(PUNICODE_STRING Dest,
1725 PUNICODE_STRING Source)
1726 {
1727 NTSTATUS Status;
1728 PWSTR Src;
1729
1730 Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING));
1731 if(!NT_SUCCESS(Status))
1732 {
1733 return Status;
1734 }
1735
1736 if(Dest->Length > 0x4000)
1737 {
1738 return STATUS_UNSUCCESSFUL;
1739 }
1740
1741 Src = Dest->Buffer;
1742 Dest->Buffer = NULL;
1743
1744 if(Dest->Length > 0 && Src)
1745 {
1746 Dest->MaximumLength = Dest->Length;
1747 Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING);
1748 if(!Dest->Buffer)
1749 {
1750 return STATUS_NO_MEMORY;
1751 }
1752
1753 Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length);
1754 if(!NT_SUCCESS(Status))
1755 {
1756 ExFreePool(Dest->Buffer);
1757 Dest->Buffer = NULL;
1758 return Status;
1759 }
1760
1761
1762 return STATUS_SUCCESS;
1763 }
1764
1765 /* string is empty */
1766 return STATUS_SUCCESS;
1767 }
1768
1769 NTSTATUS FASTCALL
1770 IntSafeCopyUnicodeStringTerminateNULL(PUNICODE_STRING Dest,
1771 PUNICODE_STRING Source)
1772 {
1773 NTSTATUS Status;
1774 PWSTR Src;
1775
1776 Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING));
1777 if(!NT_SUCCESS(Status))
1778 {
1779 return Status;
1780 }
1781
1782 if(Dest->Length > 0x4000)
1783 {
1784 return STATUS_UNSUCCESSFUL;
1785 }
1786
1787 Src = Dest->Buffer;
1788 Dest->Buffer = NULL;
1789
1790 if(Dest->Length > 0 && Src)
1791 {
1792 Dest->MaximumLength = Dest->Length + sizeof(WCHAR);
1793 Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING);
1794 if(!Dest->Buffer)
1795 {
1796 return STATUS_NO_MEMORY;
1797 }
1798
1799 Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length);
1800 if(!NT_SUCCESS(Status))
1801 {
1802 ExFreePool(Dest->Buffer);
1803 Dest->Buffer = NULL;
1804 return Status;
1805 }
1806
1807 /* make sure the string is null-terminated */
1808 Src = (PWSTR)((PBYTE)Dest->Buffer + Dest->Length);
1809 *Src = L'\0';
1810
1811 return STATUS_SUCCESS;
1812 }
1813
1814 /* string is empty */
1815 return STATUS_SUCCESS;
1816 }
1817
1818 NTSTATUS FASTCALL
1819 IntUnicodeStringToNULLTerminated(PWSTR *Dest, PUNICODE_STRING Src)
1820 {
1821 if (Src->Length + sizeof(WCHAR) <= Src->MaximumLength
1822 && L'\0' == Src->Buffer[Src->Length / sizeof(WCHAR)])
1823 {
1824 /* The unicode_string is already nul terminated. Just reuse it. */
1825 *Dest = Src->Buffer;
1826 return STATUS_SUCCESS;
1827 }
1828
1829 *Dest = ExAllocatePoolWithTag(PagedPool, Src->Length + sizeof(WCHAR), TAG_STRING);
1830 if (NULL == *Dest)
1831 {
1832 return STATUS_NO_MEMORY;
1833 }
1834 RtlCopyMemory(*Dest, Src->Buffer, Src->Length);
1835 (*Dest)[Src->Length / 2] = L'\0';
1836
1837 return STATUS_SUCCESS;
1838 }
1839
1840 void FASTCALL
1841 IntFreeNULLTerminatedFromUnicodeString(PWSTR NullTerminated, PUNICODE_STRING UnicodeString)
1842 {
1843 if (NullTerminated != UnicodeString->Buffer)
1844 {
1845 ExFreePool(NullTerminated);
1846 }
1847 }
1848
1849 BOOL STDCALL
1850 NtUserUpdatePerUserSystemParameters(
1851 DWORD dwReserved,
1852 BOOL bEnable)
1853 {
1854 BOOL Result = TRUE;
1855 DECLARE_RETURN(BOOLEAN);
1856
1857 DPRINT("Enter NtUserUpdatePerUserSystemParameters\n");
1858 UserEnterExclusive();
1859
1860 Result &= IntDesktopUpdatePerUserSettings(bEnable);
1861 RETURN( Result);
1862
1863 CLEANUP:
1864 DPRINT("Leave NtUserUpdatePerUserSystemParameters, ret=%i\n",_ret_);
1865 UserLeave();
1866 END_CLEANUP;
1867 }
1868
1869 PW32PROCESSINFO
1870 GetW32ProcessInfo(VOID)
1871 {
1872 PW32PROCESSINFO pi;
1873 PW32PROCESS W32Process = PsGetCurrentProcessWin32Process();
1874
1875 if (W32Process == NULL)
1876 {
1877 /* FIXME - temporary hack for system threads... */
1878 return NULL;
1879 }
1880
1881 if (W32Process->ProcessInfo == NULL)
1882 {
1883 pi = UserHeapAlloc(sizeof(W32PROCESSINFO));
1884 if (pi != NULL)
1885 {
1886 RtlZeroMemory(pi,
1887 sizeof(W32PROCESSINFO));
1888
1889 /* initialize it */
1890 pi->UserHandleTable = gHandleTable;
1891
1892 if (InterlockedCompareExchangePointer(&W32Process->ProcessInfo,
1893 pi,
1894 NULL) != NULL)
1895 {
1896 UserHeapFree(pi);
1897 }
1898 }
1899 else
1900 {
1901 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
1902 }
1903 }
1904
1905 return W32Process->ProcessInfo;
1906 }
1907
1908 PW32THREADINFO
1909 GetW32ThreadInfo(VOID)
1910 {
1911 PTEB Teb;
1912 PW32THREADINFO ti;
1913 PW32THREAD W32Thread = PsGetCurrentThreadWin32Thread();
1914
1915 if (W32Thread == NULL)
1916 {
1917 /* FIXME - temporary hack for system threads... */
1918 return NULL;
1919 }
1920
1921 /* allocate a W32THREAD structure if neccessary */
1922 if (W32Thread->ThreadInfo == NULL)
1923 {
1924 ti = UserHeapAlloc(sizeof(W32THREADINFO));
1925 if (ti != NULL)
1926 {
1927 RtlZeroMemory(ti,
1928 sizeof(W32THREADINFO));
1929
1930 /* initialize it */
1931 ti->kpi = GetW32ProcessInfo();
1932 ti->pi = UserHeapAddressToUser(ti->kpi);
1933 if (W32Thread->Desktop != NULL)
1934 {
1935 ti->Desktop = W32Thread->Desktop->DesktopInfo;
1936 ti->DesktopHeapDelta = DesktopHeapGetUserDelta();
1937 }
1938 else
1939 {
1940 ti->Desktop = NULL;
1941 ti->DesktopHeapDelta = 0;
1942 }
1943
1944 W32Thread->ThreadInfo = ti;
1945 /* update the TEB */
1946 Teb = NtCurrentTeb();
1947 _SEH_TRY
1948 {
1949 ProbeForWrite(Teb,
1950 sizeof(TEB),
1951 sizeof(ULONG));
1952
1953 Teb->Win32ThreadInfo = UserHeapAddressToUser(W32Thread->ThreadInfo);
1954 }
1955 _SEH_HANDLE
1956 {
1957 SetLastNtError(_SEH_GetExceptionCode());
1958 }
1959 _SEH_END;
1960 }
1961 else
1962 {
1963 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
1964 }
1965 }
1966
1967 return W32Thread->ThreadInfo;
1968 }
1969
1970
1971 /* EOF */