2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Miscellaneous User functions
5 * FILE: subsystems/win32/win32k/ntuser/misc.c
6 * PROGRAMER: Ge van Geldorp (ge@gse.nl)
10 DBG_DEFAULT_CHANNEL(UserMisc
);
14 UserGetLanguageID(VOID
)
17 OBJECT_ATTRIBUTES ObAttr
;
18 // http://support.microsoft.com/kb/324097
19 ULONG Ret
= 0x409; // English
20 PKEY_VALUE_PARTIAL_INFORMATION pKeyInfo
;
21 ULONG Size
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + MAX_PATH
*sizeof(WCHAR
);
22 UNICODE_STRING Language
;
24 RtlInitUnicodeString( &Language
,
25 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Language");
27 InitializeObjectAttributes( &ObAttr
,
33 if ( NT_SUCCESS(ZwOpenKey(&KeyHandle
, KEY_READ
, &ObAttr
)))
35 pKeyInfo
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_STRING
);
38 RtlInitUnicodeString(&Language
, L
"Default");
40 if ( NT_SUCCESS(ZwQueryValueKey( KeyHandle
,
42 KeyValuePartialInformation
,
47 RtlInitUnicodeString(&Language
, (PWSTR
)pKeyInfo
->Data
);
48 RtlUnicodeStringToInteger(&Language
, 16, &Ret
);
50 ExFreePoolWithTag(pKeyInfo
, TAG_STRING
);
54 TRACE("Language ID = %x\n",Ret
);
68 if (!pwndParent
) pwndParent
= pwnd
;
70 if ( pwndParent
->head
.pti
->ppi
!= PsGetCurrentProcessWin32Process())
72 return (HBRUSH
)IntDefWindowProc( pwndParent
, CtlMsg
, (WPARAM
)hdc
, (LPARAM
)UserHMGetHandle(pwnd
), FALSE
);
75 hBrush
= (HBRUSH
)co_IntSendMessage( UserHMGetHandle(pwndParent
), CtlMsg
, (WPARAM
)hdc
, (LPARAM
)UserHMGetHandle(pwnd
));
77 if (!hBrush
|| !GreIsHandleValid(hBrush
))
79 hBrush
= (HBRUSH
)IntDefWindowProc( pwndParent
, CtlMsg
, (WPARAM
)hdc
, (LPARAM
)UserHMGetHandle(pwnd
), FALSE
);
91 PWND pwndParent
= IntGetParent(pwnd
);
92 return GetControlColor( pwndParent
, pwnd
, hdc
, ctlType
);
97 NtUserGetControlBrush(
103 HBRUSH hBrush
= NULL
;
105 UserEnterExclusive();
106 if ( (pwnd
= UserGetWindowObject(hwnd
)) &&
107 ((ctlType
- WM_CTLCOLORMSGBOX
) < CTLCOLOR_MAX
) &&
110 hBrush
= GetControlBrush(pwnd
, hdc
, ctlType
);
117 * Called from PaintRect, works almost like wine PaintRect16 but returns hBrush.
121 NtUserGetControlColor(
125 UINT CtlMsg
) // Wine PaintRect: WM_CTLCOLORMSGBOX + hbrush
127 PWND pwnd
, pwndParent
= NULL
;
128 HBRUSH hBrush
= NULL
;
130 UserEnterExclusive();
131 if ( (pwnd
= UserGetWindowObject(hwnd
)) &&
132 ((CtlMsg
- WM_CTLCOLORMSGBOX
) < CTLCOLOR_MAX
) &&
135 if (hwndParent
) pwndParent
= UserGetWindowObject(hwndParent
);
136 hBrush
= GetControlColor( pwndParent
, pwnd
, hdc
, CtlMsg
);
146 NtUserGetThreadState(
151 TRACE("Enter NtUserGetThreadState\n");
152 if (Routine
!= THREADSTATE_GETTHREADINFO
)
158 UserEnterExclusive();
163 case THREADSTATE_GETTHREADINFO
:
166 case THREADSTATE_FOCUSWINDOW
:
167 ret
= (DWORD_PTR
)UserGetFocusWindow();
169 case THREADSTATE_CAPTUREWINDOW
:
170 /* FIXME: Should use UserEnterShared */
171 ret
= (DWORD_PTR
)IntGetCapture();
173 case THREADSTATE_PROGMANWINDOW
:
174 ret
= (DWORD_PTR
)GetW32ThreadInfo()->pDeskInfo
->hProgmanWindow
;
176 case THREADSTATE_TASKMANWINDOW
:
177 ret
= (DWORD_PTR
)GetW32ThreadInfo()->pDeskInfo
->hTaskManWindow
;
179 case THREADSTATE_ACTIVEWINDOW
:
180 ret
= (DWORD_PTR
)UserGetActiveWindow();
182 case THREADSTATE_INSENDMESSAGE
:
184 PUSER_SENT_MESSAGE Message
=
185 ((PTHREADINFO
)PsGetCurrentThreadWin32Thread())->pusmCurrent
;
186 ERR("THREADSTATE_INSENDMESSAGE\n");
191 if (Message
->SenderQueue
)
195 if (Message
->CompletionCallback
)
196 ret
= ISMEX_CALLBACK
;
200 /* If ReplyMessage */
201 if (Message
->QS_Flags
& QS_SMRESULT
) ret
|= ISMEX_REPLIED
;
206 case THREADSTATE_GETMESSAGETIME
:
207 ret
= ((PTHREADINFO
)PsGetCurrentThreadWin32Thread())->timeLast
;
210 case THREADSTATE_UPTIMELASTREAD
:
213 LARGE_INTEGER LargeTickCount
;
214 pti
= PsGetCurrentThreadWin32Thread();
215 KeQueryTickCount(&LargeTickCount
);
216 pti
->MessageQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
217 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
221 case THREADSTATE_GETINPUTSTATE
:
222 ret
= LOWORD(IntGetQueueStatus(QS_POSTMESSAGE
|QS_TIMER
|QS_PAINT
|QS_SENDMESSAGE
|QS_INPUT
)) & (QS_KEY
| QS_MOUSEBUTTON
);
226 TRACE("Leave NtUserGetThreadState, ret=%i\n", ret
);
234 NtUserSetThreadState(
240 // Test the only flags user can change.
241 if (Set
& ~(QF_FF10STATUS
|QF_DIALOGACTIVE
|QF_TABSWITCHING
|QF_FMENUSTATUS
|QF_FMENUSTATUSBREAK
)) return 0;
242 if (Flags
& ~(QF_FF10STATUS
|QF_DIALOGACTIVE
|QF_TABSWITCHING
|QF_FMENUSTATUS
|QF_FMENUSTATUSBREAK
)) return 0;
243 UserEnterExclusive();
244 pti
= PsGetCurrentThreadWin32Thread();
245 if (pti
->MessageQueue
)
247 Ret
= pti
->MessageQueue
->QF_flags
; // Get the queue flags.
249 pti
->MessageQueue
->QF_flags
|= (Set
&Flags
); // Set the queue flags.
252 if (Flags
) pti
->MessageQueue
->QF_flags
&= ~Flags
; // Clr the queue flags.
261 NtUserGetDoubleClickTime(VOID
)
265 TRACE("Enter NtUserGetDoubleClickTime\n");
268 // FIXME: Check if this works on non-interactive winsta
269 Result
= gspv
.iDblClickTime
;
271 TRACE("Leave NtUserGetDoubleClickTime, ret=%i\n", Result
);
278 NtUserGetGUIThreadInfo(
279 DWORD idThread
, /* If NULL use foreground thread */
280 LPGUITHREADINFO lpgui
)
283 PTHRDCARETINFO CaretInfo
;
284 GUITHREADINFO SafeGui
;
286 PUSER_MESSAGE_QUEUE MsgQueue
;
287 PTHREADINFO W32Thread
;
288 PETHREAD Thread
= NULL
;
290 DECLARE_RETURN(BOOLEAN
);
292 TRACE("Enter NtUserGetGUIThreadInfo\n");
295 Status
= MmCopyFromCaller(&SafeGui
, lpgui
, sizeof(DWORD
));
296 if(!NT_SUCCESS(Status
))
298 SetLastNtError(Status
);
302 if(SafeGui
.cbSize
!= sizeof(GUITHREADINFO
))
304 EngSetLastError(ERROR_INVALID_PARAMETER
);
310 Status
= PsLookupThreadByThreadId((HANDLE
)(DWORD_PTR
)idThread
, &Thread
);
311 if(!NT_SUCCESS(Status
))
313 EngSetLastError(ERROR_ACCESS_DENIED
);
316 W32Thread
= (PTHREADINFO
)Thread
->Tcb
.Win32Thread
;
317 Desktop
= W32Thread
->rpdesk
;
320 { /* Get the foreground thread */
321 Thread
= PsGetCurrentThread();
322 W32Thread
= (PTHREADINFO
)Thread
->Tcb
.Win32Thread
;
323 Desktop
= W32Thread
->rpdesk
;
326 if (!Thread
|| !Desktop
)
328 if(idThread
&& Thread
)
329 ObDereferenceObject(Thread
);
330 EngSetLastError(ERROR_ACCESS_DENIED
);
334 if ( W32Thread
->MessageQueue
)
335 MsgQueue
= W32Thread
->MessageQueue
;
338 if ( Desktop
) MsgQueue
= Desktop
->ActiveMessageQueue
;
341 CaretInfo
= MsgQueue
->CaretInfo
;
343 SafeGui
.flags
= (CaretInfo
->Visible
? GUI_CARETBLINKING
: 0);
345 if (MsgQueue
->MenuOwner
)
346 SafeGui
.flags
|= GUI_INMENUMODE
| MsgQueue
->MenuState
;
348 if (MsgQueue
->MoveSize
)
349 SafeGui
.flags
|= GUI_INMOVESIZE
;
351 /* FIXME: Add flag GUI_16BITTASK */
353 SafeGui
.hwndActive
= MsgQueue
->ActiveWindow
;
354 SafeGui
.hwndFocus
= MsgQueue
->FocusWindow
;
355 SafeGui
.hwndCapture
= MsgQueue
->CaptureWindow
;
356 SafeGui
.hwndMenuOwner
= MsgQueue
->MenuOwner
;
357 SafeGui
.hwndMoveSize
= MsgQueue
->MoveSize
;
358 SafeGui
.hwndCaret
= CaretInfo
->hWnd
;
360 SafeGui
.rcCaret
.left
= CaretInfo
->Pos
.x
;
361 SafeGui
.rcCaret
.top
= CaretInfo
->Pos
.y
;
362 SafeGui
.rcCaret
.right
= SafeGui
.rcCaret
.left
+ CaretInfo
->Size
.cx
;
363 SafeGui
.rcCaret
.bottom
= SafeGui
.rcCaret
.top
+ CaretInfo
->Size
.cy
;
366 ObDereferenceObject(Thread
);
368 Status
= MmCopyToCaller(lpgui
, &SafeGui
, sizeof(GUITHREADINFO
));
369 if(!NT_SUCCESS(Status
))
371 SetLastNtError(Status
);
378 TRACE("Leave NtUserGetGUIThreadInfo, ret=%i\n",_ret_
);
386 NtUserGetGuiResources(
391 PPROCESSINFO W32Process
;
394 DECLARE_RETURN(DWORD
);
396 TRACE("Enter NtUserGetGuiResources\n");
399 Status
= ObReferenceObjectByHandle(hProcess
,
400 PROCESS_QUERY_INFORMATION
,
406 if(!NT_SUCCESS(Status
))
408 SetLastNtError(Status
);
412 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
415 ObDereferenceObject(Process
);
416 EngSetLastError(ERROR_INVALID_PARAMETER
);
424 Ret
= (DWORD
)W32Process
->GDIHandleCount
;
429 Ret
= (DWORD
)W32Process
->UserHandleCount
;
434 EngSetLastError(ERROR_INVALID_PARAMETER
);
439 ObDereferenceObject(Process
);
444 TRACE("Leave NtUserGetGuiResources, ret=%i\n",_ret_
);
450 IntSafeCopyUnicodeString(PUNICODE_STRING Dest
,
451 PUNICODE_STRING Source
)
456 Status
= MmCopyFromCaller(Dest
, Source
, sizeof(UNICODE_STRING
));
457 if(!NT_SUCCESS(Status
))
462 if(Dest
->Length
> 0x4000)
464 return STATUS_UNSUCCESSFUL
;
469 Dest
->MaximumLength
= Dest
->Length
;
471 if(Dest
->Length
> 0 && Src
)
473 Dest
->Buffer
= ExAllocatePoolWithTag(PagedPool
, Dest
->MaximumLength
, TAG_STRING
);
476 return STATUS_NO_MEMORY
;
479 Status
= MmCopyFromCaller(Dest
->Buffer
, Src
, Dest
->Length
);
480 if(!NT_SUCCESS(Status
))
482 ExFreePoolWithTag(Dest
->Buffer
, TAG_STRING
);
488 return STATUS_SUCCESS
;
491 /* String is empty */
492 return STATUS_SUCCESS
;
496 IntSafeCopyUnicodeStringTerminateNULL(PUNICODE_STRING Dest
,
497 PUNICODE_STRING Source
)
502 Status
= MmCopyFromCaller(Dest
, Source
, sizeof(UNICODE_STRING
));
503 if(!NT_SUCCESS(Status
))
508 if(Dest
->Length
> 0x4000)
510 return STATUS_UNSUCCESSFUL
;
515 Dest
->MaximumLength
= 0;
517 if(Dest
->Length
> 0 && Src
)
519 Dest
->MaximumLength
= Dest
->Length
+ sizeof(WCHAR
);
520 Dest
->Buffer
= ExAllocatePoolWithTag(PagedPool
, Dest
->MaximumLength
, TAG_STRING
);
523 return STATUS_NO_MEMORY
;
526 Status
= MmCopyFromCaller(Dest
->Buffer
, Src
, Dest
->Length
);
527 if(!NT_SUCCESS(Status
))
529 ExFreePoolWithTag(Dest
->Buffer
, TAG_STRING
);
534 /* Make sure the string is null-terminated */
535 Src
= (PWSTR
)((PBYTE
)Dest
->Buffer
+ Dest
->Length
);
538 return STATUS_SUCCESS
;
541 /* String is empty */
542 return STATUS_SUCCESS
;
545 void UserDbgAssertThreadInfo(BOOL showCaller
)
552 ppi
= PsGetCurrentProcessWin32Process();
553 pti
= PsGetCurrentThreadWin32Thread();
554 Teb
= NtCurrentTeb();
555 pci
= GetWin32ClientInfo();
559 ASSERT(pti
->ppi
== ppi
);
560 ASSERT(pti
->pClientInfo
== pci
);
561 ASSERT(Teb
->Win32ThreadInfo
== pti
);
562 ASSERT(pci
->ppi
== ppi
);
563 ASSERT(pci
->fsHooks
== pti
->fsHooks
);
564 ASSERT(pci
->ulClientDelta
== DesktopHeapGetUserDelta());
565 if (pti
->pcti
&& pci
->pDeskInfo
)
566 ASSERT(pci
->pClientThreadInfo
== (PVOID
)((ULONG_PTR
)pti
->pcti
- pci
->ulClientDelta
));
567 if (pti
->KeyboardLayout
)
568 ASSERT(pci
->hKL
== pti
->KeyboardLayout
->hkl
);
569 if(pti
->rpdesk
!= NULL
)
570 ASSERT(pti
->pDeskInfo
== pti
->rpdesk
->pDeskInfo
);
572 /*too bad we still get this assertion*/
573 /* ASSERT(pci->dwTIFlags == pti->TIF_flags); */
574 if(pci
->dwTIFlags
!= pti
->TIF_flags
)
576 ERR("pci->dwTIFlags(0x%x) doesn't match pti->TIF_flags(0x%x)\n", pci
->dwTIFlags
, pti
->TIF_flags
);
579 DbgPrint("Caller:\n");
580 KeRosDumpStackFrames(NULL
, 10);
582 pci
->dwTIFlags
= pti
->TIF_flags
;
588 UserDbgPreServiceHook(ULONG ulSyscallId
, PULONG_PTR pulArguments
)
590 UserDbgAssertThreadInfo(FALSE
);
595 UserDbgPostServiceHook(ULONG ulSyscallId
, ULONG_PTR ulResult
)
597 /* Make sure that the first syscall is NtUserInitialize */
598 /* too bad this fails */
599 //ASSERT(gbInitialized);
601 UserDbgAssertThreadInfo(TRUE
);
608 GetW32ProcessInfo(VOID
)
610 return (PPROCESSINFO
)PsGetCurrentProcessWin32Process();
614 GetW32ThreadInfo(VOID
)
616 UserDbgAssertThreadInfo(TRUE
);
617 return (PTHREADINFO
)PsGetCurrentThreadWin32Thread();