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