-surround user part (most of it) with a single lock (currently a mutex, but will...
[reactos.git] / reactos / subsys / 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 PW32THREAD pThread;
25 pThread = PsGetWin32Thread();
26 if( pThread && pThread->MessageQueue ) {
27 pmPrimitiveMessageQueue = pThread->MessageQueue;
28 IntReferenceMessageQueue(pmPrimitiveMessageQueue);
29 DPRINT( "Installed primitive input queue.\n" );
30 }
31 } else {
32 DPRINT1( "Alert! Someone is trying to steal the primitive queue.\n" );
33 }
34 }
35
36 VOID W32kUnregisterPrimitiveMessageQueue(VOID)
37 {
38 extern PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue;
39 IntDereferenceMessageQueue(pmPrimitiveMessageQueue);
40 pmPrimitiveMessageQueue = NULL;
41 }
42
43 PUSER_MESSAGE_QUEUE W32kGetPrimitiveMessageQueue()
44 {
45 extern PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue;
46 return pmPrimitiveMessageQueue;
47 }
48
49 BOOL FASTCALL
50 co_IntRegisterLogonProcess(HANDLE ProcessId, BOOL Register)
51 {
52 PEPROCESS Process;
53 NTSTATUS Status;
54 CSR_API_MESSAGE Request;
55
56 Status = PsLookupProcessByProcessId(ProcessId,
57 &Process);
58 if (!NT_SUCCESS(Status))
59 {
60 SetLastWin32Error(RtlNtStatusToDosError(Status));
61 return FALSE;
62 }
63
64 if (Register)
65 {
66 /* Register the logon process */
67 if (LogonProcess != NULL)
68 {
69 ObDereferenceObject(Process);
70 return FALSE;
71 }
72
73 LogonProcess = (PW32PROCESS)Process->Win32Process;
74 }
75 else
76 {
77 /* Deregister the logon process */
78 if (LogonProcess != (PW32PROCESS)Process->Win32Process)
79 {
80 ObDereferenceObject(Process);
81 return FALSE;
82 }
83
84 LogonProcess = NULL;
85 }
86
87 ObDereferenceObject(Process);
88
89 Request.Type = MAKE_CSR_API(REGISTER_LOGON_PROCESS, CSR_GUI);
90 Request.Data.RegisterLogonProcessRequest.ProcessId = ProcessId;
91 Request.Data.RegisterLogonProcessRequest.Register = Register;
92
93 Status = co_CsrNotify(&Request);
94 if (! NT_SUCCESS(Status))
95 {
96 DPRINT1("Failed to register logon process with CSRSS\n");
97 return FALSE;
98 }
99
100 return TRUE;
101 }
102
103 /*
104 * @unimplemented
105 */
106 DWORD
107 STDCALL
108 NtUserCallNoParam(DWORD Routine)
109 {
110 DWORD Result = 0;
111 DECLARE_RETURN(DWORD);
112
113 DPRINT("Enter NtUserCallNoParam\n");
114 UserEnterExclusive();
115
116 switch(Routine)
117 {
118 case NOPARAM_ROUTINE_REGISTER_PRIMITIVE:
119 W32kRegisterPrimitiveMessageQueue();
120 Result = (DWORD)TRUE;
121 break;
122
123 case NOPARAM_ROUTINE_DESTROY_CARET:
124 Result = (DWORD)co_IntDestroyCaret(PsGetCurrentThread()->Tcb.Win32Thread);
125 break;
126
127 case NOPARAM_ROUTINE_INIT_MESSAGE_PUMP:
128 Result = (DWORD)IntInitMessagePumpHook();
129 break;
130
131 case NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP:
132 Result = (DWORD)IntUninitMessagePumpHook();
133 break;
134
135 case NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO:
136 Result = (DWORD)MsqGetMessageExtraInfo();
137 break;
138
139 case NOPARAM_ROUTINE_ANYPOPUP:
140 Result = (DWORD)IntAnyPopup();
141 break;
142
143 case NOPARAM_ROUTINE_CSRSS_INITIALIZED:
144 Result = (DWORD)CsrInit();
145 break;
146
147 case NOPARAM_ROUTINE_MSQCLEARWAKEMASK:
148 RETURN( (DWORD)IntMsqClearWakeMask());
149
150 default:
151 DPRINT1("Calling invalid routine number 0x%x in NtUserCallNoParam\n", Routine);
152 SetLastWin32Error(ERROR_INVALID_PARAMETER);
153 break;
154 }
155 RETURN(Result);
156
157 CLEANUP:
158 DPRINT("Leave NtUserCallNoParam, ret=%i\n",_ret_);
159 UserLeave();
160 END_CLEANUP;
161 }
162
163 /*
164 * @implemented
165 */
166 DWORD
167 STDCALL
168 NtUserCallOneParam(
169 DWORD Param,
170 DWORD Routine)
171 {
172 DECLARE_RETURN(DWORD);
173
174 DPRINT("Enter NtUserCallOneParam\n");
175 UserEnterExclusive();
176
177 switch(Routine)
178 {
179 case ONEPARAM_ROUTINE_GETMENU:
180 {
181 PWINDOW_OBJECT WindowObject;
182 DWORD Result;
183
184 WindowObject = IntGetWindowObject((HWND)Param);
185 if(!WindowObject)
186 {
187 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
188 RETURN( FALSE);
189 }
190
191 Result = (DWORD)WindowObject->IDMenu;
192
193 IntReleaseWindowObject(WindowObject);
194 RETURN( Result);
195 }
196
197 case ONEPARAM_ROUTINE_ISWINDOWUNICODE:
198 {
199 PWINDOW_OBJECT WindowObject;
200 DWORD Result;
201
202 WindowObject = IntGetWindowObject((HWND)Param);
203 if(!WindowObject)
204 {
205 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
206 RETURN( FALSE);
207 }
208 Result = WindowObject->Unicode;
209 IntReleaseWindowObject(WindowObject);
210 RETURN( Result);
211 }
212
213 case ONEPARAM_ROUTINE_WINDOWFROMDC:
214 RETURN( (DWORD)IntWindowFromDC((HDC)Param));
215
216 case ONEPARAM_ROUTINE_GETWNDCONTEXTHLPID:
217 {
218 PWINDOW_OBJECT WindowObject;
219 DWORD Result;
220
221 WindowObject = IntGetWindowObject((HWND)Param);
222 if(!WindowObject)
223 {
224 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
225 RETURN( FALSE);
226 }
227
228 Result = WindowObject->ContextHelpId;
229
230 IntReleaseWindowObject(WindowObject);
231 RETURN( Result);
232 }
233
234 case ONEPARAM_ROUTINE_SWAPMOUSEBUTTON:
235 {
236 PWINSTATION_OBJECT WinStaObject;
237 NTSTATUS Status;
238 DWORD Result;
239
240 Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
241 KernelMode,
242 0,
243 &WinStaObject);
244 if (!NT_SUCCESS(Status))
245 RETURN( (DWORD)FALSE);
246
247 /* FIXME
248 Result = (DWORD)IntSwapMouseButton(WinStaObject, (BOOL)Param); */
249 Result = 0;
250
251 ObDereferenceObject(WinStaObject);
252 RETURN( Result);
253 }
254
255 case ONEPARAM_ROUTINE_SWITCHCARETSHOWING:
256 RETURN( (DWORD)IntSwitchCaretShowing((PVOID)Param));
257
258 case ONEPARAM_ROUTINE_SETCARETBLINKTIME:
259 RETURN( (DWORD)IntSetCaretBlinkTime((UINT)Param));
260
261 case ONEPARAM_ROUTINE_ENUMCLIPBOARDFORMATS:
262 RETURN( (DWORD)IntEnumClipboardFormats((UINT)Param));
263
264 case ONEPARAM_ROUTINE_GETWINDOWINSTANCE:
265 {
266 PWINDOW_OBJECT WindowObject;
267 DWORD Result;
268
269 if(!(WindowObject = IntGetWindowObject((HWND)Param)))
270 {
271 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
272 RETURN( FALSE);
273 }
274
275 Result = (DWORD)WindowObject->Instance;
276 IntReleaseWindowObject(WindowObject);
277 RETURN( Result);
278 }
279
280 case ONEPARAM_ROUTINE_SETMESSAGEEXTRAINFO:
281 RETURN( (DWORD)MsqSetMessageExtraInfo((LPARAM)Param));
282
283 case ONEPARAM_ROUTINE_GETCURSORPOSITION:
284 {
285 PWINSTATION_OBJECT WinStaObject;
286 NTSTATUS Status;
287 POINT Pos;
288
289 if(!Param)
290 RETURN( (DWORD)FALSE);
291 Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
292 KernelMode,
293 0,
294 &WinStaObject);
295 if (!NT_SUCCESS(Status))
296 RETURN( (DWORD)FALSE);
297
298 /* FIXME - check if process has WINSTA_READATTRIBUTES */
299 IntGetCursorLocation(WinStaObject, &Pos);
300
301 Status = MmCopyToCaller((PPOINT)Param, &Pos, sizeof(POINT));
302 if(!NT_SUCCESS(Status))
303 {
304 ObDereferenceObject(WinStaObject);
305 SetLastNtError(Status);
306 RETURN( FALSE);
307 }
308
309 ObDereferenceObject(WinStaObject);
310
311 RETURN( (DWORD)TRUE);
312 }
313
314 case ONEPARAM_ROUTINE_ISWINDOWINDESTROY:
315 {
316 PWINDOW_OBJECT WindowObject;
317 DWORD Result;
318
319 WindowObject = IntGetWindowObject((HWND)Param);
320 if(!WindowObject)
321 {
322 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
323 RETURN( FALSE);
324 }
325
326 Result = (DWORD)IntIsWindowInDestroy(WindowObject);
327
328 IntReleaseWindowObject(WindowObject);
329 RETURN( Result);
330 }
331
332 case ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING:
333 {
334 BOOL Enable;
335 PW32PROCESS Process = PsGetWin32Process();
336
337 if(Process != NULL)
338 {
339 Enable = (BOOL)(Param != 0);
340
341 if(Enable)
342 {
343 Process->Flags &= ~W32PF_NOWINDOWGHOSTING;
344 }
345 else
346 {
347 Process->Flags |= W32PF_NOWINDOWGHOSTING;
348 }
349
350 RETURN( TRUE);
351 }
352
353 RETURN( FALSE);
354 }
355
356 case ONEPARAM_ROUTINE_MSQSETWAKEMASK:
357 RETURN( (DWORD)IntMsqSetWakeMask(Param));
358
359 case ONEPARAM_ROUTINE_GETKEYBOARDTYPE:
360 RETURN( UserGetKeyboardType(Param));
361
362 case ONEPARAM_ROUTINE_GETKEYBOARDLAYOUT:
363 RETURN( (DWORD)UserGetKeyboardLayout(Param));
364 }
365 DPRINT1("Calling invalid routine number 0x%x in NtUserCallOneParam(), Param=0x%x\n",
366 Routine, Param);
367 SetLastWin32Error(ERROR_INVALID_PARAMETER);
368 RETURN( 0);
369
370 CLEANUP:
371 DPRINT("Leave NtUserCallOneParam, ret=%i\n",_ret_);
372 UserLeave();
373 END_CLEANUP;
374 }
375
376
377 /*
378 * @implemented
379 */
380 DWORD
381 STDCALL
382 NtUserCallTwoParam(
383 DWORD Param1,
384 DWORD Param2,
385 DWORD Routine)
386 {
387 NTSTATUS Status;
388 PWINDOW_OBJECT WindowObject;
389 DECLARE_RETURN(DWORD);
390
391 DPRINT("Enter NtUserCallTwoParam\n");
392 UserEnterExclusive();
393
394 switch(Routine)
395 {
396 case TWOPARAM_ROUTINE_SETDCPENCOLOR:
397 {
398 RETURN( (DWORD)IntSetDCColor((HDC)Param1, OBJ_PEN, (COLORREF)Param2));
399 }
400 case TWOPARAM_ROUTINE_SETDCBRUSHCOLOR:
401 {
402 RETURN( (DWORD)IntSetDCColor((HDC)Param1, OBJ_BRUSH, (COLORREF)Param2));
403 }
404 case TWOPARAM_ROUTINE_GETDCCOLOR:
405 {
406 RETURN( (DWORD)IntGetDCColor((HDC)Param1, (ULONG)Param2));
407 }
408 case TWOPARAM_ROUTINE_GETWINDOWRGNBOX:
409 {
410 DWORD Ret;
411 RECT rcRect;
412 Ret = (DWORD)IntGetWindowRgnBox((HWND)Param1, &rcRect);
413 Status = MmCopyToCaller((PVOID)Param2, &rcRect, sizeof(RECT));
414 if(!NT_SUCCESS(Status))
415 {
416 SetLastNtError(Status);
417 RETURN( ERROR);
418 }
419 RETURN( Ret);
420 }
421 case TWOPARAM_ROUTINE_GETWINDOWRGN:
422 {
423 RETURN( (DWORD)IntGetWindowRgn((HWND)Param1, (HRGN)Param2));
424 }
425 case TWOPARAM_ROUTINE_SETMENUBARHEIGHT:
426 {
427 DWORD Ret;
428 PMENU_OBJECT MenuObject = IntGetMenuObject((HMENU)Param1);
429 if(!MenuObject)
430 RETURN( 0);
431
432 if(Param2 > 0)
433 {
434 Ret = (MenuObject->MenuInfo.Height == (int)Param2);
435 MenuObject->MenuInfo.Height = (int)Param2;
436 }
437 else
438 Ret = (DWORD)MenuObject->MenuInfo.Height;
439 IntReleaseMenuObject(MenuObject);
440 RETURN( Ret);
441 }
442 case TWOPARAM_ROUTINE_SETMENUITEMRECT:
443 {
444 BOOL Ret;
445 SETMENUITEMRECT smir;
446 PMENU_OBJECT MenuObject = IntGetMenuObject((HMENU)Param1);
447 if(!MenuObject)
448 RETURN( 0);
449
450 if(!NT_SUCCESS(MmCopyFromCaller(&smir, (PVOID)Param2, sizeof(SETMENUITEMRECT))))
451 {
452 IntReleaseMenuObject(MenuObject);
453 RETURN( 0);
454 }
455
456 Ret = IntSetMenuItemRect(MenuObject, smir.uItem, smir.fByPosition, &smir.rcRect);
457
458 IntReleaseMenuObject(MenuObject);
459 RETURN( (DWORD)Ret);
460 }
461
462 case TWOPARAM_ROUTINE_SETGUITHRDHANDLE:
463 {
464 PUSER_MESSAGE_QUEUE MsgQueue = PsGetCurrentThread()->Tcb.Win32Thread->MessageQueue;
465
466 ASSERT(MsgQueue);
467 RETURN( (DWORD)MsqSetStateWindow(MsgQueue, (ULONG)Param1, (HWND)Param2));
468 }
469
470 case TWOPARAM_ROUTINE_ENABLEWINDOW:
471 UNIMPLEMENTED
472 RETURN( 0);
473
474 case TWOPARAM_ROUTINE_UNKNOWN:
475 UNIMPLEMENTED
476 RETURN( 0);
477
478 case TWOPARAM_ROUTINE_SHOWOWNEDPOPUPS:
479 RETURN( (DWORD)IntShowOwnedPopups((HWND) Param1, (BOOL) Param2));
480
481 case TWOPARAM_ROUTINE_ROS_SHOWWINDOW:
482 {
483 #define WIN_NEEDS_SHOW_OWNEDPOPUP (0x00000040)
484 PWINDOW_OBJECT Window = IntGetWindowObject((HWND)Param1);
485 DPRINT1("ROS_SHOWWINDOW\n");
486 if (Window == 0)
487 {
488 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
489 RETURN( FALSE);
490 }
491 if (Param2)
492 {
493 if (!(Window->Flags & WIN_NEEDS_SHOW_OWNEDPOPUP))
494 {
495 IntReleaseWindowObject(Window);
496 RETURN( TRUE);
497 }
498 Window->Flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
499 }
500 else Window->Flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
501 DPRINT1("ROS_SHOWWINDOW ---> 0x%x\n",Window->Flags);
502 IntReleaseWindowObject(Window);
503 RETURN( TRUE);
504 }
505 case TWOPARAM_ROUTINE_SWITCHTOTHISWINDOW:
506 UNIMPLEMENTED
507 RETURN( 0);
508
509 case TWOPARAM_ROUTINE_VALIDATERGN:
510 RETURN( (DWORD)UserValidateRgn((HWND) Param1, (HRGN) Param2));
511
512 case TWOPARAM_ROUTINE_SETWNDCONTEXTHLPID:
513 WindowObject = IntGetWindowObject((HWND)Param1);
514 if(!WindowObject)
515 {
516 SetLastWin32Error(ERROR_INVALID_HANDLE);
517 RETURN( (DWORD)FALSE);
518 }
519
520 WindowObject->ContextHelpId = Param2;
521
522 IntReleaseWindowObject(WindowObject);
523 RETURN( (DWORD)TRUE);
524
525 case TWOPARAM_ROUTINE_SETCARETPOS:
526 RETURN( (DWORD)co_IntSetCaretPos((int)Param1, (int)Param2));
527
528 case TWOPARAM_ROUTINE_GETWINDOWINFO:
529 {
530 WINDOWINFO wi;
531 DWORD Ret;
532
533 if(!(WindowObject = IntGetWindowObject((HWND)Param1)))
534 {
535 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
536 RETURN( FALSE);
537 }
538
539 #if 0
540 /*
541 * According to WINE, Windows' doesn't check the cbSize field
542 */
543
544 Status = MmCopyFromCaller(&wi.cbSize, (PVOID)Param2, sizeof(wi.cbSize));
545 if(!NT_SUCCESS(Status))
546 {
547 IntReleaseWindowObject(WindowObject);
548 SetLastNtError(Status);
549 RETURN( FALSE);
550 }
551
552 if(wi.cbSize != sizeof(WINDOWINFO))
553 {
554 IntReleaseWindowObject(WindowObject);
555 SetLastWin32Error(ERROR_INVALID_PARAMETER);
556 RETURN( FALSE);
557 }
558 #endif
559
560 if((Ret = (DWORD)IntGetWindowInfo(WindowObject, &wi)))
561 {
562 Status = MmCopyToCaller((PVOID)Param2, &wi, sizeof(WINDOWINFO));
563 if(!NT_SUCCESS(Status))
564 {
565 IntReleaseWindowObject(WindowObject);
566 SetLastNtError(Status);
567 RETURN( FALSE);
568 }
569 }
570
571 IntReleaseWindowObject(WindowObject);
572 RETURN( Ret);
573 }
574
575 case TWOPARAM_ROUTINE_REGISTERLOGONPROC:
576 RETURN( (DWORD)co_IntRegisterLogonProcess((HANDLE)Param1, (BOOL)Param2));
577
578 case TWOPARAM_ROUTINE_SETSYSCOLORS:
579 {
580 DWORD Ret = 0;
581 PVOID Buffer;
582 struct
583 {
584 INT *Elements;
585 COLORREF *Colors;
586 } ChangeSysColors;
587
588 /* FIXME - we should make use of SEH here... */
589
590 Status = MmCopyFromCaller(&ChangeSysColors, (PVOID)Param1, sizeof(ChangeSysColors));
591 if(!NT_SUCCESS(Status))
592 {
593 SetLastNtError(Status);
594 RETURN( 0);
595 }
596
597 Buffer = ExAllocatePool(PagedPool, (Param2 * sizeof(INT)) + (Param2 * sizeof(COLORREF)));
598 if(Buffer != NULL)
599 {
600 INT *Elements = (INT*)Buffer;
601 COLORREF *Colors = (COLORREF*)Buffer + Param2;
602
603 Status = MmCopyFromCaller(Elements, ChangeSysColors.Elements, Param2 * sizeof(INT));
604 if(NT_SUCCESS(Status))
605 {
606 Status = MmCopyFromCaller(Colors, ChangeSysColors.Colors, Param2 * sizeof(COLORREF));
607 if(NT_SUCCESS(Status))
608 {
609 Ret = (DWORD)IntSetSysColors((UINT)Param2, Elements, Colors);
610 }
611 else
612 SetLastNtError(Status);
613 }
614 else
615 SetLastNtError(Status);
616
617 ExFreePool(Buffer);
618 }
619
620
621 RETURN( Ret);
622 }
623
624 case TWOPARAM_ROUTINE_GETSYSCOLORBRUSHES:
625 case TWOPARAM_ROUTINE_GETSYSCOLORPENS:
626 case TWOPARAM_ROUTINE_GETSYSCOLORS:
627 {
628 DWORD Ret = 0;
629 union
630 {
631 PVOID Pointer;
632 HBRUSH *Brushes;
633 HPEN *Pens;
634 COLORREF *Colors;
635 } Buffer;
636
637 /* FIXME - we should make use of SEH here... */
638
639 Buffer.Pointer = ExAllocatePool(PagedPool, Param2 * sizeof(HANDLE));
640 if(Buffer.Pointer != NULL)
641 {
642 switch(Routine)
643 {
644 case TWOPARAM_ROUTINE_GETSYSCOLORBRUSHES:
645 Ret = (DWORD)IntGetSysColorBrushes(Buffer.Brushes, (UINT)Param2);
646 break;
647 case TWOPARAM_ROUTINE_GETSYSCOLORPENS:
648 Ret = (DWORD)IntGetSysColorPens(Buffer.Pens, (UINT)Param2);
649 break;
650 case TWOPARAM_ROUTINE_GETSYSCOLORS:
651 Ret = (DWORD)IntGetSysColors(Buffer.Colors, (UINT)Param2);
652 break;
653 default:
654 Ret = 0;
655 break;
656 }
657
658 if(Ret > 0)
659 {
660 Status = MmCopyToCaller((PVOID)Param1, Buffer.Pointer, Param2 * sizeof(HANDLE));
661 if(!NT_SUCCESS(Status))
662 {
663 SetLastNtError(Status);
664 Ret = 0;
665 }
666 }
667
668 ExFreePool(Buffer.Pointer);
669 }
670 RETURN( Ret);
671 }
672
673 }
674 DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam(), Param1=0x%x Parm2=0x%x\n",
675 Routine, Param1, Param2);
676 SetLastWin32Error(ERROR_INVALID_PARAMETER);
677 RETURN( 0);
678
679 CLEANUP:
680 DPRINT("Leave NtUserCallTwoParam, ret=%i\n",_ret_);
681 UserLeave();
682 END_CLEANUP;
683 }
684
685
686 /*
687 * @unimplemented
688 */
689 BOOL
690 STDCALL
691 NtUserCallHwndLock(
692 HWND hWnd,
693 DWORD Routine)
694 {
695 BOOL Ret = 0;
696 PWINDOW_OBJECT Window;
697 DECLARE_RETURN(BOOLEAN);
698
699 DPRINT("Enter NtUserCallHwndLock\n");
700 UserEnterExclusive();
701
702 Window = IntGetWindowObject(hWnd);
703 if (Window == 0)
704 {
705 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
706 RETURN( FALSE);
707 }
708
709 /* FIXME: Routine can be 0x53 - 0x5E */
710 switch (Routine)
711 {
712 case HWNDLOCK_ROUTINE_ARRANGEICONICWINDOWS:
713 co_WinPosArrangeIconicWindows(Window);
714 break;
715
716 case HWNDLOCK_ROUTINE_DRAWMENUBAR:
717 {
718 PMENU_OBJECT MenuObject;
719 DPRINT("HWNDLOCK_ROUTINE_DRAWMENUBAR\n");
720 Ret = FALSE;
721 if (!((Window->Style & (WS_CHILD | WS_POPUP)) != WS_CHILD)) break;
722 MenuObject = IntGetMenuObject((HMENU) Window->IDMenu);
723 if(MenuObject == NULL) break;
724 MenuObject->MenuInfo.WndOwner = hWnd;
725 MenuObject->MenuInfo.Height = 0;
726 IntReleaseMenuObject(MenuObject);
727 co_WinPosSetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
728 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
729 Ret = TRUE;
730 break;
731 }
732
733 case HWNDLOCK_ROUTINE_REDRAWFRAME:
734 /* FIXME */
735 break;
736
737 case HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOW:
738 Ret = co_IntSetForegroundWindow(Window);
739 break;
740
741 case HWNDLOCK_ROUTINE_UPDATEWINDOW:
742 /* FIXME */
743 break;
744 }
745
746 IntReleaseWindowObject(Window);
747
748 RETURN( Ret);
749
750 CLEANUP:
751 DPRINT("Leave NtUserCallHwndLock, ret=%i\n",_ret_);
752 UserLeave();
753 END_CLEANUP;
754 }
755
756 /*
757 * @unimplemented
758 */
759 HWND
760 STDCALL
761 NtUserCallHwndOpt(
762 HWND Param,
763 DWORD Routine)
764 {
765 switch (Routine)
766 {
767 case HWNDOPT_ROUTINE_SETPROGMANWINDOW:
768 /*
769 * FIXME
770 * Nothing too hard...validate the hWnd and save it in the Desktop Info
771 */
772 DPRINT1("HWNDOPT_ROUTINE_SETPROGMANWINDOW UNIMPLEMENTED\n");
773 break;
774
775 case HWNDOPT_ROUTINE_SETTASKMANWINDOW:
776 /*
777 * FIXME
778 * Nothing too hard...validate the hWnd and save it in the Desktop Info
779 */
780 DPRINT1("HWNDOPT_ROUTINE_SETTASKMANWINDOW UNIMPLEMENTED\n");
781 break;
782 }
783
784 return Param;
785 }
786
787 /*
788 * @unimplemented
789 */
790 DWORD STDCALL
791 NtUserGetThreadState(
792 DWORD Routine)
793 {
794 DECLARE_RETURN(DWORD);
795
796 DPRINT("Enter NtUserGetThreadState\n");
797 UserEnterShared();
798
799 switch (Routine)
800 {
801 case 0:
802 RETURN( (DWORD)IntGetThreadFocusWindow());
803 }
804 RETURN( 0);
805
806 CLEANUP:
807 DPRINT("Leave NtUserGetThreadState, ret=%i\n",_ret_);
808 UserLeave();
809 END_CLEANUP;
810 }
811
812 VOID FASTCALL
813 IntGetFontMetricSetting(LPWSTR lpValueName, PLOGFONTW font)
814 {
815 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
816 NTSTATUS Status;
817 static LOGFONTW DefaultFont = {
818 11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
819 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
820 L"Bitstream Vera Sans"
821 };
822
823 RtlZeroMemory(&QueryTable, sizeof(QueryTable));
824
825 QueryTable[0].Name = lpValueName;
826 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
827 QueryTable[0].EntryContext = font;
828
829 Status = RtlQueryRegistryValues(
830 RTL_REGISTRY_USER,
831 L"Control Panel\\Desktop\\WindowMetrics",
832 QueryTable,
833 NULL,
834 NULL);
835
836 if (!NT_SUCCESS(Status))
837 {
838 RtlCopyMemory(font, &DefaultFont, sizeof(LOGFONTW));
839 }
840 }
841
842 ULONG FASTCALL
843 IntSystemParametersInfo(
844 UINT uiAction,
845 UINT uiParam,
846 PVOID pvParam,
847 UINT fWinIni)
848 {
849 PWINSTATION_OBJECT WinStaObject;
850 NTSTATUS Status;
851
852 static BOOL bInitialized = FALSE;
853 static LOGFONTW IconFont;
854 static NONCLIENTMETRICSW pMetrics;
855 static BOOL GradientCaptions = TRUE;
856 static UINT FocusBorderHeight = 1;
857 static UINT FocusBorderWidth = 1;
858
859 if (!bInitialized)
860 {
861 RtlZeroMemory(&IconFont, sizeof(LOGFONTW));
862 RtlZeroMemory(&pMetrics, sizeof(NONCLIENTMETRICSW));
863
864 IntGetFontMetricSetting(L"CaptionFont", &pMetrics.lfCaptionFont);
865 IntGetFontMetricSetting(L"SmCaptionFont", &pMetrics.lfSmCaptionFont);
866 IntGetFontMetricSetting(L"MenuFont", &pMetrics.lfMenuFont);
867 IntGetFontMetricSetting(L"StatusFont", &pMetrics.lfStatusFont);
868 IntGetFontMetricSetting(L"MessageFont", &pMetrics.lfMessageFont);
869 IntGetFontMetricSetting(L"IconFont", &IconFont);
870
871 pMetrics.iBorderWidth = 1;
872 pMetrics.iScrollWidth = UserGetSystemMetrics(SM_CXVSCROLL);
873 pMetrics.iScrollHeight = UserGetSystemMetrics(SM_CYHSCROLL);
874 pMetrics.iCaptionWidth = UserGetSystemMetrics(SM_CXSIZE);
875 pMetrics.iCaptionHeight = UserGetSystemMetrics(SM_CYSIZE);
876 pMetrics.iSmCaptionWidth = UserGetSystemMetrics(SM_CXSMSIZE);
877 pMetrics.iSmCaptionHeight = UserGetSystemMetrics(SM_CYSMSIZE);
878 pMetrics.iMenuWidth = UserGetSystemMetrics(SM_CXMENUSIZE);
879 pMetrics.iMenuHeight = UserGetSystemMetrics(SM_CYMENUSIZE);
880 pMetrics.cbSize = sizeof(NONCLIENTMETRICSW);
881
882 bInitialized = TRUE;
883 }
884
885 switch(uiAction)
886 {
887 case SPI_SETDOUBLECLKWIDTH:
888 case SPI_SETDOUBLECLKHEIGHT:
889 case SPI_SETDOUBLECLICKTIME:
890 case SPI_SETDESKWALLPAPER:
891 case SPI_GETDESKWALLPAPER:
892 {
893 PSYSTEM_CURSORINFO CurInfo;
894
895 Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
896 KernelMode,
897 0,
898 &WinStaObject);
899 if(!NT_SUCCESS(Status))
900 {
901 SetLastNtError(Status);
902 return (DWORD)FALSE;
903 }
904
905 switch(uiAction)
906 {
907 case SPI_SETDOUBLECLKWIDTH:
908 CurInfo = IntGetSysCursorInfo(WinStaObject);
909 /* FIXME limit the maximum value? */
910 CurInfo->DblClickWidth = uiParam;
911 break;
912 case SPI_SETDOUBLECLKHEIGHT:
913 CurInfo = IntGetSysCursorInfo(WinStaObject);
914 /* FIXME limit the maximum value? */
915 CurInfo->DblClickHeight = uiParam;
916 break;
917 case SPI_SETDOUBLECLICKTIME:
918 CurInfo = IntGetSysCursorInfo(WinStaObject);
919 /* FIXME limit the maximum time to 1000 ms? */
920 CurInfo->DblClickSpeed = uiParam;
921 break;
922 case SPI_SETDESKWALLPAPER:
923 {
924 /* This function expects different parameters than the user mode version!
925
926 We let the user mode code load the bitmap, it passed the handle to
927 the bitmap. We'll change it's ownership to system and replace it with
928 the current wallpaper bitmap */
929 HBITMAP hOldBitmap, hNewBitmap;
930 ASSERT(pvParam);
931
932 hNewBitmap = *(HBITMAP*)pvParam;
933 if(hNewBitmap != NULL)
934 {
935 BITMAPOBJ *bmp;
936 /* try to get the size of the wallpaper */
937 if(!(bmp = BITMAPOBJ_LockBitmap(hNewBitmap)))
938 {
939 ObDereferenceObject(WinStaObject);
940 return FALSE;
941 }
942 WinStaObject->cxWallpaper = bmp->SurfObj.sizlBitmap.cx;
943 WinStaObject->cyWallpaper = bmp->SurfObj.sizlBitmap.cy;
944
945 BITMAPOBJ_UnlockBitmap(bmp);
946
947 /* change the bitmap's ownership */
948 GDIOBJ_SetOwnership(hNewBitmap, NULL);
949 }
950 hOldBitmap = (HBITMAP)InterlockedExchange((LONG*)&WinStaObject->hbmWallpaper, (LONG)hNewBitmap);
951 if(hOldBitmap != NULL)
952 {
953 /* delete the old wallpaper */
954 NtGdiDeleteObject(hOldBitmap);
955 }
956 break;
957 }
958 case SPI_GETDESKWALLPAPER:
959 /* This function expects different parameters than the user mode version!
960
961 We basically return the current wallpaper handle - if any. The user
962 mode version should load the string from the registry and return it
963 without calling this function */
964 ASSERT(pvParam);
965 *(HBITMAP*)pvParam = (HBITMAP)WinStaObject->hbmWallpaper;
966 break;
967 }
968
969 /* FIXME save the value to the registry */
970
971 ObDereferenceObject(WinStaObject);
972 return TRUE;
973 }
974 case SPI_SETWORKAREA:
975 {
976 RECT *rc;
977 PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
978
979 if(!Desktop)
980 {
981 /* FIXME - Set last error */
982 return FALSE;
983 }
984
985 ASSERT(pvParam);
986 rc = (RECT*)pvParam;
987 Desktop->WorkArea = *rc;
988
989 return TRUE;
990 }
991 case SPI_GETWORKAREA:
992 {
993 PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
994
995 if(!Desktop)
996 {
997 /* FIXME - Set last error */
998 return FALSE;
999 }
1000
1001 ASSERT(pvParam);
1002 IntGetDesktopWorkArea(Desktop, (PRECT)pvParam);
1003
1004 return TRUE;
1005 }
1006 case SPI_SETGRADIENTCAPTIONS:
1007 {
1008 GradientCaptions = (pvParam != NULL);
1009 /* FIXME - should be checked if the color depth is higher than 8bpp? */
1010 return TRUE;
1011 }
1012 case SPI_GETGRADIENTCAPTIONS:
1013 {
1014 HDC hDC;
1015 BOOL Ret = GradientCaptions;
1016
1017 hDC = IntGetScreenDC();
1018 if(hDC)
1019 {
1020 Ret = (NtGdiGetDeviceCaps(hDC, BITSPIXEL) > 8) && Ret;
1021
1022 ASSERT(pvParam);
1023 *((PBOOL)pvParam) = Ret;
1024 return TRUE;
1025 }
1026 return FALSE;
1027 }
1028 case SPI_SETFONTSMOOTHING:
1029 {
1030 IntEnableFontRendering(uiParam != 0);
1031 return TRUE;
1032 }
1033 case SPI_GETFONTSMOOTHING:
1034 {
1035 ASSERT(pvParam);
1036 *((BOOL*)pvParam) = IntIsFontRenderingEnabled();
1037 return TRUE;
1038 }
1039 case SPI_GETICONTITLELOGFONT:
1040 {
1041 ASSERT(pvParam);
1042 *((LOGFONTW*)pvParam) = IconFont;
1043 return TRUE;
1044 }
1045 case SPI_GETNONCLIENTMETRICS:
1046 {
1047 ASSERT(pvParam);
1048 *((NONCLIENTMETRICSW*)pvParam) = pMetrics;
1049 return TRUE;
1050 }
1051 case SPI_GETFOCUSBORDERHEIGHT:
1052 {
1053 ASSERT(pvParam);
1054 *((UINT*)pvParam) = FocusBorderHeight;
1055 return TRUE;
1056 }
1057 case SPI_GETFOCUSBORDERWIDTH:
1058 {
1059 ASSERT(pvParam);
1060 *((UINT*)pvParam) = FocusBorderWidth;
1061 return TRUE;
1062 }
1063 case SPI_SETFOCUSBORDERHEIGHT:
1064 {
1065 FocusBorderHeight = (UINT)pvParam;
1066 return TRUE;
1067 }
1068 case SPI_SETFOCUSBORDERWIDTH:
1069 {
1070 FocusBorderWidth = (UINT)pvParam;
1071 return TRUE;
1072 }
1073
1074 default:
1075 {
1076 DPRINT1("SystemParametersInfo: Unsupported Action 0x%x (uiParam: 0x%x, pvParam: 0x%x, fWinIni: 0x%x)\n",
1077 uiAction, uiParam, pvParam, fWinIni);
1078 return FALSE;
1079 }
1080 }
1081 return FALSE;
1082 }
1083
1084 /*
1085 * @implemented
1086 */
1087 BOOL FASTCALL
1088 UserSystemParametersInfo(
1089 UINT uiAction,
1090 UINT uiParam,
1091 PVOID pvParam,
1092 UINT fWinIni)
1093 {
1094 NTSTATUS Status;
1095
1096 switch(uiAction)
1097 {
1098 case SPI_SETDOUBLECLKWIDTH:
1099 case SPI_SETDOUBLECLKHEIGHT:
1100 case SPI_SETDOUBLECLICKTIME:
1101 case SPI_SETGRADIENTCAPTIONS:
1102 case SPI_SETFONTSMOOTHING:
1103 case SPI_SETFOCUSBORDERHEIGHT:
1104 case SPI_SETFOCUSBORDERWIDTH:
1105 {
1106 return (DWORD)IntSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni);
1107 }
1108 case SPI_SETWORKAREA:
1109 {
1110 RECT rc;
1111 Status = MmCopyFromCaller(&rc, (PRECT)pvParam, sizeof(RECT));
1112 if(!NT_SUCCESS(Status))
1113 {
1114 SetLastNtError(Status);
1115 return( FALSE);
1116 }
1117 return( (DWORD)IntSystemParametersInfo(uiAction, uiParam, &rc, fWinIni));
1118 }
1119 case SPI_GETWORKAREA:
1120 {
1121 RECT rc;
1122
1123 if(!IntSystemParametersInfo(uiAction, uiParam, &rc, fWinIni))
1124 {
1125 return( FALSE);
1126 }
1127
1128 Status = MmCopyToCaller((PRECT)pvParam, &rc, sizeof(RECT));
1129 if(!NT_SUCCESS(Status))
1130 {
1131 SetLastNtError(Status);
1132 return( FALSE);
1133 }
1134 return( TRUE);
1135 }
1136 case SPI_GETFONTSMOOTHING:
1137 case SPI_GETGRADIENTCAPTIONS:
1138 case SPI_GETFOCUSBORDERHEIGHT:
1139 case SPI_GETFOCUSBORDERWIDTH:
1140 {
1141 BOOL Ret;
1142
1143 if(!IntSystemParametersInfo(uiAction, uiParam, &Ret, fWinIni))
1144 {
1145 return( FALSE);
1146 }
1147
1148 Status = MmCopyToCaller(pvParam, &Ret, sizeof(BOOL));
1149 if(!NT_SUCCESS(Status))
1150 {
1151 SetLastNtError(Status);
1152 return( FALSE);
1153 }
1154 return( TRUE);
1155 }
1156 case SPI_SETDESKWALLPAPER:
1157 {
1158 /* !!! As opposed to the user mode version this version accepts a handle
1159 to the bitmap! */
1160 HBITMAP hbmWallpaper;
1161
1162 Status = MmCopyFromCaller(&hbmWallpaper, pvParam, sizeof(HBITMAP));
1163 if(!NT_SUCCESS(Status))
1164 {
1165 SetLastNtError(Status);
1166 return( FALSE);
1167 }
1168 return( IntSystemParametersInfo(SPI_SETDESKWALLPAPER, 0, &hbmWallpaper, fWinIni));
1169 }
1170 case SPI_GETDESKWALLPAPER:
1171 {
1172 /* !!! As opposed to the user mode version this version returns a handle
1173 to the bitmap! */
1174 HBITMAP hbmWallpaper;
1175 BOOL Ret;
1176
1177 Ret = IntSystemParametersInfo(SPI_GETDESKWALLPAPER, 0, &hbmWallpaper, fWinIni);
1178
1179 Status = MmCopyToCaller(pvParam, &hbmWallpaper, sizeof(HBITMAP));
1180 if(!NT_SUCCESS(Status))
1181 {
1182 SetLastNtError(Status);
1183 return( FALSE);
1184 }
1185 return( Ret);
1186 }
1187 case SPI_GETICONTITLELOGFONT:
1188 {
1189 LOGFONTW IconFont;
1190
1191 if(!IntSystemParametersInfo(uiAction, uiParam, &IconFont, fWinIni))
1192 {
1193 return( FALSE);
1194 }
1195
1196 Status = MmCopyToCaller(pvParam, &IconFont, sizeof(LOGFONTW));
1197 if(!NT_SUCCESS(Status))
1198 {
1199 SetLastNtError(Status);
1200 return( FALSE);
1201 }
1202 return( TRUE);
1203 }
1204 case SPI_GETNONCLIENTMETRICS:
1205 {
1206 NONCLIENTMETRICSW metrics;
1207
1208 Status = MmCopyFromCaller(&metrics.cbSize, pvParam, sizeof(UINT));
1209 if(!NT_SUCCESS(Status))
1210 {
1211 SetLastNtError(Status);
1212 return( FALSE);
1213 }
1214 if(metrics.cbSize != sizeof(NONCLIENTMETRICSW))
1215 {
1216 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1217 return( FALSE);
1218 }
1219
1220 if(!IntSystemParametersInfo(uiAction, uiParam, &metrics, fWinIni))
1221 {
1222 return( FALSE);
1223 }
1224
1225 Status = MmCopyToCaller(pvParam, &metrics.cbSize, sizeof(NONCLIENTMETRICSW));
1226 if(!NT_SUCCESS(Status))
1227 {
1228 SetLastNtError(Status);
1229 return( FALSE);
1230 }
1231 return( TRUE);
1232 }
1233 }
1234 return( FALSE);
1235 }
1236
1237
1238
1239
1240 /*
1241 * @implemented
1242 */
1243 BOOL
1244 STDCALL
1245 NtUserSystemParametersInfo(
1246 UINT uiAction,
1247 UINT uiParam,
1248 PVOID pvParam,
1249 UINT fWinIni)
1250 {
1251 DECLARE_RETURN(BOOLEAN);
1252
1253 DPRINT("Enter NtUserSystemParametersInfo\n");
1254 UserEnterExclusive();
1255
1256 RETURN( UserSystemParametersInfo(uiAction, uiParam, pvParam, fWinIni));
1257
1258 CLEANUP:
1259 DPRINT("Leave NtUserSystemParametersInfo, ret=%i\n",_ret_);
1260 UserLeave();
1261 END_CLEANUP;
1262 }
1263
1264
1265
1266 UINT
1267 STDCALL
1268 NtUserGetDoubleClickTime(VOID)
1269 {
1270 UINT Result;
1271 NTSTATUS Status;
1272 PWINSTATION_OBJECT WinStaObject;
1273 PSYSTEM_CURSORINFO CurInfo;
1274 DECLARE_RETURN(UINT);
1275
1276 DPRINT("Enter NtUserGetDoubleClickTime\n");
1277 UserEnterShared();
1278
1279 Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
1280 KernelMode,
1281 0,
1282 &WinStaObject);
1283 if (!NT_SUCCESS(Status))
1284 RETURN( (DWORD)FALSE);
1285
1286 CurInfo = IntGetSysCursorInfo(WinStaObject);
1287 Result = CurInfo->DblClickSpeed;
1288
1289 ObDereferenceObject(WinStaObject);
1290 RETURN( Result);
1291
1292 CLEANUP:
1293 DPRINT("Leave NtUserGetDoubleClickTime, ret=%i\n",_ret_);
1294 UserLeave();
1295 END_CLEANUP;
1296 }
1297
1298 BOOL
1299 STDCALL
1300 NtUserGetGUIThreadInfo(
1301 DWORD idThread, /* if NULL use foreground thread */
1302 LPGUITHREADINFO lpgui)
1303 {
1304 NTSTATUS Status;
1305 PTHRDCARETINFO CaretInfo;
1306 GUITHREADINFO SafeGui;
1307 PDESKTOP_OBJECT Desktop;
1308 PUSER_MESSAGE_QUEUE MsgQueue;
1309 PETHREAD Thread = NULL;
1310 DECLARE_RETURN(BOOLEAN);
1311
1312 DPRINT("Enter NtUserGetGUIThreadInfo\n");
1313 UserEnterShared();
1314
1315 Status = MmCopyFromCaller(&SafeGui, lpgui, sizeof(DWORD));
1316 if(!NT_SUCCESS(Status))
1317 {
1318 SetLastNtError(Status);
1319 RETURN( FALSE);
1320 }
1321
1322 if(SafeGui.cbSize != sizeof(GUITHREADINFO))
1323 {
1324 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1325 RETURN( FALSE);
1326 }
1327
1328 if(idThread)
1329 {
1330 Status = PsLookupThreadByThreadId((HANDLE)idThread, &Thread);
1331 if(!NT_SUCCESS(Status))
1332 {
1333 SetLastWin32Error(ERROR_ACCESS_DENIED);
1334 RETURN( FALSE);
1335 }
1336 Desktop = Thread->Tcb.Win32Thread->Desktop;
1337 }
1338 else
1339 {
1340 /* get the foreground thread */
1341 PW32THREAD W32Thread = PsGetCurrentThread()->Tcb.Win32Thread;
1342 Desktop = W32Thread->Desktop;
1343 if(Desktop)
1344 {
1345 MsgQueue = Desktop->ActiveMessageQueue;
1346 if(MsgQueue)
1347 {
1348 Thread = MsgQueue->Thread;
1349 }
1350 }
1351 }
1352
1353 if(!Thread || !Desktop)
1354 {
1355 if(idThread && Thread)
1356 ObDereferenceObject(Thread);
1357 SetLastWin32Error(ERROR_ACCESS_DENIED);
1358 RETURN( FALSE);
1359 }
1360
1361 MsgQueue = (PUSER_MESSAGE_QUEUE)Desktop->ActiveMessageQueue;
1362 CaretInfo = MsgQueue->CaretInfo;
1363
1364 SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0);
1365 if(MsgQueue->MenuOwner)
1366 SafeGui.flags |= GUI_INMENUMODE | MsgQueue->MenuState;
1367 if(MsgQueue->MoveSize)
1368 SafeGui.flags |= GUI_INMOVESIZE;
1369
1370 /* FIXME add flag GUI_16BITTASK */
1371
1372 SafeGui.hwndActive = MsgQueue->ActiveWindow;
1373 SafeGui.hwndFocus = MsgQueue->FocusWindow;
1374 SafeGui.hwndCapture = MsgQueue->CaptureWindow;
1375 SafeGui.hwndMenuOwner = MsgQueue->MenuOwner;
1376 SafeGui.hwndMoveSize = MsgQueue->MoveSize;
1377 SafeGui.hwndCaret = CaretInfo->hWnd;
1378
1379 SafeGui.rcCaret.left = CaretInfo->Pos.x;
1380 SafeGui.rcCaret.top = CaretInfo->Pos.y;
1381 SafeGui.rcCaret.right = SafeGui.rcCaret.left + CaretInfo->Size.cx;
1382 SafeGui.rcCaret.bottom = SafeGui.rcCaret.top + CaretInfo->Size.cy;
1383
1384 if(idThread)
1385 ObDereferenceObject(Thread);
1386
1387 Status = MmCopyToCaller(lpgui, &SafeGui, sizeof(GUITHREADINFO));
1388 if(!NT_SUCCESS(Status))
1389 {
1390 SetLastNtError(Status);
1391 RETURN( FALSE);
1392 }
1393
1394 RETURN( TRUE);
1395
1396 CLEANUP:
1397 DPRINT("Leave NtUserGetGUIThreadInfo, ret=%i\n",_ret_);
1398 UserLeave();
1399 END_CLEANUP;
1400 }
1401
1402
1403 DWORD
1404 STDCALL
1405 NtUserGetGuiResources(
1406 HANDLE hProcess,
1407 DWORD uiFlags)
1408 {
1409 PEPROCESS Process;
1410 PW32PROCESS W32Process;
1411 NTSTATUS Status;
1412 DWORD Ret = 0;
1413 DECLARE_RETURN(DWORD);
1414
1415 DPRINT("Enter NtUserGetGuiResources\n");
1416 UserEnterShared();
1417
1418 Status = ObReferenceObjectByHandle(hProcess,
1419 PROCESS_QUERY_INFORMATION,
1420 PsProcessType,
1421 ExGetPreviousMode(),
1422 (PVOID*)&Process,
1423 NULL);
1424
1425 if(!NT_SUCCESS(Status))
1426 {
1427 SetLastNtError(Status);
1428 RETURN( 0);
1429 }
1430
1431 W32Process = (PW32PROCESS)Process->Win32Process;
1432 if(!W32Process)
1433 {
1434 ObDereferenceObject(Process);
1435 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1436 RETURN( 0);
1437 }
1438
1439 switch(uiFlags)
1440 {
1441 case GR_GDIOBJECTS:
1442 {
1443 Ret = (DWORD)W32Process->GDIObjects;
1444 break;
1445 }
1446 case GR_USEROBJECTS:
1447 {
1448 Ret = (DWORD)W32Process->UserObjects;
1449 break;
1450 }
1451 default:
1452 {
1453 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1454 break;
1455 }
1456 }
1457
1458 ObDereferenceObject(Process);
1459
1460 RETURN( Ret);
1461
1462 CLEANUP:
1463 DPRINT("Leave NtUserGetGuiResources, ret=%i\n",_ret_);
1464 UserLeave();
1465 END_CLEANUP;
1466 }
1467
1468 NTSTATUS FASTCALL
1469 IntSafeCopyUnicodeString(PUNICODE_STRING Dest,
1470 PUNICODE_STRING Source)
1471 {
1472 NTSTATUS Status;
1473 PWSTR Src;
1474
1475 Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING));
1476 if(!NT_SUCCESS(Status))
1477 {
1478 return Status;
1479 }
1480
1481 if(Dest->Length > 0x4000)
1482 {
1483 return STATUS_UNSUCCESSFUL;
1484 }
1485
1486 Src = Dest->Buffer;
1487 Dest->Buffer = NULL;
1488
1489 if(Dest->Length > 0 && Src)
1490 {
1491 Dest->MaximumLength = Dest->Length;
1492 Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING);
1493 if(!Dest->Buffer)
1494 {
1495 return STATUS_NO_MEMORY;
1496 }
1497
1498 Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length);
1499 if(!NT_SUCCESS(Status))
1500 {
1501 ExFreePool(Dest->Buffer);
1502 Dest->Buffer = NULL;
1503 return Status;
1504 }
1505
1506
1507 return STATUS_SUCCESS;
1508 }
1509
1510 /* string is empty */
1511 return STATUS_SUCCESS;
1512 }
1513
1514 NTSTATUS FASTCALL
1515 IntSafeCopyUnicodeStringTerminateNULL(PUNICODE_STRING Dest,
1516 PUNICODE_STRING Source)
1517 {
1518 NTSTATUS Status;
1519 PWSTR Src;
1520
1521 Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING));
1522 if(!NT_SUCCESS(Status))
1523 {
1524 return Status;
1525 }
1526
1527 if(Dest->Length > 0x4000)
1528 {
1529 return STATUS_UNSUCCESSFUL;
1530 }
1531
1532 Src = Dest->Buffer;
1533 Dest->Buffer = NULL;
1534
1535 if(Dest->Length > 0 && Src)
1536 {
1537 Dest->MaximumLength = Dest->Length + sizeof(WCHAR);
1538 Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING);
1539 if(!Dest->Buffer)
1540 {
1541 return STATUS_NO_MEMORY;
1542 }
1543
1544 Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length);
1545 if(!NT_SUCCESS(Status))
1546 {
1547 ExFreePool(Dest->Buffer);
1548 Dest->Buffer = NULL;
1549 return Status;
1550 }
1551
1552 /* make sure the string is null-terminated */
1553 Src = (PWSTR)((PBYTE)Dest->Buffer + Dest->Length);
1554 *Src = L'\0';
1555
1556 return STATUS_SUCCESS;
1557 }
1558
1559 /* string is empty */
1560 return STATUS_SUCCESS;
1561 }
1562
1563 NTSTATUS FASTCALL
1564 IntUnicodeStringToNULLTerminated(PWSTR *Dest, PUNICODE_STRING Src)
1565 {
1566 if (Src->Length + sizeof(WCHAR) <= Src->MaximumLength
1567 && L'\0' == Src->Buffer[Src->Length / sizeof(WCHAR)])
1568 {
1569 /* The unicode_string is already nul terminated. Just reuse it. */
1570 *Dest = Src->Buffer;
1571 return STATUS_SUCCESS;
1572 }
1573
1574 *Dest = ExAllocatePoolWithTag(PagedPool, Src->Length + sizeof(WCHAR), TAG_STRING);
1575 if (NULL == *Dest)
1576 {
1577 return STATUS_NO_MEMORY;
1578 }
1579 RtlCopyMemory(*Dest, Src->Buffer, Src->Length);
1580 (*Dest)[Src->Length / 2] = L'\0';
1581
1582 return STATUS_SUCCESS;
1583 }
1584
1585 void FASTCALL
1586 IntFreeNULLTerminatedFromUnicodeString(PWSTR NullTerminated, PUNICODE_STRING UnicodeString)
1587 {
1588 if (NullTerminated != UnicodeString->Buffer)
1589 {
1590 ExFreePool(NullTerminated);
1591 }
1592 }
1593
1594 BOOL STDCALL
1595 NtUserUpdatePerUserSystemParameters(
1596 DWORD dwReserved,
1597 BOOL bEnable)
1598 {
1599 BOOL Result = TRUE;
1600 DECLARE_RETURN(BOOLEAN);
1601
1602 DPRINT("Enter NtUserUpdatePerUserSystemParameters\n");
1603 UserEnterExclusive();
1604
1605 Result &= IntDesktopUpdatePerUserSettings(bEnable);
1606 RETURN( Result);
1607
1608 CLEANUP:
1609 DPRINT("Leave NtUserUpdatePerUserSystemParameters, ret=%i\n",_ret_);
1610 UserLeave();
1611 END_CLEANUP;
1612 }
1613
1614 /* EOF */