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