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