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