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