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