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