Fixing a small bug, value where never devliver from SPI and that did make screensaver...
[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 return TRUE;
1025 break;
1026 case SPI_GETSCREENSAVETIMEOUT:
1027 if (pvParam != NULL) *((UINT*)pvParam) = WinStaObject->ScreenSaverTimeOut;
1028 return TRUE;
1029 break;
1030 case SPI_SETSCREENSAVETIMEOUT:
1031 WinStaObject->ScreenSaverTimeOut = uiParam;
1032 return TRUE;
1033 break;
1034 case SPI_GETSCREENSAVERRUNNING:
1035 if (pvParam != NULL) *((BOOL*)pvParam) = WinStaObject->ScreenSaverRunning;
1036 return TRUE;
1037 break;
1038 case SPI_SETSCREENSAVERRUNNING:
1039 if (pvParam != NULL) *((BOOL*)pvParam) = WinStaObject->ScreenSaverRunning;
1040 WinStaObject->ScreenSaverRunning = uiParam;
1041 return TRUE;
1042 break;
1043 case SPI_GETWHEELSCROLLLINES:
1044 CurInfo = IntGetSysCursorInfo(WinStaObject);
1045 if (pvParam != NULL) *((UINT*)pvParam) = CurInfo->WheelScroLines;
1046 /* FIXME add this value to scroll list as scroll value ?? */
1047 return TRUE;
1048 break;
1049 case SPI_GETWHEELSCROLLCHARS:
1050 CurInfo = IntGetSysCursorInfo(WinStaObject);
1051 if (pvParam != NULL) *((UINT*)pvParam) = CurInfo->WheelScroChars;
1052 // FIXME add this value to scroll list as scroll value ??
1053 return TRUE;
1054 break;
1055 case SPI_SETDOUBLECLKWIDTH:
1056 CurInfo = IntGetSysCursorInfo(WinStaObject);
1057 /* FIXME limit the maximum value? */
1058 CurInfo->DblClickWidth = uiParam;
1059 break;
1060 case SPI_SETDOUBLECLKHEIGHT:
1061 CurInfo = IntGetSysCursorInfo(WinStaObject);
1062 /* FIXME limit the maximum value? */
1063 CurInfo->DblClickHeight = uiParam;
1064 break;
1065 case SPI_SETDOUBLECLICKTIME:
1066 CurInfo = IntGetSysCursorInfo(WinStaObject);
1067 /* FIXME limit the maximum time to 1000 ms? */
1068 CurInfo->DblClickSpeed = uiParam;
1069 break;
1070 case SPI_SETDESKWALLPAPER:
1071 {
1072 /* This function expects different parameters than the user mode version!
1073
1074 We let the user mode code load the bitmap, it passed the handle to
1075 the bitmap. We'll change it's ownership to system and replace it with
1076 the current wallpaper bitmap */
1077 HBITMAP hOldBitmap, hNewBitmap;
1078 UNICODE_STRING Key = RTL_CONSTANT_STRING(L"Control Panel\\Desktop");
1079 UNICODE_STRING Tile = RTL_CONSTANT_STRING(L"TileWallpaper");
1080 UNICODE_STRING Style = RTL_CONSTANT_STRING(L"WallpaperStyle");
1081 UNICODE_STRING KeyPath;
1082 OBJECT_ATTRIBUTES KeyAttributes;
1083 OBJECT_ATTRIBUTES ObjectAttributes;
1084 NTSTATUS Status;
1085 HANDLE CurrentUserKey = NULL;
1086 HANDLE KeyHandle = NULL;
1087 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
1088 ULONG Length = 0;
1089 ULONG ResLength = 0;
1090 ULONG TileNum = 0;
1091 ULONG StyleNum = 0;
1092 ASSERT(pvParam);
1093
1094 hNewBitmap = *(HBITMAP*)pvParam;
1095 if(hNewBitmap != NULL)
1096 {
1097 BITMAPOBJ *bmp;
1098 /* try to get the size of the wallpaper */
1099 if(!(bmp = BITMAPOBJ_LockBitmap(hNewBitmap)))
1100 {
1101 ObDereferenceObject(WinStaObject);
1102 return FALSE;
1103 }
1104 WinStaObject->cxWallpaper = bmp->SurfObj.sizlBitmap.cx;
1105 WinStaObject->cyWallpaper = bmp->SurfObj.sizlBitmap.cy;
1106
1107 BITMAPOBJ_UnlockBitmap(bmp);
1108
1109 /* change the bitmap's ownership */
1110 GDIOBJ_SetOwnership(GdiHandleTable, hNewBitmap, NULL);
1111 }
1112 hOldBitmap = (HBITMAP)InterlockedExchange((LONG*)&WinStaObject->hbmWallpaper, (LONG)hNewBitmap);
1113 if(hOldBitmap != NULL)
1114 {
1115 /* delete the old wallpaper */
1116 NtGdiDeleteObject(hOldBitmap);
1117 }
1118
1119 /* Set the style */
1120
1121 /*default value is center */
1122 WinStaObject->WallpaperMode = wmCenter;
1123
1124
1125
1126 /* Get a handle to the current users settings */
1127 RtlFormatCurrentUserKeyPath(&KeyPath);
1128 InitializeObjectAttributes(&ObjectAttributes,&KeyPath,OBJ_CASE_INSENSITIVE,NULL,NULL);
1129 ZwOpenKey(&CurrentUserKey, KEY_READ, &ObjectAttributes);
1130 RtlFreeUnicodeString(&KeyPath);
1131
1132 /* open up the settings to read the values */
1133 InitializeObjectAttributes(&KeyAttributes, &Key, OBJ_CASE_INSENSITIVE,
1134 CurrentUserKey, NULL);
1135 ZwOpenKey(&KeyHandle, KEY_READ, &KeyAttributes);
1136 ZwClose(CurrentUserKey);
1137
1138 /* read the tile value in the registry */
1139 Status = ZwQueryValueKey(KeyHandle, &Tile, KeyValuePartialInformation,
1140 0, 0, &ResLength);
1141
1142 /* fall back to .DEFAULT if we didnt find values */
1143 if(Status == STATUS_INVALID_HANDLE)
1144 {
1145 RtlInitUnicodeString (&KeyPath,L"\\Registry\\User\\.Default\\Control Panel\\Desktop");
1146 InitializeObjectAttributes(&KeyAttributes, &KeyPath, OBJ_CASE_INSENSITIVE,
1147 NULL, NULL);
1148 ZwOpenKey(&KeyHandle, KEY_READ, &KeyAttributes);
1149 ZwQueryValueKey(KeyHandle, &Tile, KeyValuePartialInformation,
1150 0, 0, &ResLength);
1151 }
1152
1153 ResLength += sizeof(KEY_VALUE_PARTIAL_INFORMATION);
1154 KeyValuePartialInfo = ExAllocatePoolWithTag(PagedPool, ResLength, TAG_STRING);
1155 Length = ResLength;
1156
1157 if(!KeyValuePartialInfo)
1158 {
1159 NtClose(KeyHandle);
1160 return 0;
1161 }
1162
1163 Status = ZwQueryValueKey(KeyHandle, &Tile, KeyValuePartialInformation,
1164 (PVOID)KeyValuePartialInfo, Length, &ResLength);
1165 if(!NT_SUCCESS(Status) || (KeyValuePartialInfo->Type != REG_SZ))
1166 {
1167 ZwClose(KeyHandle);
1168 ExFreePool(KeyValuePartialInfo);
1169 return 0;
1170 }
1171
1172 Tile.Length = KeyValuePartialInfo->DataLength;
1173 Tile.MaximumLength = KeyValuePartialInfo->DataLength;
1174 Tile.Buffer = (PWSTR)KeyValuePartialInfo->Data;
1175
1176 Status = RtlUnicodeStringToInteger(&Tile, 0, &TileNum);
1177 if(!NT_SUCCESS(Status))
1178 {
1179 TileNum = 0;
1180 }
1181 ExFreePool(KeyValuePartialInfo);
1182
1183 /* start over again and look for the style*/
1184 ResLength = 0;
1185 Status = ZwQueryValueKey(KeyHandle, &Style, KeyValuePartialInformation,
1186 0, 0, &ResLength);
1187
1188 ResLength += sizeof(KEY_VALUE_PARTIAL_INFORMATION);
1189 KeyValuePartialInfo = ExAllocatePoolWithTag(PagedPool, ResLength, TAG_STRING);
1190 Length = ResLength;
1191
1192 if(!KeyValuePartialInfo)
1193 {
1194 ZwClose(KeyHandle);
1195 return 0;
1196 }
1197
1198 Status = ZwQueryValueKey(KeyHandle, &Style, KeyValuePartialInformation,
1199 (PVOID)KeyValuePartialInfo, Length, &ResLength);
1200 if(!NT_SUCCESS(Status) || (KeyValuePartialInfo->Type != REG_SZ))
1201 {
1202 ZwClose(KeyHandle);
1203 ExFreePool(KeyValuePartialInfo);
1204 return 0;
1205 }
1206
1207 Style.Length = KeyValuePartialInfo->DataLength;
1208 Style.MaximumLength = KeyValuePartialInfo->DataLength;
1209 Style.Buffer = (PWSTR)KeyValuePartialInfo->Data;
1210
1211 Status = RtlUnicodeStringToInteger(&Style, 0, &StyleNum);
1212 if(!NT_SUCCESS(Status))
1213 {
1214 StyleNum = 0;
1215 }
1216 ExFreePool(KeyValuePartialInfo);
1217
1218 /* Check the values we found in the registry */
1219 if(TileNum && !StyleNum)
1220 {
1221 WinStaObject->WallpaperMode = wmTile;
1222 }
1223 else if(!TileNum && StyleNum == 2)
1224 {
1225 WinStaObject->WallpaperMode = wmStretch;
1226 }
1227
1228 ZwClose(KeyHandle);
1229 break;
1230 }
1231 case SPI_GETDESKWALLPAPER:
1232 /* This function expects different parameters than the user mode version!
1233
1234 We basically return the current wallpaper handle - if any. The user
1235 mode version should load the string from the registry and return it
1236 without calling this function */
1237 ASSERT(pvParam);
1238 *(HBITMAP*)pvParam = (HBITMAP)WinStaObject->hbmWallpaper;
1239 break;
1240 }
1241
1242 /* FIXME save the value to the registry */
1243
1244 ObDereferenceObject(WinStaObject);
1245 return TRUE;
1246 }
1247 case SPI_SETWORKAREA:
1248 {
1249 RECT *rc;
1250 PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
1251
1252 if(!Desktop)
1253 {
1254 /* FIXME - Set last error */
1255 return FALSE;
1256 }
1257
1258 ASSERT(pvParam);
1259 rc = (RECT*)pvParam;
1260 Desktop->WorkArea = *rc;
1261
1262 return TRUE;
1263 }
1264 case SPI_GETWORKAREA:
1265 {
1266 PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
1267
1268 if(!Desktop)
1269 {
1270 /* FIXME - Set last error */
1271 return FALSE;
1272 }
1273
1274 ASSERT(pvParam);
1275 IntGetDesktopWorkArea(Desktop, (PRECT)pvParam);
1276
1277 return TRUE;
1278 }
1279 case SPI_SETGRADIENTCAPTIONS:
1280 {
1281 GradientCaptions = (pvParam != NULL);
1282 /* FIXME - should be checked if the color depth is higher than 8bpp? */
1283 return TRUE;
1284 }
1285 case SPI_GETGRADIENTCAPTIONS:
1286 {
1287 HDC hDC;
1288 BOOL Ret = GradientCaptions;
1289
1290 hDC = IntGetScreenDC();
1291 if(hDC)
1292 {
1293 Ret = (NtGdiGetDeviceCaps(hDC, BITSPIXEL) > 8) && Ret;
1294
1295 ASSERT(pvParam);
1296 *((PBOOL)pvParam) = Ret;
1297 return TRUE;
1298 }
1299 return FALSE;
1300 }
1301 case SPI_SETFONTSMOOTHING:
1302 {
1303 IntEnableFontRendering(uiParam != 0);
1304 return TRUE;
1305 }
1306 case SPI_GETFONTSMOOTHING:
1307 {
1308 ASSERT(pvParam);
1309 *((BOOL*)pvParam) = IntIsFontRenderingEnabled();
1310 return TRUE;
1311 }
1312 case SPI_GETICONTITLELOGFONT:
1313 {
1314 ASSERT(pvParam);
1315 *((LOGFONTW*)pvParam) = IconFont;
1316 return TRUE;
1317 }
1318 case SPI_GETNONCLIENTMETRICS:
1319 {
1320 ASSERT(pvParam);
1321 *((NONCLIENTMETRICSW*)pvParam) = pMetrics;
1322 return TRUE;
1323 }
1324 case SPI_GETFOCUSBORDERHEIGHT:
1325 {
1326 ASSERT(pvParam);
1327 *((UINT*)pvParam) = FocusBorderHeight;
1328 return TRUE;
1329 }
1330 case SPI_GETFOCUSBORDERWIDTH:
1331 {
1332 ASSERT(pvParam);
1333 *((UINT*)pvParam) = FocusBorderWidth;
1334 return TRUE;
1335 }
1336 case SPI_SETFOCUSBORDERHEIGHT:
1337 {
1338 FocusBorderHeight = (UINT)pvParam;
1339 return TRUE;
1340 }
1341 case SPI_SETFOCUSBORDERWIDTH:
1342 {
1343 FocusBorderWidth = (UINT)pvParam;
1344 return TRUE;
1345 }
1346
1347 default:
1348 {
1349 DPRINT1("SystemParametersInfo: Unsupported Action 0x%x (uiParam: 0x%x, pvParam: 0x%x, fWinIni: 0x%x)\n",
1350 uiAction, uiParam, pvParam, fWinIni);
1351 return FALSE;
1352 }
1353 }
1354 return FALSE;
1355 }
1356
1357 /*
1358 * @implemented
1359 */
1360 BOOL FASTCALL
1361 UserSystemParametersInfo(
1362 UINT uiAction,
1363 UINT uiParam,
1364 PVOID pvParam,
1365 UINT fWinIni)
1366 {
1367 NTSTATUS Status;
1368
1369 switch(uiAction)
1370 {
1371 case SPI_SETDOUBLECLKWIDTH:
1372 case SPI_SETDOUBLECLKHEIGHT:
1373 case SPI_SETDOUBLECLICKTIME:
1374 case SPI_SETGRADIENTCAPTIONS:
1375 case SPI_SETFONTSMOOTHING:
1376 case SPI_SETFOCUSBORDERHEIGHT:
1377 case SPI_SETFOCUSBORDERWIDTH:
1378 {
1379 return (DWORD)IntSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni);
1380 }
1381 case SPI_SETWORKAREA:
1382 {
1383 RECT rc;
1384 Status = MmCopyFromCaller(&rc, (PRECT)pvParam, sizeof(RECT));
1385 if(!NT_SUCCESS(Status))
1386 {
1387 SetLastNtError(Status);
1388 return( FALSE);
1389 }
1390 return( (DWORD)IntSystemParametersInfo(uiAction, uiParam, &rc, fWinIni));
1391 }
1392 case SPI_GETWORKAREA:
1393 {
1394 RECT rc;
1395
1396 if(!IntSystemParametersInfo(uiAction, uiParam, &rc, fWinIni))
1397 {
1398 return( FALSE);
1399 }
1400
1401 Status = MmCopyToCaller((PRECT)pvParam, &rc, sizeof(RECT));
1402 if(!NT_SUCCESS(Status))
1403 {
1404 SetLastNtError(Status);
1405 return( FALSE);
1406 }
1407 return( TRUE);
1408 }
1409 case SPI_GETFONTSMOOTHING:
1410 case SPI_GETGRADIENTCAPTIONS:
1411 case SPI_GETFOCUSBORDERHEIGHT:
1412 case SPI_GETFOCUSBORDERWIDTH:
1413 case SPI_GETWHEELSCROLLLINES:
1414 case SPI_GETWHEELSCROLLCHARS:
1415 case SPI_GETSCREENSAVERRUNNING:
1416 case SPI_SETSCREENSAVERRUNNING:
1417 case SPI_GETSCREENSAVETIMEOUT:
1418 case SPI_SETSCREENSAVETIMEOUT:
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 = PsGetWin32Process();
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 = PsGetWin32Thread();
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 */