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)
22 ULONG Size
= sizeof(WCHAR
) * (MAX_PATH
+ 12);
23 OBJECT_ATTRIBUTES ObAttr
;
24 // http://support.microsoft.com/kb/324097
25 ULONG Ret
= 0x409; // English
27 UNICODE_STRING Language
;
29 RtlInitUnicodeString( &Language
,
30 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Language");
32 InitializeObjectAttributes( &ObAttr
,
38 if ( NT_SUCCESS(ZwOpenKey(&KeyHandle
, KEY_READ
, &ObAttr
)))
40 KeyInfo
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_STRING
);
43 RtlInitUnicodeString(&Language
, L
"Default");
45 if ( NT_SUCCESS(ZwQueryValueKey( KeyHandle
,
47 KeyValuePartialInformation
,
52 RtlInitUnicodeString(&Language
, (PVOID
)((char *)KeyInfo
+ 12));
53 RtlUnicodeStringToInteger(&Language
, 16, &Ret
);
55 ExFreePoolWithTag(KeyInfo
, TAG_STRING
);
59 DPRINT("Language ID = %x\n",Ret
);
72 DPRINT("Enter NtUserGetThreadState\n");
73 if (Routine
!= THREADSTATE_GETTHREADINFO
)
84 case THREADSTATE_GETTHREADINFO
:
87 case THREADSTATE_FOCUSWINDOW
:
88 ret
= (DWORD_PTR
)IntGetThreadFocusWindow();
90 case THREADSTATE_CAPTUREWINDOW
:
91 /* FIXME should use UserEnterShared */
92 ret
= (DWORD_PTR
)IntGetCapture();
94 case THREADSTATE_PROGMANWINDOW
:
95 ret
= (DWORD_PTR
)GetW32ThreadInfo()->pDeskInfo
->hProgmanWindow
;
97 case THREADSTATE_TASKMANWINDOW
:
98 ret
= (DWORD_PTR
)GetW32ThreadInfo()->pDeskInfo
->hTaskManWindow
;
100 case THREADSTATE_ACTIVEWINDOW
:
101 ret
= (DWORD_PTR
)UserGetActiveWindow();
103 case THREADSTATE_INSENDMESSAGE
:
105 DWORD Ret
= ISMEX_NOSEND
;
106 PUSER_MESSAGE_QUEUE MessageQueue
=
107 ((PTHREADINFO
)PsGetCurrentThreadWin32Thread())->MessageQueue
;
108 DPRINT1("THREADSTATE_INSENDMESSAGE\n");
110 if (!IsListEmpty(&MessageQueue
->SentMessagesListHead
))
114 else if (!IsListEmpty(&MessageQueue
->NotifyMessagesListHead
))
116 /* FIXME Need to set message flag when in callback mode with notify */
119 /* FIXME Need to set message flag if replied to or ReplyMessage */
122 case THREADSTATE_GETMESSAGETIME
:
123 /* FIXME Needs more work! */
124 RETURN( ((PTHREADINFO
)PsGetCurrentThreadWin32Thread())->timeLast
);
126 case THREADSTATE_GETINPUTSTATE
:
127 RETURN( HIWORD(IntGetQueueStatus(FALSE
)) & (QS_KEY
| QS_MOUSEBUTTON
));
130 DPRINT("Leave NtUserGetThreadState, ret=%i\n", ret
);
139 NtUserGetDoubleClickTime(VOID
)
143 PWINSTATION_OBJECT WinStaObject
;
144 PSYSTEM_CURSORINFO CurInfo
;
145 DECLARE_RETURN(UINT
);
147 DPRINT("Enter NtUserGetDoubleClickTime\n");
150 Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
154 if (!NT_SUCCESS(Status
))
155 RETURN( (DWORD
)FALSE
);
157 CurInfo
= IntGetSysCursorInfo(WinStaObject
);
158 Result
= CurInfo
->DblClickSpeed
;
160 ObDereferenceObject(WinStaObject
);
164 DPRINT("Leave NtUserGetDoubleClickTime, ret=%i\n",_ret_
);
171 NtUserGetGUIThreadInfo(
172 DWORD idThread
, /* if NULL use foreground thread */
173 LPGUITHREADINFO lpgui
)
176 PTHRDCARETINFO CaretInfo
;
177 GUITHREADINFO SafeGui
;
179 PUSER_MESSAGE_QUEUE MsgQueue
;
180 PETHREAD Thread
= NULL
;
181 DECLARE_RETURN(BOOLEAN
);
183 DPRINT("Enter NtUserGetGUIThreadInfo\n");
186 Status
= MmCopyFromCaller(&SafeGui
, lpgui
, sizeof(DWORD
));
187 if(!NT_SUCCESS(Status
))
189 SetLastNtError(Status
);
193 if(SafeGui
.cbSize
!= sizeof(GUITHREADINFO
))
195 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
201 Status
= PsLookupThreadByThreadId((HANDLE
)(DWORD_PTR
)idThread
, &Thread
);
202 if(!NT_SUCCESS(Status
))
204 SetLastWin32Error(ERROR_ACCESS_DENIED
);
207 Desktop
= ((PTHREADINFO
)Thread
->Tcb
.Win32Thread
)->Desktop
;
211 /* get the foreground thread */
212 PTHREADINFO W32Thread
= (PTHREADINFO
)PsGetCurrentThread()->Tcb
.Win32Thread
;
213 Desktop
= W32Thread
->Desktop
;
216 MsgQueue
= Desktop
->ActiveMessageQueue
;
219 Thread
= MsgQueue
->Thread
;
224 if(!Thread
|| !Desktop
)
226 if(idThread
&& Thread
)
227 ObDereferenceObject(Thread
);
228 SetLastWin32Error(ERROR_ACCESS_DENIED
);
232 MsgQueue
= (PUSER_MESSAGE_QUEUE
)Desktop
->ActiveMessageQueue
;
233 CaretInfo
= MsgQueue
->CaretInfo
;
235 SafeGui
.flags
= (CaretInfo
->Visible
? GUI_CARETBLINKING
: 0);
236 if(MsgQueue
->MenuOwner
)
237 SafeGui
.flags
|= GUI_INMENUMODE
| MsgQueue
->MenuState
;
238 if(MsgQueue
->MoveSize
)
239 SafeGui
.flags
|= GUI_INMOVESIZE
;
241 /* FIXME add flag GUI_16BITTASK */
243 SafeGui
.hwndActive
= MsgQueue
->ActiveWindow
;
244 SafeGui
.hwndFocus
= MsgQueue
->FocusWindow
;
245 SafeGui
.hwndCapture
= MsgQueue
->CaptureWindow
;
246 SafeGui
.hwndMenuOwner
= MsgQueue
->MenuOwner
;
247 SafeGui
.hwndMoveSize
= MsgQueue
->MoveSize
;
248 SafeGui
.hwndCaret
= CaretInfo
->hWnd
;
250 SafeGui
.rcCaret
.left
= CaretInfo
->Pos
.x
;
251 SafeGui
.rcCaret
.top
= CaretInfo
->Pos
.y
;
252 SafeGui
.rcCaret
.right
= SafeGui
.rcCaret
.left
+ CaretInfo
->Size
.cx
;
253 SafeGui
.rcCaret
.bottom
= SafeGui
.rcCaret
.top
+ CaretInfo
->Size
.cy
;
256 ObDereferenceObject(Thread
);
258 Status
= MmCopyToCaller(lpgui
, &SafeGui
, sizeof(GUITHREADINFO
));
259 if(!NT_SUCCESS(Status
))
261 SetLastNtError(Status
);
268 DPRINT("Leave NtUserGetGUIThreadInfo, ret=%i\n",_ret_
);
276 NtUserGetGuiResources(
281 PW32PROCESS W32Process
;
284 DECLARE_RETURN(DWORD
);
286 DPRINT("Enter NtUserGetGuiResources\n");
289 Status
= ObReferenceObjectByHandle(hProcess
,
290 PROCESS_QUERY_INFORMATION
,
296 if(!NT_SUCCESS(Status
))
298 SetLastNtError(Status
);
302 W32Process
= (PW32PROCESS
)Process
->Win32Process
;
305 ObDereferenceObject(Process
);
306 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
314 Ret
= (DWORD
)W32Process
->GDIHandleCount
;
319 Ret
= (DWORD
)W32Process
->UserHandleCount
;
324 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
329 ObDereferenceObject(Process
);
334 DPRINT("Leave NtUserGetGuiResources, ret=%i\n",_ret_
);
340 IntSafeCopyUnicodeString(PUNICODE_STRING Dest
,
341 PUNICODE_STRING Source
)
346 Status
= MmCopyFromCaller(Dest
, Source
, sizeof(UNICODE_STRING
));
347 if(!NT_SUCCESS(Status
))
352 if(Dest
->Length
> 0x4000)
354 return STATUS_UNSUCCESSFUL
;
359 Dest
->MaximumLength
= Dest
->Length
;
361 if(Dest
->Length
> 0 && Src
)
363 Dest
->Buffer
= ExAllocatePoolWithTag(PagedPool
, Dest
->MaximumLength
, TAG_STRING
);
366 return STATUS_NO_MEMORY
;
369 Status
= MmCopyFromCaller(Dest
->Buffer
, Src
, Dest
->Length
);
370 if(!NT_SUCCESS(Status
))
372 ExFreePoolWithTag(Dest
->Buffer
, TAG_STRING
);
378 return STATUS_SUCCESS
;
381 /* string is empty */
382 return STATUS_SUCCESS
;
386 IntSafeCopyUnicodeStringTerminateNULL(PUNICODE_STRING Dest
,
387 PUNICODE_STRING Source
)
392 Status
= MmCopyFromCaller(Dest
, Source
, sizeof(UNICODE_STRING
));
393 if(!NT_SUCCESS(Status
))
398 if(Dest
->Length
> 0x4000)
400 return STATUS_UNSUCCESSFUL
;
405 Dest
->MaximumLength
= 0;
407 if(Dest
->Length
> 0 && Src
)
409 Dest
->MaximumLength
= Dest
->Length
+ sizeof(WCHAR
);
410 Dest
->Buffer
= ExAllocatePoolWithTag(PagedPool
, Dest
->MaximumLength
, TAG_STRING
);
413 return STATUS_NO_MEMORY
;
416 Status
= MmCopyFromCaller(Dest
->Buffer
, Src
, Dest
->Length
);
417 if(!NT_SUCCESS(Status
))
419 ExFreePoolWithTag(Dest
->Buffer
, TAG_STRING
);
424 /* make sure the string is null-terminated */
425 Src
= (PWSTR
)((PBYTE
)Dest
->Buffer
+ Dest
->Length
);
428 return STATUS_SUCCESS
;
431 /* string is empty */
432 return STATUS_SUCCESS
;
436 IntUnicodeStringToNULLTerminated(PWSTR
*Dest
, PUNICODE_STRING Src
)
438 if (Src
->Length
+ sizeof(WCHAR
) <= Src
->MaximumLength
439 && L
'\0' == Src
->Buffer
[Src
->Length
/ sizeof(WCHAR
)])
441 /* The unicode_string is already nul terminated. Just reuse it. */
443 return STATUS_SUCCESS
;
446 *Dest
= ExAllocatePoolWithTag(PagedPool
, Src
->Length
+ sizeof(WCHAR
), TAG_STRING
);
449 return STATUS_NO_MEMORY
;
451 RtlCopyMemory(*Dest
, Src
->Buffer
, Src
->Length
);
452 (*Dest
)[Src
->Length
/ 2] = L
'\0';
454 return STATUS_SUCCESS
;
458 IntFreeNULLTerminatedFromUnicodeString(PWSTR NullTerminated
, PUNICODE_STRING UnicodeString
)
460 if (NullTerminated
!= UnicodeString
->Buffer
)
462 ExFreePool(NullTerminated
);
467 GetW32ProcessInfo(VOID
)
470 PW32PROCESS W32Process
= PsGetCurrentProcessWin32Process();
472 if (W32Process
== NULL
)
474 /* FIXME - temporary hack for system threads... */
478 if (W32Process
->ProcessInfo
== NULL
)
480 pi
= UserHeapAlloc(sizeof(PROCESSINFO
));
484 sizeof(PROCESSINFO
));
487 pi
->UserHandleTable
= gHandleTable
;
488 pi
->hUserHeap
= W32Process
->HeapMappings
.KernelMapping
;
489 pi
->UserHeapDelta
= (ULONG_PTR
)W32Process
->HeapMappings
.KernelMapping
-
490 (ULONG_PTR
)W32Process
->HeapMappings
.UserMapping
;
492 if (InterlockedCompareExchangePointer((PVOID
*)&W32Process
->ProcessInfo
,
501 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
505 return W32Process
->ProcessInfo
;
509 GetW32ThreadInfo(VOID
)
515 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
519 /* FIXME - temporary hack for system threads... */
523 /* allocate a THREADINFO structure if neccessary */
524 if (pti
->ThreadInfo
== NULL
)
526 ti
= UserHeapAlloc(sizeof(W32THREADINFO
));
530 sizeof(W32THREADINFO
));
533 ti
->ppi
= ppi
= GetW32ProcessInfo();
534 ti
->fsHooks
= pti
->fsHooks
;
535 pti
->pcti
= &pti
->cti
; // FIXME Need to set it in desktop.c!
536 if (pti
->Desktop
!= NULL
)
538 pti
->pDeskInfo
= ti
->pDeskInfo
= pti
->Desktop
->DesktopInfo
;
542 pti
->pDeskInfo
= ti
->pDeskInfo
= NULL
;
545 pti
->ThreadInfo
= ti
;
547 Teb
= NtCurrentTeb();
548 pci
= GetWin32ClientInfo();
549 pti
->pClientInfo
= pci
;
556 Teb
->Win32ThreadInfo
= UserHeapAddressToUser(pti
->ThreadInfo
);
558 pci
->pClientThreadInfo
= NULL
; // FIXME Need to set it in desktop.c!
560 pci
->fsHooks
= pti
->fsHooks
;
561 /* CI may not have been initialized. */
562 if (!pci
->pDeskInfo
&& pti
->pDeskInfo
)
564 if (!pci
->ulClientDelta
) pci
->ulClientDelta
= DesktopHeapGetUserDelta();
567 (PVOID
)((ULONG_PTR
)pti
->pDeskInfo
- pci
->ulClientDelta
);
570 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
572 SetLastNtError(_SEH2_GetExceptionCode());
578 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
582 return pti
->ThreadInfo
;