Sprinkle win32k with some explicit voids,
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / misc.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Misc User funcs
5 * FILE: subsystem/win32/win32k/ntuser/misc.c
6 * PROGRAMER: Ge van Geldorp (ge@gse.nl)
7 * REVISION HISTORY:
8 * 2003/05/22 Created
9 */
10
11 #include <w32k.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16
17 SHORT
18 FASTCALL
19 IntGdiGetLanguageID(VOID)
20 {
21 HANDLE KeyHandle;
22 ULONG Size = sizeof(WCHAR) * (MAX_PATH + 12);
23 OBJECT_ATTRIBUTES ObAttr;
24 // http://support.microsoft.com/kb/324097
25 ULONG Ret = 0x409; // English
26 PVOID KeyInfo;
27 UNICODE_STRING Language;
28
29 RtlInitUnicodeString( &Language,
30 L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Language");
31
32 InitializeObjectAttributes( &ObAttr,
33 &Language,
34 OBJ_CASE_INSENSITIVE,
35 NULL,
36 NULL);
37
38 if ( NT_SUCCESS(ZwOpenKey(&KeyHandle, KEY_READ, &ObAttr)))
39 {
40 KeyInfo = ExAllocatePoolWithTag(PagedPool, Size, TAG_STRING);
41 if ( KeyInfo )
42 {
43 RtlInitUnicodeString(&Language, L"Default");
44
45 if ( NT_SUCCESS(ZwQueryValueKey( KeyHandle,
46 &Language,
47 KeyValuePartialInformation,
48 KeyInfo,
49 Size,
50 &Size)) )
51 {
52 RtlInitUnicodeString(&Language, (PVOID)((char *)KeyInfo + 12));
53 RtlUnicodeStringToInteger(&Language, 16, &Ret);
54 }
55 ExFreePoolWithTag(KeyInfo, TAG_STRING);
56 }
57 ZwClose(KeyHandle);
58 }
59 DPRINT("Language ID = %x\n",Ret);
60 return (SHORT) Ret;
61 }
62
63 /*
64 * @unimplemented
65 */
66 DWORD APIENTRY
67 NtUserGetThreadState(
68 DWORD Routine)
69 {
70 DECLARE_RETURN(DWORD);
71
72 DPRINT("Enter NtUserGetThreadState\n");
73 if (Routine != THREADSTATE_GETTHREADINFO)
74 {
75 UserEnterShared();
76 }
77 else
78 {
79 UserEnterExclusive();
80 }
81
82 switch (Routine)
83 {
84 case THREADSTATE_GETTHREADINFO:
85 GetW32ThreadInfo();
86 RETURN(0);
87
88 case THREADSTATE_FOCUSWINDOW:
89 RETURN( (DWORD)IntGetThreadFocusWindow());
90 case THREADSTATE_CAPTUREWINDOW:
91 /* FIXME should use UserEnterShared */
92 RETURN( (DWORD)IntGetCapture());
93 case THREADSTATE_PROGMANWINDOW:
94 RETURN( (DWORD)GetW32ThreadInfo()->pDeskInfo->hProgmanWindow);
95 case THREADSTATE_TASKMANWINDOW:
96 RETURN( (DWORD)GetW32ThreadInfo()->pDeskInfo->hTaskManWindow);
97 case THREADSTATE_ACTIVEWINDOW:
98 RETURN ( (DWORD)UserGetActiveWindow());
99 case THREADSTATE_INSENDMESSAGE:
100 {
101 DWORD Ret = ISMEX_NOSEND;
102 PUSER_MESSAGE_QUEUE MessageQueue =
103 ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->MessageQueue;
104 DPRINT1("THREADSTATE_INSENDMESSAGE\n");
105
106 if (!IsListEmpty(&MessageQueue->SentMessagesListHead))
107 {
108 Ret = ISMEX_SEND;
109 }
110 else if (!IsListEmpty(&MessageQueue->NotifyMessagesListHead))
111 {
112 /* FIXME Need to set message flag when in callback mode with notify */
113 Ret = ISMEX_NOTIFY;
114 }
115 /* FIXME Need to set message flag if replied to or ReplyMessage */
116 RETURN( Ret);
117 }
118 case THREADSTATE_GETMESSAGETIME:
119 /* FIXME Needs more work! */
120 RETURN( ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->timeLast);
121
122 case THREADSTATE_GETINPUTSTATE:
123 RETURN( HIWORD(IntGetQueueStatus(FALSE)) & (QS_KEY | QS_MOUSEBUTTON));
124 }
125 RETURN( 0);
126
127 CLEANUP:
128 DPRINT("Leave NtUserGetThreadState, ret=%i\n",_ret_);
129 UserLeave();
130 END_CLEANUP;
131 }
132
133
134 UINT
135 APIENTRY
136 NtUserGetDoubleClickTime(VOID)
137 {
138 UINT Result;
139
140 DPRINT("Enter NtUserGetDoubleClickTime\n");
141 UserEnterShared();
142
143 // FIXME: Check if this works on non-interactive winsta
144 Result = gspv.iDblClickTime;
145
146 DPRINT("Leave NtUserGetDoubleClickTime, ret=%i\n", Result);
147 UserLeave();
148 return Result;
149 }
150
151 BOOL
152 APIENTRY
153 NtUserGetGUIThreadInfo(
154 DWORD idThread, /* if NULL use foreground thread */
155 LPGUITHREADINFO lpgui)
156 {
157 NTSTATUS Status;
158 PTHRDCARETINFO CaretInfo;
159 GUITHREADINFO SafeGui;
160 PDESKTOP Desktop;
161 PUSER_MESSAGE_QUEUE MsgQueue;
162 PETHREAD Thread = NULL;
163 DECLARE_RETURN(BOOLEAN);
164
165 DPRINT("Enter NtUserGetGUIThreadInfo\n");
166 UserEnterShared();
167
168 Status = MmCopyFromCaller(&SafeGui, lpgui, sizeof(DWORD));
169 if(!NT_SUCCESS(Status))
170 {
171 SetLastNtError(Status);
172 RETURN( FALSE);
173 }
174
175 if(SafeGui.cbSize != sizeof(GUITHREADINFO))
176 {
177 SetLastWin32Error(ERROR_INVALID_PARAMETER);
178 RETURN( FALSE);
179 }
180
181 if(idThread)
182 {
183 Status = PsLookupThreadByThreadId((HANDLE)idThread, &Thread);
184 if(!NT_SUCCESS(Status))
185 {
186 SetLastWin32Error(ERROR_ACCESS_DENIED);
187 RETURN( FALSE);
188 }
189 Desktop = ((PTHREADINFO)Thread->Tcb.Win32Thread)->Desktop;
190 }
191 else
192 {
193 /* get the foreground thread */
194 PTHREADINFO W32Thread = (PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread;
195 Desktop = W32Thread->Desktop;
196 if(Desktop)
197 {
198 MsgQueue = Desktop->ActiveMessageQueue;
199 if(MsgQueue)
200 {
201 Thread = MsgQueue->Thread;
202 }
203 }
204 }
205
206 if(!Thread || !Desktop)
207 {
208 if(idThread && Thread)
209 ObDereferenceObject(Thread);
210 SetLastWin32Error(ERROR_ACCESS_DENIED);
211 RETURN( FALSE);
212 }
213
214 MsgQueue = (PUSER_MESSAGE_QUEUE)Desktop->ActiveMessageQueue;
215 CaretInfo = MsgQueue->CaretInfo;
216
217 SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0);
218 if(MsgQueue->MenuOwner)
219 SafeGui.flags |= GUI_INMENUMODE | MsgQueue->MenuState;
220 if(MsgQueue->MoveSize)
221 SafeGui.flags |= GUI_INMOVESIZE;
222
223 /* FIXME add flag GUI_16BITTASK */
224
225 SafeGui.hwndActive = MsgQueue->ActiveWindow;
226 SafeGui.hwndFocus = MsgQueue->FocusWindow;
227 SafeGui.hwndCapture = MsgQueue->CaptureWindow;
228 SafeGui.hwndMenuOwner = MsgQueue->MenuOwner;
229 SafeGui.hwndMoveSize = MsgQueue->MoveSize;
230 SafeGui.hwndCaret = CaretInfo->hWnd;
231
232 SafeGui.rcCaret.left = CaretInfo->Pos.x;
233 SafeGui.rcCaret.top = CaretInfo->Pos.y;
234 SafeGui.rcCaret.right = SafeGui.rcCaret.left + CaretInfo->Size.cx;
235 SafeGui.rcCaret.bottom = SafeGui.rcCaret.top + CaretInfo->Size.cy;
236
237 if(idThread)
238 ObDereferenceObject(Thread);
239
240 Status = MmCopyToCaller(lpgui, &SafeGui, sizeof(GUITHREADINFO));
241 if(!NT_SUCCESS(Status))
242 {
243 SetLastNtError(Status);
244 RETURN( FALSE);
245 }
246
247 RETURN( TRUE);
248
249 CLEANUP:
250 DPRINT("Leave NtUserGetGUIThreadInfo, ret=%i\n",_ret_);
251 UserLeave();
252 END_CLEANUP;
253 }
254
255
256 DWORD
257 APIENTRY
258 NtUserGetGuiResources(
259 HANDLE hProcess,
260 DWORD uiFlags)
261 {
262 PEPROCESS Process;
263 PPROCESSINFO W32Process;
264 NTSTATUS Status;
265 DWORD Ret = 0;
266 DECLARE_RETURN(DWORD);
267
268 DPRINT("Enter NtUserGetGuiResources\n");
269 UserEnterShared();
270
271 Status = ObReferenceObjectByHandle(hProcess,
272 PROCESS_QUERY_INFORMATION,
273 PsProcessType,
274 ExGetPreviousMode(),
275 (PVOID*)&Process,
276 NULL);
277
278 if(!NT_SUCCESS(Status))
279 {
280 SetLastNtError(Status);
281 RETURN( 0);
282 }
283
284 W32Process = (PPROCESSINFO)Process->Win32Process;
285 if(!W32Process)
286 {
287 ObDereferenceObject(Process);
288 SetLastWin32Error(ERROR_INVALID_PARAMETER);
289 RETURN( 0);
290 }
291
292 switch(uiFlags)
293 {
294 case GR_GDIOBJECTS:
295 {
296 Ret = (DWORD)W32Process->GDIHandleCount;
297 break;
298 }
299 case GR_USEROBJECTS:
300 {
301 Ret = (DWORD)W32Process->UserHandleCount;
302 break;
303 }
304 default:
305 {
306 SetLastWin32Error(ERROR_INVALID_PARAMETER);
307 break;
308 }
309 }
310
311 ObDereferenceObject(Process);
312
313 RETURN( Ret);
314
315 CLEANUP:
316 DPRINT("Leave NtUserGetGuiResources, ret=%i\n",_ret_);
317 UserLeave();
318 END_CLEANUP;
319 }
320
321 NTSTATUS FASTCALL
322 IntSafeCopyUnicodeString(PUNICODE_STRING Dest,
323 PUNICODE_STRING Source)
324 {
325 NTSTATUS Status;
326 PWSTR Src;
327
328 Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING));
329 if(!NT_SUCCESS(Status))
330 {
331 return Status;
332 }
333
334 if(Dest->Length > 0x4000)
335 {
336 return STATUS_UNSUCCESSFUL;
337 }
338
339 Src = Dest->Buffer;
340 Dest->Buffer = NULL;
341 Dest->MaximumLength = Dest->Length;
342
343 if(Dest->Length > 0 && Src)
344 {
345 Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING);
346 if(!Dest->Buffer)
347 {
348 return STATUS_NO_MEMORY;
349 }
350
351 Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length);
352 if(!NT_SUCCESS(Status))
353 {
354 ExFreePoolWithTag(Dest->Buffer, TAG_STRING);
355 Dest->Buffer = NULL;
356 return Status;
357 }
358
359
360 return STATUS_SUCCESS;
361 }
362
363 /* string is empty */
364 return STATUS_SUCCESS;
365 }
366
367 NTSTATUS FASTCALL
368 IntSafeCopyUnicodeStringTerminateNULL(PUNICODE_STRING Dest,
369 PUNICODE_STRING Source)
370 {
371 NTSTATUS Status;
372 PWSTR Src;
373
374 Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING));
375 if(!NT_SUCCESS(Status))
376 {
377 return Status;
378 }
379
380 if(Dest->Length > 0x4000)
381 {
382 return STATUS_UNSUCCESSFUL;
383 }
384
385 Src = Dest->Buffer;
386 Dest->Buffer = NULL;
387 Dest->MaximumLength = 0;
388
389 if(Dest->Length > 0 && Src)
390 {
391 Dest->MaximumLength = Dest->Length + sizeof(WCHAR);
392 Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING);
393 if(!Dest->Buffer)
394 {
395 return STATUS_NO_MEMORY;
396 }
397
398 Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length);
399 if(!NT_SUCCESS(Status))
400 {
401 ExFreePoolWithTag(Dest->Buffer, TAG_STRING);
402 Dest->Buffer = NULL;
403 return Status;
404 }
405
406 /* make sure the string is null-terminated */
407 Src = (PWSTR)((PBYTE)Dest->Buffer + Dest->Length);
408 *Src = L'\0';
409
410 return STATUS_SUCCESS;
411 }
412
413 /* string is empty */
414 return STATUS_SUCCESS;
415 }
416
417 NTSTATUS FASTCALL
418 IntUnicodeStringToNULLTerminated(PWSTR *Dest, PUNICODE_STRING Src)
419 {
420 if (Src->Length + sizeof(WCHAR) <= Src->MaximumLength
421 && L'\0' == Src->Buffer[Src->Length / sizeof(WCHAR)])
422 {
423 /* The unicode_string is already nul terminated. Just reuse it. */
424 *Dest = Src->Buffer;
425 return STATUS_SUCCESS;
426 }
427
428 *Dest = ExAllocatePoolWithTag(PagedPool, Src->Length + sizeof(WCHAR), TAG_STRING);
429 if (NULL == *Dest)
430 {
431 return STATUS_NO_MEMORY;
432 }
433 RtlCopyMemory(*Dest, Src->Buffer, Src->Length);
434 (*Dest)[Src->Length / 2] = L'\0';
435
436 return STATUS_SUCCESS;
437 }
438
439 void FASTCALL
440 IntFreeNULLTerminatedFromUnicodeString(PWSTR NullTerminated, PUNICODE_STRING UnicodeString)
441 {
442 if (NullTerminated != UnicodeString->Buffer)
443 {
444 ExFreePool(NullTerminated);
445 }
446 }
447
448 PPROCESSINFO
449 GetW32ProcessInfo(VOID)
450 {
451 return (PPROCESSINFO)PsGetCurrentProcessWin32Process();
452 }
453
454 PTHREADINFO
455 GetW32ThreadInfo(VOID)
456 {
457 PTEB Teb;
458 PPROCESSINFO ppi;
459 PCLIENTINFO pci;
460 PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
461
462 if (pti == NULL)
463 {
464 /* FIXME - temporary hack for system threads... */
465 return NULL;
466 }
467 /* initialize it */
468 pti->ppi = ppi = GetW32ProcessInfo();
469
470 pti->pcti = &pti->cti; // FIXME Need to set it in desktop.c!
471
472 if (pti->Desktop != NULL)
473 {
474 pti->pDeskInfo = pti->Desktop->DesktopInfo;
475 }
476 else
477 {
478 pti->pDeskInfo = NULL;
479 }
480 /* update the TEB */
481 Teb = NtCurrentTeb();
482 pci = GetWin32ClientInfo();
483 pti->pClientInfo = pci;
484 _SEH2_TRY
485 {
486 ProbeForWrite( Teb,
487 sizeof(TEB),
488 sizeof(ULONG));
489
490 Teb->Win32ThreadInfo = (PW32THREAD) pti;
491
492 pci->pClientThreadInfo = NULL; // FIXME Need to set it in desktop.c!
493 pci->ppi = ppi;
494 pci->fsHooks = pti->fsHooks;
495 /* CI may not have been initialized. */
496 if (!pci->pDeskInfo && pti->pDeskInfo)
497 {
498 if (!pci->ulClientDelta) pci->ulClientDelta = DesktopHeapGetUserDelta();
499
500 pci->pDeskInfo = (PVOID)((ULONG_PTR)pti->pDeskInfo - pci->ulClientDelta);
501 }
502 }
503 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
504 {
505 SetLastNtError(_SEH2_GetExceptionCode());
506 }
507 _SEH2_END;
508
509 return pti;
510 }
511
512
513 /* EOF */