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