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