added missing ObDereferenceObject calls
[reactos.git] / reactos / subsys / win32k / ntuser / misc.c
1 /* $Id: misc.c,v 1.30 2003/11/23 13:46:33 weiden 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 #include <ddk/ntddk.h>
12 #include <ddk/ntddmou.h>
13 #include <win32k/win32k.h>
14 #include <win32k/dc.h>
15 #include <internal/safe.h>
16 #include <include/error.h>
17 #include <include/window.h>
18 #include <include/painting.h>
19 #include <include/dce.h>
20 #include <include/mouse.h>
21 #include <include/winsta.h>
22 #include <include/caret.h>
23 #include <include/object.h>
24
25 #define NDEBUG
26 #include <debug.h>
27
28 void W32kRegisterPrimitiveMessageQueue() {
29 extern PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue;
30 if( !pmPrimitiveMessageQueue ) {
31 PW32THREAD pThread;
32 pThread = PsGetWin32Thread();
33 if( pThread && pThread->MessageQueue ) {
34 pmPrimitiveMessageQueue = pThread->MessageQueue;
35 DbgPrint( "Installed primitive input queue.\n" );
36 }
37 } else {
38 DbgPrint( "Alert! Someone is trying to steal the primitive queue.\n" );
39 }
40 }
41
42 PUSER_MESSAGE_QUEUE W32kGetPrimitiveMessageQueue() {
43 extern PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue;
44 return pmPrimitiveMessageQueue;
45 }
46
47 /*
48 * @unimplemented
49 */
50 DWORD
51 STDCALL
52 NtUserCallNoParam(DWORD Routine)
53 {
54 DWORD Result = 0;
55
56 switch(Routine)
57 {
58 case NOPARAM_ROUTINE_REGISTER_PRIMITIVE:
59 W32kRegisterPrimitiveMessageQueue();
60 Result = (DWORD)TRUE;
61 break;
62
63 case NOPARAM_ROUTINE_DESTROY_CARET:
64 Result = (DWORD)IntDestroyCaret(PsGetCurrentThread()->Win32Thread);
65 break;
66
67 case NOPARAM_ROUTINE_INIT_MESSAGE_PUMP:
68 Result = (DWORD)IntInitMessagePumpHook();
69 break;
70
71 case NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP:
72 Result = (DWORD)IntUninitMessagePumpHook();
73 break;
74
75 default:
76 DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam\n");
77 SetLastWin32Error(ERROR_INVALID_PARAMETER);
78 break;
79 }
80 return Result;
81 }
82
83 /*
84 * @implemented
85 */
86 DWORD
87 STDCALL
88 NtUserCallOneParam(
89 DWORD Param,
90 DWORD Routine)
91 {
92 NTSTATUS Status;
93 DWORD Result = 0;
94 PWINSTATION_OBJECT WinStaObject;
95 PWINDOW_OBJECT WindowObject;
96
97 switch(Routine)
98 {
99 case ONEPARAM_ROUTINE_GETMENU:
100 WindowObject = IntGetWindowObject((HWND)Param);
101 if(!WindowObject)
102 {
103 SetLastWin32Error(ERROR_INVALID_HANDLE);
104 return FALSE;
105 }
106
107 Result = (DWORD)WindowObject->IDMenu;
108
109 IntReleaseWindowObject(WindowObject);
110 return Result;
111
112 case ONEPARAM_ROUTINE_ISWINDOWUNICODE:
113 WindowObject = IntGetWindowObject((HWND)Param);
114 if(!WindowObject)
115 {
116 SetLastWin32Error(ERROR_INVALID_HANDLE);
117 return FALSE;
118 }
119 Result = WindowObject->Unicode;
120 IntReleaseWindowObject(WindowObject);
121 return Result;
122
123 case ONEPARAM_ROUTINE_WINDOWFROMDC:
124 return (DWORD)IntWindowFromDC((HDC)Param);
125
126 case ONEPARAM_ROUTINE_GETWNDCONTEXTHLPID:
127 WindowObject = IntGetWindowObject((HWND)Param);
128 if(!WindowObject)
129 {
130 SetLastWin32Error(ERROR_INVALID_HANDLE);
131 return FALSE;
132 }
133
134 Result = WindowObject->ContextHelpId;
135
136 IntReleaseWindowObject(WindowObject);
137 return Result;
138
139 case ONEPARAM_ROUTINE_SWAPMOUSEBUTTON:
140 Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
141 KernelMode,
142 0,
143 &WinStaObject);
144 if (!NT_SUCCESS(Status))
145 return (DWORD)FALSE;
146
147 Result = (DWORD)IntSwapMouseButton(WinStaObject, (BOOL)Param);
148
149 ObDereferenceObject(WinStaObject);
150 return Result;
151
152 case ONEPARAM_ROUTINE_SWITCHCARETSHOWING:
153 return (DWORD)IntSwitchCaretShowing((PVOID)Param);
154
155 case ONEPARAM_ROUTINE_SETCARETBLINKTIME:
156 return (DWORD)IntSetCaretBlinkTime((UINT)Param);
157
158 }
159 DPRINT1("Calling invalid routine number 0x%x in NtUserCallOneParam()\n Param=0x%x\n",
160 Routine, Param);
161 SetLastWin32Error(ERROR_INVALID_PARAMETER);
162 return 0;
163 }
164
165
166 /*
167 * @implemented
168 */
169 DWORD
170 STDCALL
171 NtUserCallTwoParam(
172 DWORD Param1,
173 DWORD Param2,
174 DWORD Routine)
175 {
176 NTSTATUS Status;
177 PWINDOW_OBJECT WindowObject;
178 PSYSTEM_CURSORINFO CurInfo;
179 PWINSTATION_OBJECT WinStaObject;
180 POINT Pos;
181
182 switch(Routine)
183 {
184 case TWOPARAM_ROUTINE_ENABLEWINDOW:
185 UNIMPLEMENTED
186 return 0;
187
188 case TWOPARAM_ROUTINE_UNKNOWN:
189 UNIMPLEMENTED
190 return 0;
191
192 case TWOPARAM_ROUTINE_SHOWOWNEDPOPUPS:
193 UNIMPLEMENTED
194 return 0;
195
196 case TWOPARAM_ROUTINE_SWITCHTOTHISWINDOW:
197 UNIMPLEMENTED
198 return 0;
199
200 case TWOPARAM_ROUTINE_VALIDATERGN:
201 return (DWORD)NtUserValidateRgn((HWND) Param1, (HRGN) Param2);
202
203 case TWOPARAM_ROUTINE_SETWNDCONTEXTHLPID:
204 WindowObject = IntGetWindowObject((HWND)Param1);
205 if(!WindowObject)
206 {
207 SetLastWin32Error(ERROR_INVALID_HANDLE);
208 return (DWORD)FALSE;
209 }
210
211 WindowObject->ContextHelpId = Param2;
212
213 IntReleaseWindowObject(WindowObject);
214 return (DWORD)TRUE;
215
216 case TWOPARAM_ROUTINE_CURSORPOSITION:
217 if(!Param1)
218 return (DWORD)FALSE;
219 Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
220 KernelMode,
221 0,
222 &WinStaObject);
223 if (!NT_SUCCESS(Status))
224 return (DWORD)FALSE;
225
226 if(Param2)
227 {
228 /* set cursor position */
229
230 Status = MmCopyFromCaller(&Pos, (PPOINT)Param1, sizeof(POINT));
231 if(!NT_SUCCESS(Status))
232 {
233 ObDereferenceObject(WinStaObject);
234 SetLastNtError(Status);
235 return FALSE;
236 }
237
238 CurInfo = &WinStaObject->SystemCursor;
239 /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
240
241 //CheckClipCursor(&Pos->x, &Pos->y, CurInfo);
242 if((Pos.x != CurInfo->x) || (Pos.y != CurInfo->y))
243 {
244 MouseMoveCursor(Pos.x, Pos.y);
245 }
246
247 }
248 else
249 {
250 /* get cursor position */
251 /* FIXME - check if process has WINSTA_READATTRIBUTES */
252 Pos.x = WinStaObject->SystemCursor.x;
253 Pos.y = WinStaObject->SystemCursor.y;
254
255 Status = MmCopyToCaller((PPOINT)Param1, &Pos, sizeof(POINT));
256 if(!NT_SUCCESS(Status))
257 {
258 ObDereferenceObject(WinStaObject);
259 SetLastNtError(Status);
260 return FALSE;
261 }
262
263 }
264
265 ObDereferenceObject(WinStaObject);
266
267 return (DWORD)TRUE;
268
269 case TWOPARAM_ROUTINE_SETCARETPOS:
270 return (DWORD)IntSetCaretPos((int)Param1, (int)Param2);
271 }
272 DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam()\n Param1=0x%x Parm2=0x%x\n",
273 Routine, Param1, Param2);
274 SetLastWin32Error(ERROR_INVALID_PARAMETER);
275 return 0;
276 }
277
278 HWND
279 STDCALL
280 NtUserCallHwndOpt(
281 HWND Param,
282 DWORD Routine)
283 {
284 switch (Routine)
285 {
286 case HWNDOPT_ROUTINE_SETPROGMANWINDOW:
287 /* FIXME */
288 break;
289
290 case HWNDOPT_ROUTINE_SETTASKMANWINDOW:
291 /* FIXME */
292 break;
293 }
294
295 return 0;
296 }
297
298 /*
299 * @implemented
300 */
301 DWORD
302 STDCALL
303 NtUserSystemParametersInfo(
304 UINT uiAction,
305 UINT uiParam,
306 PVOID pvParam,
307 UINT fWinIni)
308 {
309 /* FIXME: This should be obtained from the registry */
310 static LOGFONTW CaptionFont =
311 { 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
312 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"" };
313 /* { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
314 0, 0, DEFAULT_QUALITY, FF_MODERN, L"Bitstream Vera Sans Bold" };*/
315 NTSTATUS Status;
316 PWINSTATION_OBJECT WinStaObject;
317
318 switch(uiAction)
319 {
320 case SPI_SETDOUBLECLKWIDTH:
321 case SPI_SETDOUBLECLKHEIGHT:
322 case SPI_SETDOUBLECLICKTIME:
323 {
324 Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
325 KernelMode,
326 0,
327 &WinStaObject);
328 if (!NT_SUCCESS(Status))
329 return (DWORD)FALSE;
330
331 switch(uiAction)
332 {
333 case SPI_SETDOUBLECLKWIDTH:
334 /* FIXME limit the maximum value? */
335 WinStaObject->SystemCursor.DblClickWidth = uiParam;
336 break;
337 case SPI_SETDOUBLECLKHEIGHT:
338 /* FIXME limit the maximum value? */
339 WinStaObject->SystemCursor.DblClickHeight = uiParam;
340 break;
341 case SPI_SETDOUBLECLICKTIME:
342 /* FIXME limit the maximum time to 1000 ms? */
343 WinStaObject->SystemCursor.DblClickSpeed = uiParam;
344 break;
345 }
346
347 /* FIXME save the value to the registry */
348
349 ObDereferenceObject(WinStaObject);
350 return TRUE;
351 }
352 case SPI_SETWORKAREA:
353 {
354 PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
355
356 if(!Desktop)
357 {
358 /* FIXME - Set last error */
359 return FALSE;
360 }
361
362 Status = MmCopyFromCaller(Desktop->WorkArea, (PRECT)pvParam, sizeof(RECT));
363 if(!NT_SUCCESS(Status))
364 {
365 SetLastNtError(Status);
366 return FALSE;
367 }
368
369 return TRUE;
370 }
371 case SPI_GETWORKAREA:
372 {
373 PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
374
375 if(!Desktop)
376 {
377 /* FIXME - Set last error */
378 return FALSE;
379 }
380
381 Status = MmCopyToCaller((PRECT)pvParam, Desktop->WorkArea, sizeof(RECT));
382 if(!NT_SUCCESS(Status))
383 {
384 SetLastNtError(Status);
385 return FALSE;
386 }
387
388 return TRUE;
389 }
390 case SPI_GETICONTITLELOGFONT:
391 {
392 Status = MmCopyToCaller(pvParam, &CaptionFont, sizeof(CaptionFont));
393 if(!NT_SUCCESS(Status))
394 {
395 SetLastNtError(Status);
396 return FALSE;
397 }
398 return TRUE;
399 }
400 case SPI_GETNONCLIENTMETRICS:
401 {
402 /* FIXME - use MmCopyToCaller() !!! */
403 LPNONCLIENTMETRICSW pMetrics = (LPNONCLIENTMETRICSW)pvParam;
404
405 if (pMetrics->cbSize != sizeof(NONCLIENTMETRICSW) ||
406 uiParam != sizeof(NONCLIENTMETRICSW))
407 {
408 return FALSE;
409 }
410
411 memset((char *)pvParam + sizeof(pMetrics->cbSize), 0,
412 pMetrics->cbSize - sizeof(pMetrics->cbSize));
413
414 pMetrics->iBorderWidth = 1;
415 pMetrics->iScrollWidth = NtUserGetSystemMetrics(SM_CXVSCROLL);
416 pMetrics->iScrollHeight = NtUserGetSystemMetrics(SM_CYHSCROLL);
417 pMetrics->iCaptionWidth = NtUserGetSystemMetrics(SM_CXSIZE);
418 pMetrics->iCaptionHeight = NtUserGetSystemMetrics(SM_CYSIZE);
419 memcpy((LPVOID)&(pMetrics->lfCaptionFont), &CaptionFont, sizeof(CaptionFont));
420 pMetrics->lfCaptionFont.lfWeight = FW_BOLD;
421 pMetrics->iSmCaptionWidth = NtUserGetSystemMetrics(SM_CXSMSIZE);
422 pMetrics->iSmCaptionHeight = NtUserGetSystemMetrics(SM_CYSMSIZE);
423 memcpy((LPVOID)&(pMetrics->lfSmCaptionFont), &CaptionFont, sizeof(CaptionFont));
424 pMetrics->iMenuWidth = NtUserGetSystemMetrics(SM_CXMENUSIZE);
425 pMetrics->iMenuHeight = NtUserGetSystemMetrics(SM_CYMENUSIZE);
426 memcpy((LPVOID)&(pMetrics->lfMenuFont), &CaptionFont, sizeof(CaptionFont));
427 memcpy((LPVOID)&(pMetrics->lfStatusFont), &CaptionFont, sizeof(CaptionFont));
428 memcpy((LPVOID)&(pMetrics->lfMessageFont), &CaptionFont, sizeof(CaptionFont));
429 return TRUE;
430 }
431
432 }
433 return FALSE;
434 }
435
436 UINT
437 STDCALL
438 NtUserGetDoubleClickTime(VOID)
439 {
440 UINT Result;
441 NTSTATUS Status;
442 PWINSTATION_OBJECT WinStaObject;
443
444 Status = IntValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
445 KernelMode,
446 0,
447 &WinStaObject);
448 if (!NT_SUCCESS(Status))
449 return (DWORD)FALSE;
450
451 Result = WinStaObject->SystemCursor.DblClickSpeed;
452
453 ObDereferenceObject(WinStaObject);
454 return Result;
455 }
456
457 BOOL
458 STDCALL
459 NtUserGetGUIThreadInfo(
460 DWORD idThread,
461 LPGUITHREADINFO lpgui)
462 {
463 NTSTATUS Status;
464 PTHRDCARETINFO CaretInfo;
465 GUITHREADINFO SafeGui;
466 PDESKTOP_OBJECT Desktop;
467 PUSER_MESSAGE_QUEUE MsgQueue;
468 PETHREAD Thread = NULL;
469
470 Status = MmCopyFromCaller(&SafeGui, lpgui, sizeof(DWORD));
471 if(!NT_SUCCESS(Status))
472 {
473 SetLastNtError(Status);
474 return FALSE;
475 }
476
477 if(SafeGui.cbSize != sizeof(GUITHREADINFO))
478 {
479 SetLastWin32Error(ERROR_INVALID_PARAMETER);
480 return FALSE;
481 }
482
483 if(idThread)
484 {
485 Status = PsLookupThreadByThreadId((PVOID)idThread, &Thread);
486 if(!NT_SUCCESS(Status))
487 {
488 SetLastWin32Error(ERROR_ACCESS_DENIED);
489 return FALSE;
490 }
491 Desktop = Thread->Win32Thread->Desktop;
492 }
493 else
494 {
495 /* get the foreground thread */
496 PW32THREAD W32Thread = PsGetCurrentThread()->Win32Thread;
497 Desktop = W32Thread->Desktop;
498 if(Desktop)
499 {
500 MsgQueue = Desktop->ActiveMessageQueue;
501 if(MsgQueue)
502 {
503 Thread = MsgQueue->Thread;
504 }
505 }
506 }
507
508 if(!Thread || !Desktop)
509 {
510 if(idThread && Thread)
511 ObDereferenceObject(Thread);
512 SetLastWin32Error(ERROR_ACCESS_DENIED);
513 return FALSE;
514 }
515
516 CaretInfo = ThrdCaretInfo(Thread->Win32Thread);
517 MsgQueue = (PUSER_MESSAGE_QUEUE)Desktop->ActiveMessageQueue;
518
519 SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0);
520 if(MsgQueue->MenuOwner)
521 SafeGui.flags |= GUI_INMENUMODE | MsgQueue->MenuState;
522 if(MsgQueue->MoveSize)
523 SafeGui.flags |= GUI_INMOVESIZE;
524
525 /* FIXME add flag GUI_16BITTASK */
526
527 SafeGui.hwndActive = MsgQueue->ActiveWindow;
528 SafeGui.hwndFocus = MsgQueue->FocusWindow;
529 SafeGui.hwndCapture = MsgQueue->CaptureWindow;
530 SafeGui.hwndMenuOwner = MsgQueue->MenuOwner;
531 SafeGui.hwndMoveSize = MsgQueue->MoveSize;
532 SafeGui.hwndCaret = CaretInfo->hWnd;
533
534 SafeGui.rcCaret.left = CaretInfo->Pos.x;
535 SafeGui.rcCaret.top = CaretInfo->Pos.y;
536 SafeGui.rcCaret.right = SafeGui.rcCaret.left + CaretInfo->Size.cx;
537 SafeGui.rcCaret.bottom = SafeGui.rcCaret.top + CaretInfo->Size.cy;
538
539 if(idThread)
540 ObDereferenceObject(Thread);
541
542 Status = MmCopyToCaller(lpgui, &SafeGui, sizeof(GUITHREADINFO));
543 if(!NT_SUCCESS(Status))
544 {
545 SetLastNtError(Status);
546 return FALSE;
547 }
548
549 return TRUE;
550 }
551
552
553 DWORD
554 STDCALL
555 NtUserGetGuiResources(
556 HANDLE hProcess,
557 DWORD uiFlags)
558 {
559 PEPROCESS Process;
560 PW32PROCESS W32Process;
561 NTSTATUS Status;
562 DWORD Ret = 0;
563
564 Status = ObReferenceObjectByHandle(hProcess,
565 PROCESS_QUERY_INFORMATION,
566 PsProcessType,
567 ExGetPreviousMode(),
568 (PVOID*)&Process,
569 NULL);
570
571 if(!NT_SUCCESS(Status))
572 {
573 SetLastNtError(Status);
574 return 0;
575 }
576
577 W32Process = Process->Win32Process;
578 if(!W32Process)
579 {
580 ObDereferenceObject(Process);
581 SetLastWin32Error(ERROR_INVALID_PARAMETER);
582 return 0;
583 }
584
585 switch(uiFlags)
586 {
587 case GR_GDIOBJECTS:
588 {
589 Ret = (DWORD)W32Process->GDIObjects;
590 break;
591 }
592 case GR_USEROBJECTS:
593 {
594 Ret = (DWORD)W32Process->UserObjects;
595 break;
596 }
597 default:
598 {
599 SetLastWin32Error(ERROR_INVALID_PARAMETER);
600 break;
601 }
602 }
603
604 ObDereferenceObject(Process);
605
606 return Ret;
607 }
608