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