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