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