1. Fixing so the screensaver only start one time when ReactOS starting.
[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 = PsGetWin32Thread();
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 = PsGetWin32Thread()->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 = PsGetWin32Process();
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 /*
860 * FIXME
861 * Nothing too hard...validate the hWnd and save it in the Desktop Info
862 */
863 DPRINT1("HWNDOPT_ROUTINE_SETPROGMANWINDOW UNIMPLEMENTED\n");
864 break;
865
866 case HWNDOPT_ROUTINE_SETTASKMANWINDOW:
867 /*
868 * FIXME
869 * Nothing too hard...validate the hWnd and save it in the Desktop Info
870 */
871 DPRINT1("HWNDOPT_ROUTINE_SETTASKMANWINDOW UNIMPLEMENTED\n");
872 break;
873 }
874
875 return Param;
876 }
877
878 /*
879 * @unimplemented
880 */
881 DWORD STDCALL
882 NtUserGetThreadState(
883 DWORD Routine)
884 {
885 DECLARE_RETURN(DWORD);
886
887 DPRINT("Enter NtUserGetThreadState\n");
888 if (Routine != THREADSTATE_GETTHREADINFO)
889 {
890 UserEnterShared();
891 }
892 else
893 {
894 UserEnterExclusive();
895 }
896
897 switch (Routine)
898 {
899 case THREADSTATE_GETTHREADINFO:
900 GetW32ThreadInfo();
901 RETURN(0);
902
903 case THREADSTATE_FOCUSWINDOW:
904 RETURN( (DWORD)IntGetThreadFocusWindow());
905 }
906 RETURN( 0);
907
908 CLEANUP:
909 DPRINT("Leave NtUserGetThreadState, ret=%i\n",_ret_);
910 UserLeave();
911 END_CLEANUP;
912 }
913
914 VOID FASTCALL
915 IntGetFontMetricSetting(LPWSTR lpValueName, PLOGFONTW font)
916 {
917 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
918 NTSTATUS Status;
919 /* Firefox 1.0.7 depends on the lfHeight value being negative */
920 static LOGFONTW DefaultFont = {
921 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
922 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
923 L"Bitstream Vera Sans"
924 };
925
926 RtlZeroMemory(&QueryTable, sizeof(QueryTable));
927
928 QueryTable[0].Name = lpValueName;
929 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
930 QueryTable[0].EntryContext = font;
931
932 Status = RtlQueryRegistryValues(
933 RTL_REGISTRY_USER,
934 L"Control Panel\\Desktop\\WindowMetrics",
935 QueryTable,
936 NULL,
937 NULL);
938
939 if (!NT_SUCCESS(Status))
940 {
941 RtlCopyMemory(font, &DefaultFont, sizeof(LOGFONTW));
942 }
943 }
944
945 ULONG FASTCALL
946 IntSystemParametersInfo(
947 UINT uiAction,
948 UINT uiParam,
949 PVOID pvParam,
950 UINT fWinIni)
951 {
952 PWINSTATION_OBJECT WinStaObject;
953 NTSTATUS Status;
954
955 static BOOL bInitialized = FALSE;
956 static LOGFONTW IconFont;
957 static NONCLIENTMETRICSW pMetrics;
958 static BOOL GradientCaptions = TRUE;
959 static UINT FocusBorderHeight = 1;
960 static UINT FocusBorderWidth = 1;
961
962 if (!bInitialized)
963 {
964 RtlZeroMemory(&IconFont, sizeof(LOGFONTW));
965 RtlZeroMemory(&pMetrics, sizeof(NONCLIENTMETRICSW));
966
967 IntGetFontMetricSetting(L"CaptionFont", &pMetrics.lfCaptionFont);
968 IntGetFontMetricSetting(L"SmCaptionFont", &pMetrics.lfSmCaptionFont);
969 IntGetFontMetricSetting(L"MenuFont", &pMetrics.lfMenuFont);
970 IntGetFontMetricSetting(L"StatusFont", &pMetrics.lfStatusFont);
971 IntGetFontMetricSetting(L"MessageFont", &pMetrics.lfMessageFont);
972 IntGetFontMetricSetting(L"IconFont", &IconFont);
973
974 pMetrics.iBorderWidth = 1;
975 pMetrics.iScrollWidth = UserGetSystemMetrics(SM_CXVSCROLL);
976 pMetrics.iScrollHeight = UserGetSystemMetrics(SM_CYHSCROLL);
977 pMetrics.iCaptionWidth = UserGetSystemMetrics(SM_CXSIZE);
978 pMetrics.iCaptionHeight = UserGetSystemMetrics(SM_CYSIZE);
979 pMetrics.iSmCaptionWidth = UserGetSystemMetrics(SM_CXSMSIZE);
980 pMetrics.iSmCaptionHeight = UserGetSystemMetrics(SM_CYSMSIZE);
981 pMetrics.iMenuWidth = UserGetSystemMetrics(SM_CXMENUSIZE);
982 pMetrics.iMenuHeight = UserGetSystemMetrics(SM_CYMENUSIZE);
983 pMetrics.cbSize = sizeof(NONCLIENTMETRICSW);
984
985 bInitialized = TRUE;
986 }
987
988 switch(uiAction)
989 {
990 case SPI_SETDOUBLECLKWIDTH:
991 case SPI_SETDOUBLECLKHEIGHT:
992 case SPI_SETDOUBLECLICKTIME:
993 case SPI_SETDESKWALLPAPER:
994 case SPI_GETDESKWALLPAPER:
995 case SPI_GETWHEELSCROLLLINES:
996 case SPI_GETWHEELSCROLLCHARS:
997 case SPI_SETSCREENSAVERRUNNING:
998 case SPI_GETSCREENSAVERRUNNING:
999 case SPI_GETSCREENSAVETIMEOUT:
1000 case SPI_SETSCREENSAVETIMEOUT:
1001 case SPI_GETFLATMENU:
1002 case SPI_SETFLATMENU:
1003 {
1004 PSYSTEM_CURSORINFO CurInfo;
1005
1006 Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
1007 KernelMode,
1008 0,
1009 &WinStaObject);
1010 if(!NT_SUCCESS(Status))
1011 {
1012 SetLastNtError(Status);
1013 return (DWORD)FALSE;
1014 }
1015
1016 switch(uiAction)
1017 {
1018 case SPI_GETFLATMENU:
1019 if (pvParam != NULL) *((UINT*)pvParam) = WinStaObject->FlatMenu;
1020 return TRUE;
1021 break;
1022 case SPI_SETFLATMENU:
1023 WinStaObject->FlatMenu = uiParam;
1024 break;
1025 case SPI_GETSCREENSAVETIMEOUT:
1026 if (pvParam != NULL) *((UINT*)pvParam) = WinStaObject->ScreenSaverTimeOut;
1027 return TRUE;
1028 break;
1029 case SPI_SETSCREENSAVETIMEOUT:
1030 WinStaObject->ScreenSaverTimeOut = uiParam;
1031 break;
1032 case SPI_GETSCREENSAVERRUNNING:
1033 if (pvParam != NULL) *((BOOL*)pvParam) = WinStaObject->ScreenSaverRunning;
1034 return TRUE;
1035 break;
1036 case SPI_SETSCREENSAVERRUNNING:
1037 if (pvParam != NULL) *((BOOL*)pvParam) = WinStaObject->ScreenSaverRunning;
1038 WinStaObject->ScreenSaverRunning = uiParam;
1039 break;
1040 case SPI_GETWHEELSCROLLLINES:
1041 CurInfo = IntGetSysCursorInfo(WinStaObject);
1042 if (pvParam != NULL) *((UINT*)pvParam) = CurInfo->WheelScroLines;
1043 /* FIXME add this value to scroll list as scroll value ?? */
1044 return TRUE;
1045 break;
1046 case SPI_GETWHEELSCROLLCHARS:
1047 CurInfo = IntGetSysCursorInfo(WinStaObject);
1048 if (pvParam != NULL) *((UINT*)pvParam) = CurInfo->WheelScroChars;
1049 // FIXME add this value to scroll list as scroll value ??
1050 return TRUE;
1051 break;
1052 case SPI_SETDOUBLECLKWIDTH:
1053 CurInfo = IntGetSysCursorInfo(WinStaObject);
1054 /* FIXME limit the maximum value? */
1055 CurInfo->DblClickWidth = uiParam;
1056 break;
1057 case SPI_SETDOUBLECLKHEIGHT:
1058 CurInfo = IntGetSysCursorInfo(WinStaObject);
1059 /* FIXME limit the maximum value? */
1060 CurInfo->DblClickHeight = uiParam;
1061 break;
1062 case SPI_SETDOUBLECLICKTIME:
1063 CurInfo = IntGetSysCursorInfo(WinStaObject);
1064 /* FIXME limit the maximum time to 1000 ms? */
1065 CurInfo->DblClickSpeed = uiParam;
1066 break;
1067 case SPI_SETDESKWALLPAPER:
1068 {
1069 /* This function expects different parameters than the user mode version!
1070
1071 We let the user mode code load the bitmap, it passed the handle to
1072 the bitmap. We'll change it's ownership to system and replace it with
1073 the current wallpaper bitmap */
1074 HBITMAP hOldBitmap, hNewBitmap;
1075 UNICODE_STRING Key = RTL_CONSTANT_STRING(L"Control Panel\\Desktop");
1076 UNICODE_STRING Tile = RTL_CONSTANT_STRING(L"TileWallpaper");
1077 UNICODE_STRING Style = RTL_CONSTANT_STRING(L"WallpaperStyle");
1078 UNICODE_STRING KeyPath;
1079 OBJECT_ATTRIBUTES KeyAttributes;
1080 OBJECT_ATTRIBUTES ObjectAttributes;
1081 NTSTATUS Status;
1082 HANDLE CurrentUserKey = NULL;
1083 HANDLE KeyHandle = NULL;
1084 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
1085 ULONG Length = 0;
1086 ULONG ResLength = 0;
1087 ULONG TileNum = 0;
1088 ULONG StyleNum = 0;
1089 ASSERT(pvParam);
1090
1091 hNewBitmap = *(HBITMAP*)pvParam;
1092 if(hNewBitmap != NULL)
1093 {
1094 BITMAPOBJ *bmp;
1095 /* try to get the size of the wallpaper */
1096 if(!(bmp = BITMAPOBJ_LockBitmap(hNewBitmap)))
1097 {
1098 ObDereferenceObject(WinStaObject);
1099 return FALSE;
1100 }
1101 WinStaObject->cxWallpaper = bmp->SurfObj.sizlBitmap.cx;
1102 WinStaObject->cyWallpaper = bmp->SurfObj.sizlBitmap.cy;
1103
1104 BITMAPOBJ_UnlockBitmap(bmp);
1105
1106 /* change the bitmap's ownership */
1107 GDIOBJ_SetOwnership(GdiHandleTable, hNewBitmap, NULL);
1108 }
1109 hOldBitmap = (HBITMAP)InterlockedExchange((LONG*)&WinStaObject->hbmWallpaper, (LONG)hNewBitmap);
1110 if(hOldBitmap != NULL)
1111 {
1112 /* delete the old wallpaper */
1113 NtGdiDeleteObject(hOldBitmap);
1114 }
1115
1116 /* Set the style */
1117
1118 /*default value is center */
1119 WinStaObject->WallpaperMode = wmCenter;
1120
1121
1122
1123 /* Get a handle to the current users settings */
1124 RtlFormatCurrentUserKeyPath(&KeyPath);
1125 InitializeObjectAttributes(&ObjectAttributes,&KeyPath,OBJ_CASE_INSENSITIVE,NULL,NULL);
1126 ZwOpenKey(&CurrentUserKey, KEY_READ, &ObjectAttributes);
1127 RtlFreeUnicodeString(&KeyPath);
1128
1129 /* open up the settings to read the values */
1130 InitializeObjectAttributes(&KeyAttributes, &Key, OBJ_CASE_INSENSITIVE,
1131 CurrentUserKey, NULL);
1132 ZwOpenKey(&KeyHandle, KEY_READ, &KeyAttributes);
1133 ZwClose(CurrentUserKey);
1134
1135 /* read the tile value in the registry */
1136 Status = ZwQueryValueKey(KeyHandle, &Tile, KeyValuePartialInformation,
1137 0, 0, &ResLength);
1138
1139 /* fall back to .DEFAULT if we didnt find values */
1140 if(Status == STATUS_INVALID_HANDLE)
1141 {
1142 RtlInitUnicodeString (&KeyPath,L"\\Registry\\User\\.Default\\Control Panel\\Desktop");
1143 InitializeObjectAttributes(&KeyAttributes, &KeyPath, OBJ_CASE_INSENSITIVE,
1144 NULL, NULL);
1145 ZwOpenKey(&KeyHandle, KEY_READ, &KeyAttributes);
1146 ZwQueryValueKey(KeyHandle, &Tile, KeyValuePartialInformation,
1147 0, 0, &ResLength);
1148 }
1149
1150 ResLength += sizeof(KEY_VALUE_PARTIAL_INFORMATION);
1151 KeyValuePartialInfo = ExAllocatePoolWithTag(PagedPool, ResLength, TAG_STRING);
1152 Length = ResLength;
1153
1154 if(!KeyValuePartialInfo)
1155 {
1156 NtClose(KeyHandle);
1157 return 0;
1158 }
1159
1160 Status = ZwQueryValueKey(KeyHandle, &Tile, KeyValuePartialInformation,
1161 (PVOID)KeyValuePartialInfo, Length, &ResLength);
1162 if(!NT_SUCCESS(Status) || (KeyValuePartialInfo->Type != REG_SZ))
1163 {
1164 ZwClose(KeyHandle);
1165 ExFreePool(KeyValuePartialInfo);
1166 return 0;
1167 }
1168
1169 Tile.Length = KeyValuePartialInfo->DataLength;
1170 Tile.MaximumLength = KeyValuePartialInfo->DataLength;
1171 Tile.Buffer = (PWSTR)KeyValuePartialInfo->Data;
1172
1173 Status = RtlUnicodeStringToInteger(&Tile, 0, &TileNum);
1174 if(!NT_SUCCESS(Status))
1175 {
1176 TileNum = 0;
1177 }
1178 ExFreePool(KeyValuePartialInfo);
1179
1180 /* start over again and look for the style*/
1181 ResLength = 0;
1182 Status = ZwQueryValueKey(KeyHandle, &Style, KeyValuePartialInformation,
1183 0, 0, &ResLength);
1184
1185 ResLength += sizeof(KEY_VALUE_PARTIAL_INFORMATION);
1186 KeyValuePartialInfo = ExAllocatePoolWithTag(PagedPool, ResLength, TAG_STRING);
1187 Length = ResLength;
1188
1189 if(!KeyValuePartialInfo)
1190 {
1191 ZwClose(KeyHandle);
1192 return 0;
1193 }
1194
1195 Status = ZwQueryValueKey(KeyHandle, &Style, KeyValuePartialInformation,
1196 (PVOID)KeyValuePartialInfo, Length, &ResLength);
1197 if(!NT_SUCCESS(Status) || (KeyValuePartialInfo->Type != REG_SZ))
1198 {
1199 ZwClose(KeyHandle);
1200 ExFreePool(KeyValuePartialInfo);
1201 return 0;
1202 }
1203
1204 Style.Length = KeyValuePartialInfo->DataLength;
1205 Style.MaximumLength = KeyValuePartialInfo->DataLength;
1206 Style.Buffer = (PWSTR)KeyValuePartialInfo->Data;
1207
1208 Status = RtlUnicodeStringToInteger(&Style, 0, &StyleNum);
1209 if(!NT_SUCCESS(Status))
1210 {
1211 StyleNum = 0;
1212 }
1213 ExFreePool(KeyValuePartialInfo);
1214
1215 /* Check the values we found in the registry */
1216 if(TileNum && !StyleNum)
1217 {
1218 WinStaObject->WallpaperMode = wmTile;
1219 }
1220 else if(!TileNum && StyleNum == 2)
1221 {
1222 WinStaObject->WallpaperMode = wmStretch;
1223 }
1224
1225 ZwClose(KeyHandle);
1226 break;
1227 }
1228 case SPI_GETDESKWALLPAPER:
1229 /* This function expects different parameters than the user mode version!
1230
1231 We basically return the current wallpaper handle - if any. The user
1232 mode version should load the string from the registry and return it
1233 without calling this function */
1234 ASSERT(pvParam);
1235 *(HBITMAP*)pvParam = (HBITMAP)WinStaObject->hbmWallpaper;
1236 break;
1237 }
1238
1239 /* FIXME save the value to the registry */
1240
1241 ObDereferenceObject(WinStaObject);
1242 return TRUE;
1243 }
1244 case SPI_SETWORKAREA:
1245 {
1246 RECT *rc;
1247 PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
1248
1249 if(!Desktop)
1250 {
1251 /* FIXME - Set last error */
1252 return FALSE;
1253 }
1254
1255 ASSERT(pvParam);
1256 rc = (RECT*)pvParam;
1257 Desktop->WorkArea = *rc;
1258
1259 return TRUE;
1260 }
1261 case SPI_GETWORKAREA:
1262 {
1263 PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
1264
1265 if(!Desktop)
1266 {
1267 /* FIXME - Set last error */
1268 return FALSE;
1269 }
1270
1271 ASSERT(pvParam);
1272 IntGetDesktopWorkArea(Desktop, (PRECT)pvParam);
1273
1274 return TRUE;
1275 }
1276 case SPI_SETGRADIENTCAPTIONS:
1277 {
1278 GradientCaptions = (pvParam != NULL);
1279 /* FIXME - should be checked if the color depth is higher than 8bpp? */
1280 return TRUE;
1281 }
1282 case SPI_GETGRADIENTCAPTIONS:
1283 {
1284 HDC hDC;
1285 BOOL Ret = GradientCaptions;
1286
1287 hDC = IntGetScreenDC();
1288 if(hDC)
1289 {
1290 Ret = (NtGdiGetDeviceCaps(hDC, BITSPIXEL) > 8) && Ret;
1291
1292 ASSERT(pvParam);
1293 *((PBOOL)pvParam) = Ret;
1294 return TRUE;
1295 }
1296 return FALSE;
1297 }
1298 case SPI_SETFONTSMOOTHING:
1299 {
1300 IntEnableFontRendering(uiParam != 0);
1301 return TRUE;
1302 }
1303 case SPI_GETFONTSMOOTHING:
1304 {
1305 ASSERT(pvParam);
1306 *((BOOL*)pvParam) = IntIsFontRenderingEnabled();
1307 return TRUE;
1308 }
1309 case SPI_GETICONTITLELOGFONT:
1310 {
1311 ASSERT(pvParam);
1312 *((LOGFONTW*)pvParam) = IconFont;
1313 return TRUE;
1314 }
1315 case SPI_GETNONCLIENTMETRICS:
1316 {
1317 ASSERT(pvParam);
1318 *((NONCLIENTMETRICSW*)pvParam) = pMetrics;
1319 return TRUE;
1320 }
1321 case SPI_GETFOCUSBORDERHEIGHT:
1322 {
1323 ASSERT(pvParam);
1324 *((UINT*)pvParam) = FocusBorderHeight;
1325 return TRUE;
1326 }
1327 case SPI_GETFOCUSBORDERWIDTH:
1328 {
1329 ASSERT(pvParam);
1330 *((UINT*)pvParam) = FocusBorderWidth;
1331 return TRUE;
1332 }
1333 case SPI_SETFOCUSBORDERHEIGHT:
1334 {
1335 FocusBorderHeight = (UINT)pvParam;
1336 return TRUE;
1337 }
1338 case SPI_SETFOCUSBORDERWIDTH:
1339 {
1340 FocusBorderWidth = (UINT)pvParam;
1341 return TRUE;
1342 }
1343
1344 default:
1345 {
1346 DPRINT1("SystemParametersInfo: Unsupported Action 0x%x (uiParam: 0x%x, pvParam: 0x%x, fWinIni: 0x%x)\n",
1347 uiAction, uiParam, pvParam, fWinIni);
1348 return FALSE;
1349 }
1350 }
1351 return FALSE;
1352 }
1353
1354 /*
1355 * @implemented
1356 */
1357 BOOL FASTCALL
1358 UserSystemParametersInfo(
1359 UINT uiAction,
1360 UINT uiParam,
1361 PVOID pvParam,
1362 UINT fWinIni)
1363 {
1364 NTSTATUS Status;
1365
1366 switch(uiAction)
1367 {
1368 case SPI_SETDOUBLECLKWIDTH:
1369 case SPI_SETDOUBLECLKHEIGHT:
1370 case SPI_SETDOUBLECLICKTIME:
1371 case SPI_SETGRADIENTCAPTIONS:
1372 case SPI_SETFONTSMOOTHING:
1373 case SPI_SETFOCUSBORDERHEIGHT:
1374 case SPI_SETFOCUSBORDERWIDTH:
1375 {
1376 return (DWORD)IntSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni);
1377 }
1378 case SPI_SETWORKAREA:
1379 {
1380 RECT rc;
1381 Status = MmCopyFromCaller(&rc, (PRECT)pvParam, sizeof(RECT));
1382 if(!NT_SUCCESS(Status))
1383 {
1384 SetLastNtError(Status);
1385 return( FALSE);
1386 }
1387 return( (DWORD)IntSystemParametersInfo(uiAction, uiParam, &rc, fWinIni));
1388 }
1389 case SPI_GETWORKAREA:
1390 {
1391 RECT rc;
1392
1393 if(!IntSystemParametersInfo(uiAction, uiParam, &rc, fWinIni))
1394 {
1395 return( FALSE);
1396 }
1397
1398 Status = MmCopyToCaller((PRECT)pvParam, &rc, sizeof(RECT));
1399 if(!NT_SUCCESS(Status))
1400 {
1401 SetLastNtError(Status);
1402 return( FALSE);
1403 }
1404 return( TRUE);
1405 }
1406 case SPI_GETFONTSMOOTHING:
1407 case SPI_GETGRADIENTCAPTIONS:
1408 case SPI_GETFOCUSBORDERHEIGHT:
1409 case SPI_GETFOCUSBORDERWIDTH:
1410 case SPI_GETWHEELSCROLLLINES:
1411 case SPI_GETWHEELSCROLLCHARS:
1412 case SPI_GETSCREENSAVERRUNNING:
1413 case SPI_SETSCREENSAVERRUNNING:
1414 case SPI_GETSCREENSAVETIMEOUT:
1415 case SPI_SETSCREENSAVETIMEOUT:
1416 case SPI_GETFLATMENU:
1417 case SPI_SETFLATMENU:
1418 {
1419 BOOL Ret;
1420
1421 if(!IntSystemParametersInfo(uiAction, uiParam, &Ret, fWinIni))
1422 {
1423 return( FALSE);
1424 }
1425
1426 Status = MmCopyToCaller(pvParam, &Ret, sizeof(BOOL));
1427 if(!NT_SUCCESS(Status))
1428 {
1429 SetLastNtError(Status);
1430 return( FALSE);
1431 }
1432 return( TRUE);
1433 }
1434 case SPI_SETDESKWALLPAPER:
1435 {
1436 /* !!! As opposed to the user mode version this version accepts a handle
1437 to the bitmap! */
1438 HBITMAP hbmWallpaper;
1439
1440 Status = MmCopyFromCaller(&hbmWallpaper, pvParam, sizeof(HBITMAP));
1441 if(!NT_SUCCESS(Status))
1442 {
1443 SetLastNtError(Status);
1444 return( FALSE);
1445 }
1446 return( IntSystemParametersInfo(SPI_SETDESKWALLPAPER, 0, &hbmWallpaper, fWinIni));
1447 }
1448 case SPI_GETDESKWALLPAPER:
1449 {
1450 /* !!! As opposed to the user mode version this version returns a handle
1451 to the bitmap! */
1452 HBITMAP hbmWallpaper;
1453 BOOL Ret;
1454
1455 Ret = IntSystemParametersInfo(SPI_GETDESKWALLPAPER, 0, &hbmWallpaper, fWinIni);
1456
1457 Status = MmCopyToCaller(pvParam, &hbmWallpaper, sizeof(HBITMAP));
1458 if(!NT_SUCCESS(Status))
1459 {
1460 SetLastNtError(Status);
1461 return( FALSE);
1462 }
1463 return( Ret);
1464 }
1465 case SPI_GETICONTITLELOGFONT:
1466 {
1467 LOGFONTW IconFont;
1468
1469 if(!IntSystemParametersInfo(uiAction, uiParam, &IconFont, fWinIni))
1470 {
1471 return( FALSE);
1472 }
1473
1474 Status = MmCopyToCaller(pvParam, &IconFont, sizeof(LOGFONTW));
1475 if(!NT_SUCCESS(Status))
1476 {
1477 SetLastNtError(Status);
1478 return( FALSE);
1479 }
1480 return( TRUE);
1481 }
1482 case SPI_GETNONCLIENTMETRICS:
1483 {
1484 NONCLIENTMETRICSW metrics;
1485
1486 Status = MmCopyFromCaller(&metrics.cbSize, pvParam, sizeof(UINT));
1487 if(!NT_SUCCESS(Status))
1488 {
1489 SetLastNtError(Status);
1490 return( FALSE);
1491 }
1492 if(metrics.cbSize != sizeof(NONCLIENTMETRICSW))
1493 {
1494 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1495 return( FALSE);
1496 }
1497
1498 if(!IntSystemParametersInfo(uiAction, uiParam, &metrics, fWinIni))
1499 {
1500 return( FALSE);
1501 }
1502
1503 Status = MmCopyToCaller(pvParam, &metrics.cbSize, sizeof(NONCLIENTMETRICSW));
1504 if(!NT_SUCCESS(Status))
1505 {
1506 SetLastNtError(Status);
1507 return( FALSE);
1508 }
1509 return( TRUE);
1510 }
1511 default :
1512 {
1513 DPRINT1("UserSystemParametersInfo : uiAction = %x \n",uiAction );
1514 break;
1515 }
1516 }
1517 return( FALSE);
1518 }
1519
1520
1521
1522
1523 /*
1524 * @implemented
1525 */
1526 BOOL
1527 STDCALL
1528 NtUserSystemParametersInfo(
1529 UINT uiAction,
1530 UINT uiParam,
1531 PVOID pvParam,
1532 UINT fWinIni)
1533 {
1534 DECLARE_RETURN(BOOLEAN);
1535
1536 DPRINT("Enter NtUserSystemParametersInfo\n");
1537 UserEnterExclusive();
1538
1539 RETURN( UserSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni));
1540
1541 CLEANUP:
1542 DPRINT("Leave NtUserSystemParametersInfo, ret=%i\n",_ret_);
1543 UserLeave();
1544 END_CLEANUP;
1545 }
1546
1547
1548
1549 UINT
1550 STDCALL
1551 NtUserGetDoubleClickTime(VOID)
1552 {
1553 UINT Result;
1554 NTSTATUS Status;
1555 PWINSTATION_OBJECT WinStaObject;
1556 PSYSTEM_CURSORINFO CurInfo;
1557 DECLARE_RETURN(UINT);
1558
1559 DPRINT("Enter NtUserGetDoubleClickTime\n");
1560 UserEnterShared();
1561
1562 Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
1563 KernelMode,
1564 0,
1565 &WinStaObject);
1566 if (!NT_SUCCESS(Status))
1567 RETURN( (DWORD)FALSE);
1568
1569 CurInfo = IntGetSysCursorInfo(WinStaObject);
1570 Result = CurInfo->DblClickSpeed;
1571
1572 ObDereferenceObject(WinStaObject);
1573 RETURN( Result);
1574
1575 CLEANUP:
1576 DPRINT("Leave NtUserGetDoubleClickTime, ret=%i\n",_ret_);
1577 UserLeave();
1578 END_CLEANUP;
1579 }
1580
1581 BOOL
1582 STDCALL
1583 NtUserGetGUIThreadInfo(
1584 DWORD idThread, /* if NULL use foreground thread */
1585 LPGUITHREADINFO lpgui)
1586 {
1587 NTSTATUS Status;
1588 PTHRDCARETINFO CaretInfo;
1589 GUITHREADINFO SafeGui;
1590 PDESKTOP_OBJECT Desktop;
1591 PUSER_MESSAGE_QUEUE MsgQueue;
1592 PETHREAD Thread = NULL;
1593 DECLARE_RETURN(BOOLEAN);
1594
1595 DPRINT("Enter NtUserGetGUIThreadInfo\n");
1596 UserEnterShared();
1597
1598 Status = MmCopyFromCaller(&SafeGui, lpgui, sizeof(DWORD));
1599 if(!NT_SUCCESS(Status))
1600 {
1601 SetLastNtError(Status);
1602 RETURN( FALSE);
1603 }
1604
1605 if(SafeGui.cbSize != sizeof(GUITHREADINFO))
1606 {
1607 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1608 RETURN( FALSE);
1609 }
1610
1611 if(idThread)
1612 {
1613 Status = PsLookupThreadByThreadId((HANDLE)idThread, &Thread);
1614 if(!NT_SUCCESS(Status))
1615 {
1616 SetLastWin32Error(ERROR_ACCESS_DENIED);
1617 RETURN( FALSE);
1618 }
1619 Desktop = ((PW32THREAD)Thread->Tcb.Win32Thread)->Desktop;
1620 }
1621 else
1622 {
1623 /* get the foreground thread */
1624 PW32THREAD W32Thread = (PW32THREAD)PsGetCurrentThread()->Tcb.Win32Thread;
1625 Desktop = W32Thread->Desktop;
1626 if(Desktop)
1627 {
1628 MsgQueue = Desktop->ActiveMessageQueue;
1629 if(MsgQueue)
1630 {
1631 Thread = MsgQueue->Thread;
1632 }
1633 }
1634 }
1635
1636 if(!Thread || !Desktop)
1637 {
1638 if(idThread && Thread)
1639 ObDereferenceObject(Thread);
1640 SetLastWin32Error(ERROR_ACCESS_DENIED);
1641 RETURN( FALSE);
1642 }
1643
1644 MsgQueue = (PUSER_MESSAGE_QUEUE)Desktop->ActiveMessageQueue;
1645 CaretInfo = MsgQueue->CaretInfo;
1646
1647 SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0);
1648 if(MsgQueue->MenuOwner)
1649 SafeGui.flags |= GUI_INMENUMODE | MsgQueue->MenuState;
1650 if(MsgQueue->MoveSize)
1651 SafeGui.flags |= GUI_INMOVESIZE;
1652
1653 /* FIXME add flag GUI_16BITTASK */
1654
1655 SafeGui.hwndActive = MsgQueue->ActiveWindow;
1656 SafeGui.hwndFocus = MsgQueue->FocusWindow;
1657 SafeGui.hwndCapture = MsgQueue->CaptureWindow;
1658 SafeGui.hwndMenuOwner = MsgQueue->MenuOwner;
1659 SafeGui.hwndMoveSize = MsgQueue->MoveSize;
1660 SafeGui.hwndCaret = CaretInfo->hWnd;
1661
1662 SafeGui.rcCaret.left = CaretInfo->Pos.x;
1663 SafeGui.rcCaret.top = CaretInfo->Pos.y;
1664 SafeGui.rcCaret.right = SafeGui.rcCaret.left + CaretInfo->Size.cx;
1665 SafeGui.rcCaret.bottom = SafeGui.rcCaret.top + CaretInfo->Size.cy;
1666
1667 if(idThread)
1668 ObDereferenceObject(Thread);
1669
1670 Status = MmCopyToCaller(lpgui, &SafeGui, sizeof(GUITHREADINFO));
1671 if(!NT_SUCCESS(Status))
1672 {
1673 SetLastNtError(Status);
1674 RETURN( FALSE);
1675 }
1676
1677 RETURN( TRUE);
1678
1679 CLEANUP:
1680 DPRINT("Leave NtUserGetGUIThreadInfo, ret=%i\n",_ret_);
1681 UserLeave();
1682 END_CLEANUP;
1683 }
1684
1685
1686 DWORD
1687 STDCALL
1688 NtUserGetGuiResources(
1689 HANDLE hProcess,
1690 DWORD uiFlags)
1691 {
1692 PEPROCESS Process;
1693 PW32PROCESS W32Process;
1694 NTSTATUS Status;
1695 DWORD Ret = 0;
1696 DECLARE_RETURN(DWORD);
1697
1698 DPRINT("Enter NtUserGetGuiResources\n");
1699 UserEnterShared();
1700
1701 Status = ObReferenceObjectByHandle(hProcess,
1702 PROCESS_QUERY_INFORMATION,
1703 PsProcessType,
1704 ExGetPreviousMode(),
1705 (PVOID*)&Process,
1706 NULL);
1707
1708 if(!NT_SUCCESS(Status))
1709 {
1710 SetLastNtError(Status);
1711 RETURN( 0);
1712 }
1713
1714 W32Process = (PW32PROCESS)Process->Win32Process;
1715 if(!W32Process)
1716 {
1717 ObDereferenceObject(Process);
1718 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1719 RETURN( 0);
1720 }
1721
1722 switch(uiFlags)
1723 {
1724 case GR_GDIOBJECTS:
1725 {
1726 Ret = (DWORD)W32Process->GDIObjects;
1727 break;
1728 }
1729 case GR_USEROBJECTS:
1730 {
1731 Ret = (DWORD)W32Process->UserObjects;
1732 break;
1733 }
1734 default:
1735 {
1736 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1737 break;
1738 }
1739 }
1740
1741 ObDereferenceObject(Process);
1742
1743 RETURN( Ret);
1744
1745 CLEANUP:
1746 DPRINT("Leave NtUserGetGuiResources, ret=%i\n",_ret_);
1747 UserLeave();
1748 END_CLEANUP;
1749 }
1750
1751 NTSTATUS FASTCALL
1752 IntSafeCopyUnicodeString(PUNICODE_STRING Dest,
1753 PUNICODE_STRING Source)
1754 {
1755 NTSTATUS Status;
1756 PWSTR Src;
1757
1758 Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING));
1759 if(!NT_SUCCESS(Status))
1760 {
1761 return Status;
1762 }
1763
1764 if(Dest->Length > 0x4000)
1765 {
1766 return STATUS_UNSUCCESSFUL;
1767 }
1768
1769 Src = Dest->Buffer;
1770 Dest->Buffer = NULL;
1771
1772 if(Dest->Length > 0 && Src)
1773 {
1774 Dest->MaximumLength = Dest->Length;
1775 Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING);
1776 if(!Dest->Buffer)
1777 {
1778 return STATUS_NO_MEMORY;
1779 }
1780
1781 Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length);
1782 if(!NT_SUCCESS(Status))
1783 {
1784 ExFreePool(Dest->Buffer);
1785 Dest->Buffer = NULL;
1786 return Status;
1787 }
1788
1789
1790 return STATUS_SUCCESS;
1791 }
1792
1793 /* string is empty */
1794 return STATUS_SUCCESS;
1795 }
1796
1797 NTSTATUS FASTCALL
1798 IntSafeCopyUnicodeStringTerminateNULL(PUNICODE_STRING Dest,
1799 PUNICODE_STRING Source)
1800 {
1801 NTSTATUS Status;
1802 PWSTR Src;
1803
1804 Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING));
1805 if(!NT_SUCCESS(Status))
1806 {
1807 return Status;
1808 }
1809
1810 if(Dest->Length > 0x4000)
1811 {
1812 return STATUS_UNSUCCESSFUL;
1813 }
1814
1815 Src = Dest->Buffer;
1816 Dest->Buffer = NULL;
1817
1818 if(Dest->Length > 0 && Src)
1819 {
1820 Dest->MaximumLength = Dest->Length + sizeof(WCHAR);
1821 Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING);
1822 if(!Dest->Buffer)
1823 {
1824 return STATUS_NO_MEMORY;
1825 }
1826
1827 Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length);
1828 if(!NT_SUCCESS(Status))
1829 {
1830 ExFreePool(Dest->Buffer);
1831 Dest->Buffer = NULL;
1832 return Status;
1833 }
1834
1835 /* make sure the string is null-terminated */
1836 Src = (PWSTR)((PBYTE)Dest->Buffer + Dest->Length);
1837 *Src = L'\0';
1838
1839 return STATUS_SUCCESS;
1840 }
1841
1842 /* string is empty */
1843 return STATUS_SUCCESS;
1844 }
1845
1846 NTSTATUS FASTCALL
1847 IntUnicodeStringToNULLTerminated(PWSTR *Dest, PUNICODE_STRING Src)
1848 {
1849 if (Src->Length + sizeof(WCHAR) <= Src->MaximumLength
1850 && L'\0' == Src->Buffer[Src->Length / sizeof(WCHAR)])
1851 {
1852 /* The unicode_string is already nul terminated. Just reuse it. */
1853 *Dest = Src->Buffer;
1854 return STATUS_SUCCESS;
1855 }
1856
1857 *Dest = ExAllocatePoolWithTag(PagedPool, Src->Length + sizeof(WCHAR), TAG_STRING);
1858 if (NULL == *Dest)
1859 {
1860 return STATUS_NO_MEMORY;
1861 }
1862 RtlCopyMemory(*Dest, Src->Buffer, Src->Length);
1863 (*Dest)[Src->Length / 2] = L'\0';
1864
1865 return STATUS_SUCCESS;
1866 }
1867
1868 void FASTCALL
1869 IntFreeNULLTerminatedFromUnicodeString(PWSTR NullTerminated, PUNICODE_STRING UnicodeString)
1870 {
1871 if (NullTerminated != UnicodeString->Buffer)
1872 {
1873 ExFreePool(NullTerminated);
1874 }
1875 }
1876
1877 BOOL STDCALL
1878 NtUserUpdatePerUserSystemParameters(
1879 DWORD dwReserved,
1880 BOOL bEnable)
1881 {
1882 BOOL Result = TRUE;
1883 DECLARE_RETURN(BOOLEAN);
1884
1885 DPRINT("Enter NtUserUpdatePerUserSystemParameters\n");
1886 UserEnterExclusive();
1887
1888 Result &= IntDesktopUpdatePerUserSettings(bEnable);
1889 RETURN( Result);
1890
1891 CLEANUP:
1892 DPRINT("Leave NtUserUpdatePerUserSystemParameters, ret=%i\n",_ret_);
1893 UserLeave();
1894 END_CLEANUP;
1895 }
1896
1897 PW32PROCESSINFO
1898 GetW32ProcessInfo(VOID)
1899 {
1900 PW32PROCESSINFO pi;
1901 PW32PROCESS W32Process = PsGetWin32Process();
1902
1903 if (W32Process == NULL)
1904 {
1905 /* FIXME - temporary hack for system threads... */
1906 return NULL;
1907 }
1908
1909 if (W32Process->ProcessInfo == NULL)
1910 {
1911 pi = UserHeapAlloc(sizeof(W32PROCESSINFO));
1912 if (pi != NULL)
1913 {
1914 RtlZeroMemory(pi,
1915 sizeof(W32PROCESSINFO));
1916
1917 /* initialize it */
1918 pi->UserHandleTable = gHandleTable;
1919
1920 if (InterlockedCompareExchangePointer(&W32Process->ProcessInfo,
1921 pi,
1922 NULL) != NULL)
1923 {
1924 UserHeapFree(pi);
1925 }
1926 }
1927 else
1928 {
1929 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
1930 }
1931 }
1932
1933 return W32Process->ProcessInfo;
1934 }
1935
1936 PW32THREADINFO
1937 GetW32ThreadInfo(VOID)
1938 {
1939 PTEB Teb;
1940 PW32THREADINFO ti;
1941 PW32THREAD W32Thread = PsGetWin32Thread();
1942
1943 if (W32Thread == NULL)
1944 {
1945 /* FIXME - temporary hack for system threads... */
1946 return NULL;
1947 }
1948
1949 /* allocate a W32THREAD structure if neccessary */
1950 if (W32Thread->ThreadInfo == NULL)
1951 {
1952 ti = UserHeapAlloc(sizeof(W32THREADINFO));
1953 if (ti != NULL)
1954 {
1955 RtlZeroMemory(ti,
1956 sizeof(W32THREADINFO));
1957
1958 /* initialize it */
1959 ti->kpi = GetW32ProcessInfo();
1960 ti->pi = UserHeapAddressToUser(ti->kpi);
1961 if (W32Thread->Desktop != NULL)
1962 {
1963 ti->Desktop = W32Thread->Desktop->DesktopInfo;
1964 ti->DesktopHeapDelta = DesktopHeapGetUserDelta();
1965 }
1966 else
1967 {
1968 ti->Desktop = NULL;
1969 ti->DesktopHeapDelta = 0;
1970 }
1971
1972 W32Thread->ThreadInfo = ti;
1973 /* update the TEB */
1974 Teb = NtCurrentTeb();
1975 _SEH_TRY
1976 {
1977 ProbeForWrite(Teb,
1978 sizeof(TEB),
1979 sizeof(ULONG));
1980
1981 Teb->Win32ThreadInfo = UserHeapAddressToUser(W32Thread->ThreadInfo);
1982 }
1983 _SEH_HANDLE
1984 {
1985 SetLastNtError(_SEH_GetExceptionCode());
1986 }
1987 _SEH_END;
1988 }
1989 else
1990 {
1991 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
1992 }
1993 }
1994
1995 return W32Thread->ThreadInfo;
1996 }
1997
1998
1999 /* EOF */