xref: /reactos/win32ss/user/ntuser/misc.c (revision ea6e7740)
1 /*
2  * COPYRIGHT:        See COPYING in the top level directory
3  * PROJECT:          ReactOS Win32k subsystem
4  * PURPOSE:          Miscellaneous User functions
5  * FILE:             win32ss/user/ntuser/misc.c
6  * PROGRAMER:        Ge van Geldorp (ge@gse.nl)
7  */
8 
9 #include <win32k.h>
10 DBG_DEFAULT_CHANNEL(UserMisc);
11 
12 
13 /*
14  * NOTE: _scwprintf() is NOT exported by ntoskrnl.exe,
15  * only _vscwprintf() is, so we need to implement it here.
16  * Code comes from sdk/lib/crt/printf/_scwprintf.c .
17  * See also win32ss/user/winsrv/usersrv/harderror.c .
18  */
19 int
20 __cdecl
21 _scwprintf(
22     const wchar_t *format,
23     ...)
24 {
25     int len;
26     va_list args;
27 
28     va_start(args, format);
29     len = _vscwprintf(format, args);
30     va_end(args);
31 
32     return len;
33 }
34 
35 
36 /*
37  * Test the Thread to verify and validate it. Hard to the core tests are required.
38  */
39 PTHREADINFO
40 FASTCALL
41 IntTID2PTI(HANDLE id)
42 {
43    NTSTATUS Status;
44    PETHREAD Thread;
45    PTHREADINFO pti;
46    Status = PsLookupThreadByThreadId(id, &Thread);
47    if (!NT_SUCCESS(Status))
48    {
49       return NULL;
50    }
51    if (PsIsThreadTerminating(Thread))
52    {
53       ObDereferenceObject(Thread);
54       return NULL;
55    }
56    pti = PsGetThreadWin32Thread(Thread);
57    if (!pti)
58    {
59       ObDereferenceObject(Thread);
60       return NULL;
61    }
62    // Validate and verify!
63    _SEH2_TRY
64    {
65       if (pti->TIF_flags & TIF_INCLEANUP) pti = NULL;
66       if (pti && !(pti->TIF_flags & TIF_GUITHREADINITIALIZED)) pti = NULL;
67       if (PsGetThreadId(Thread) != id) pti = NULL;
68    }
69    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
70    {
71       pti = NULL;
72    }
73    _SEH2_END
74    ObDereferenceObject(Thread);
75    return pti;
76 }
77 
78 DWORD
79 FASTCALL
80 UserGetLanguageToggle(VOID)
81 {
82     NTSTATUS Status;
83     DWORD dwValue = 0;
84 
85     Status = RegReadUserSetting(L"Keyboard Layout\\Toggle", L"Layout Hotkey", REG_SZ, &dwValue, sizeof(dwValue));
86     if (NT_SUCCESS(Status))
87     {
88         dwValue = atoi((char *)&dwValue);
89         TRACE("Layout Hotkey %d\n",dwValue);
90     }
91     return dwValue;
92 }
93 
94 USHORT
95 FASTCALL
96 UserGetLanguageID(VOID)
97 {
98   HANDLE KeyHandle;
99   OBJECT_ATTRIBUTES ObAttr;
100 //  http://support.microsoft.com/kb/324097
101   ULONG Ret = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
102   PKEY_VALUE_PARTIAL_INFORMATION pKeyInfo;
103   ULONG Size = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + MAX_PATH*sizeof(WCHAR);
104   UNICODE_STRING Language;
105 
106   RtlInitUnicodeString( &Language,
107     L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Language");
108 
109   InitializeObjectAttributes( &ObAttr,
110                               &Language,
111                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
112                               NULL,
113                               NULL);
114 
115   if ( NT_SUCCESS(ZwOpenKey(&KeyHandle, KEY_READ, &ObAttr)))
116   {
117      pKeyInfo = ExAllocatePoolWithTag(PagedPool, Size, TAG_STRING);
118      if ( pKeyInfo )
119      {
120         RtlInitUnicodeString(&Language, L"Default");
121 
122         if ( NT_SUCCESS(ZwQueryValueKey( KeyHandle,
123                                          &Language,
124                         KeyValuePartialInformation,
125                                           pKeyInfo,
126                                               Size,
127                                              &Size)) )
128       {
129         RtlInitUnicodeString(&Language, (PWSTR)pKeyInfo->Data);
130         if (!NT_SUCCESS(RtlUnicodeStringToInteger(&Language, 16, &Ret)))
131         {
132             Ret = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
133         }
134       }
135       ExFreePoolWithTag(pKeyInfo, TAG_STRING);
136     }
137     ZwClose(KeyHandle);
138   }
139   TRACE("Language ID = %x\n",Ret);
140   return (USHORT) Ret;
141 }
142 
143 HBRUSH
144 FASTCALL
145 GetControlColor(
146    PWND pwndParent,
147    PWND pwnd,
148    HDC hdc,
149    UINT CtlMsg)
150 {
151     HBRUSH hBrush;
152 
153     if (!pwndParent) pwndParent = pwnd;
154 
155     if ( pwndParent->head.pti->ppi != PsGetCurrentProcessWin32Process())
156     {
157        return (HBRUSH)IntDefWindowProc( pwndParent, CtlMsg, (WPARAM)hdc, (LPARAM)UserHMGetHandle(pwnd), FALSE);
158     }
159 
160     hBrush = (HBRUSH)co_IntSendMessage( UserHMGetHandle(pwndParent), CtlMsg, (WPARAM)hdc, (LPARAM)UserHMGetHandle(pwnd));
161 
162     if (!hBrush || !GreIsHandleValid(hBrush))
163     {
164        hBrush = (HBRUSH)IntDefWindowProc( pwndParent, CtlMsg, (WPARAM)hdc, (LPARAM)UserHMGetHandle(pwnd), FALSE);
165     }
166     return hBrush;
167 }
168 
169 HBRUSH
170 FASTCALL
171 GetControlBrush(
172    PWND pwnd,
173    HDC  hdc,
174    UINT ctlType)
175 {
176     PWND pwndParent = IntGetParent(pwnd);
177     return GetControlColor( pwndParent, pwnd, hdc, ctlType);
178 }
179 
180 HBRUSH
181 APIENTRY
182 NtUserGetControlBrush(
183    HWND hwnd,
184    HDC  hdc,
185    UINT ctlType)
186 {
187    PWND pwnd;
188    HBRUSH hBrush = NULL;
189 
190    UserEnterExclusive();
191    if ( (pwnd = UserGetWindowObject(hwnd)) &&
192        ((ctlType - WM_CTLCOLORMSGBOX) < CTLCOLOR_MAX) &&
193         hdc )
194    {
195       hBrush = GetControlBrush(pwnd, hdc, ctlType);
196    }
197    UserLeave();
198    return hBrush;
199 }
200 
201 /*
202  * Called from PaintRect, works almost like wine PaintRect16 but returns hBrush.
203  */
204 HBRUSH
205 APIENTRY
206 NtUserGetControlColor(
207    HWND hwndParent,
208    HWND hwnd,
209    HDC hdc,
210    UINT CtlMsg) // Wine PaintRect: WM_CTLCOLORMSGBOX + hbrush
211 {
212    PWND pwnd, pwndParent = NULL;
213    HBRUSH hBrush = NULL;
214 
215    UserEnterExclusive();
216    if ( (pwnd = UserGetWindowObject(hwnd)) &&
217        ((CtlMsg - WM_CTLCOLORMSGBOX) < CTLCOLOR_MAX) &&
218         hdc )
219    {
220       if (hwndParent) pwndParent = UserGetWindowObject(hwndParent);
221       hBrush = GetControlColor( pwndParent, pwnd, hdc, CtlMsg);
222    }
223    UserLeave();
224    return hBrush;
225 }
226 
227 /*
228  * @unimplemented
229  */
230 DWORD_PTR APIENTRY
231 NtUserGetThreadState(
232    DWORD Routine)
233 {
234    DWORD_PTR ret = 0;
235 
236    TRACE("Enter NtUserGetThreadState\n");
237    if (Routine != THREADSTATE_GETTHREADINFO)
238    {
239        UserEnterShared();
240    }
241    else
242    {
243        UserEnterExclusive();
244    }
245 
246    switch (Routine)
247    {
248       case THREADSTATE_GETTHREADINFO:
249          GetW32ThreadInfo();
250          break;
251       case THREADSTATE_FOCUSWINDOW:
252          ret = (DWORD_PTR)IntGetThreadFocusWindow();
253          break;
254       case THREADSTATE_CAPTUREWINDOW:
255          /* FIXME: Should use UserEnterShared */
256          ret = (DWORD_PTR)IntGetCapture();
257          break;
258       case THREADSTATE_PROGMANWINDOW:
259          ret = (DWORD_PTR)GetW32ThreadInfo()->pDeskInfo->hProgmanWindow;
260          break;
261       case THREADSTATE_TASKMANWINDOW:
262          ret = (DWORD_PTR)GetW32ThreadInfo()->pDeskInfo->hTaskManWindow;
263          break;
264       case THREADSTATE_ACTIVEWINDOW:
265          ret = (DWORD_PTR)UserGetActiveWindow();
266          break;
267       case THREADSTATE_INSENDMESSAGE:
268          {
269            PUSER_SENT_MESSAGE Message =
270                 ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->pusmCurrent;
271            TRACE("THREADSTATE_INSENDMESSAGE\n");
272 
273            ret = ISMEX_NOSEND;
274            if (Message)
275            {
276              if (Message->ptiSender)
277                 ret = ISMEX_SEND;
278              else
279              {
280                 if (Message->CompletionCallback)
281                    ret = ISMEX_CALLBACK;
282                 else
283                    ret = ISMEX_NOTIFY;
284              }
285              /* If ReplyMessage */
286              if (Message->QS_Flags & QS_SMRESULT) ret |= ISMEX_REPLIED;
287            }
288 
289            break;
290          }
291       case THREADSTATE_GETMESSAGETIME:
292          ret = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->timeLast;
293          break;
294 
295       case THREADSTATE_UPTIMELASTREAD:
296          {
297            PTHREADINFO pti;
298            pti = PsGetCurrentThreadWin32Thread();
299            pti->pcti->timeLastRead = EngGetTickCount32();
300            break;
301          }
302 
303       case THREADSTATE_GETINPUTSTATE:
304          ret = LOWORD(IntGetQueueStatus(QS_POSTMESSAGE|QS_TIMER|QS_PAINT|QS_SENDMESSAGE|QS_INPUT)) & (QS_KEY | QS_MOUSEBUTTON);
305          break;
306 
307       case THREADSTATE_FOREGROUNDTHREAD:
308          ret = (gpqForeground == GetW32ThreadInfo()->MessageQueue);
309          break;
310       case THREADSTATE_GETCURSOR:
311          ret = (DWORD_PTR) (GetW32ThreadInfo()->MessageQueue->CursorObject ?
312                             UserHMGetHandle(GetW32ThreadInfo()->MessageQueue->CursorObject) : 0);
313          break;
314       case THREADSTATE_GETMESSAGEEXTRAINFO:
315          ret = (DWORD_PTR)MsqGetMessageExtraInfo();
316         break;
317       case THREADSTATE_UNKNOWN13:
318          ret = FALSE; /* FIXME: See imm32 */
319          break;
320    }
321 
322    TRACE("Leave NtUserGetThreadState, ret=%lu\n", ret);
323    UserLeave();
324 
325    return ret;
326 }
327 
328 DWORD
329 APIENTRY
330 NtUserSetThreadState(
331    DWORD Set,
332    DWORD Flags)
333 {
334    PTHREADINFO pti;
335    DWORD Ret = 0;
336    // Test the only flags user can change.
337    if (Set & ~(QF_FF10STATUS|QF_DIALOGACTIVE|QF_TABSWITCHING|QF_FMENUSTATUS|QF_FMENUSTATUSBREAK)) return 0;
338    if (Flags & ~(QF_FF10STATUS|QF_DIALOGACTIVE|QF_TABSWITCHING|QF_FMENUSTATUS|QF_FMENUSTATUSBREAK)) return 0;
339    UserEnterExclusive();
340    pti = PsGetCurrentThreadWin32Thread();
341    if (pti->MessageQueue)
342    {
343       Ret = pti->MessageQueue->QF_flags;    // Get the queue flags.
344       if (Set)
345          pti->MessageQueue->QF_flags |= (Set&Flags); // Set the queue flags.
346       else
347       {
348          if (Flags) pti->MessageQueue->QF_flags &= ~Flags; // Clr the queue flags.
349       }
350    }
351    UserLeave();
352    return Ret;
353 }
354 
355 UINT
356 APIENTRY
357 NtUserGetDoubleClickTime(VOID)
358 {
359    UINT Result;
360 
361    TRACE("Enter NtUserGetDoubleClickTime\n");
362    UserEnterShared();
363 
364    // FIXME: Check if this works on non-interactive winsta
365    Result = gspv.iDblClickTime;
366 
367    TRACE("Leave NtUserGetDoubleClickTime, ret=%u\n", Result);
368    UserLeave();
369    return Result;
370 }
371 
372 BOOL
373 APIENTRY
374 NtUserGetGUIThreadInfo(
375    DWORD idThread, /* If NULL use foreground thread */
376    LPGUITHREADINFO lpgui)
377 {
378    NTSTATUS Status;
379    PTHRDCARETINFO CaretInfo;
380    GUITHREADINFO SafeGui;
381    PDESKTOP Desktop;
382    PUSER_MESSAGE_QUEUE MsgQueue;
383    PTHREADINFO W32Thread, pti;
384 
385    DECLARE_RETURN(BOOLEAN);
386 
387    TRACE("Enter NtUserGetGUIThreadInfo\n");
388    UserEnterShared();
389 
390    Status = MmCopyFromCaller(&SafeGui, lpgui, sizeof(DWORD));
391    if(!NT_SUCCESS(Status))
392    {
393       SetLastNtError(Status);
394       RETURN( FALSE);
395    }
396 
397    if(SafeGui.cbSize != sizeof(GUITHREADINFO))
398    {
399       EngSetLastError(ERROR_INVALID_PARAMETER);
400       RETURN( FALSE);
401    }
402 
403    if (idThread)
404    {
405       pti = PsGetCurrentThreadWin32Thread();
406 
407       // Validate Tread ID
408       W32Thread = IntTID2PTI((HANDLE)(DWORD_PTR)idThread);
409 
410       if ( !W32Thread )
411       {
412           EngSetLastError(ERROR_ACCESS_DENIED);
413           RETURN( FALSE);
414       }
415 
416       Desktop = W32Thread->rpdesk;
417 
418       // Check Desktop and it must be the same as current.
419       if ( !Desktop || Desktop != pti->rpdesk )
420       {
421           EngSetLastError(ERROR_ACCESS_DENIED);
422           RETURN( FALSE);
423       }
424 
425       if ( W32Thread->MessageQueue )
426         MsgQueue = W32Thread->MessageQueue;
427       else
428       {
429         if ( Desktop ) MsgQueue = Desktop->ActiveMessageQueue;
430       }
431    }
432    else
433    {  /* Get the foreground thread */
434       /* FIXME: Handle NULL queue properly? */
435       MsgQueue = IntGetFocusMessageQueue();
436       if(!MsgQueue)
437       {
438         EngSetLastError(ERROR_ACCESS_DENIED);
439         RETURN( FALSE);
440       }
441    }
442 
443    CaretInfo = &MsgQueue->CaretInfo;
444 
445    SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0);
446 /*
447    if (W32Thread->pMenuState->pGlobalPopupMenu)
448    {
449        SafeGui.flags |= GUI_INMENUMODE;
450 
451        if (W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify)
452           SafeGui.hwndMenuOwner = UserHMGetHandle(W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify);
453 
454        if (W32Thread->pMenuState->pGlobalPopupMenu->fHasMenuBar)
455        {
456           if (W32Thread->pMenuState->pGlobalPopupMenu->fIsSysMenu)
457           {
458              SafeGui.flags |= GUI_SYSTEMMENUMODE;
459           }
460        }
461        else
462        {
463           SafeGui.flags |= GUI_POPUPMENUMODE;
464        }
465    }
466  */
467    SafeGui.hwndMenuOwner = MsgQueue->MenuOwner;
468 
469    if (MsgQueue->MenuOwner)
470       SafeGui.flags |= GUI_INMENUMODE | MsgQueue->MenuState;
471 
472    if (MsgQueue->MoveSize)
473       SafeGui.flags |= GUI_INMOVESIZE;
474 
475    /* FIXME: Add flag GUI_16BITTASK */
476 
477    SafeGui.hwndActive = MsgQueue->spwndActive ? UserHMGetHandle(MsgQueue->spwndActive) : 0;
478    SafeGui.hwndFocus = MsgQueue->spwndFocus ? UserHMGetHandle(MsgQueue->spwndFocus) : 0;
479    SafeGui.hwndCapture = MsgQueue->spwndCapture ? UserHMGetHandle(MsgQueue->spwndCapture) : 0;
480    SafeGui.hwndMoveSize = MsgQueue->MoveSize;
481    SafeGui.hwndCaret = CaretInfo->hWnd;
482 
483    SafeGui.rcCaret.left = CaretInfo->Pos.x;
484    SafeGui.rcCaret.top = CaretInfo->Pos.y;
485    SafeGui.rcCaret.right = SafeGui.rcCaret.left + CaretInfo->Size.cx;
486    SafeGui.rcCaret.bottom = SafeGui.rcCaret.top + CaretInfo->Size.cy;
487 
488    Status = MmCopyToCaller(lpgui, &SafeGui, sizeof(GUITHREADINFO));
489    if(!NT_SUCCESS(Status))
490    {
491       SetLastNtError(Status);
492       RETURN( FALSE);
493    }
494 
495    RETURN( TRUE);
496 
497 CLEANUP:
498    TRACE("Leave NtUserGetGUIThreadInfo, ret=%u\n",_ret_);
499    UserLeave();
500    END_CLEANUP;
501 }
502 
503 
504 DWORD
505 APIENTRY
506 NtUserGetGuiResources(
507    HANDLE hProcess,
508    DWORD uiFlags)
509 {
510    PEPROCESS Process;
511    PPROCESSINFO W32Process;
512    NTSTATUS Status;
513    DWORD Ret = 0;
514    DECLARE_RETURN(DWORD);
515 
516    TRACE("Enter NtUserGetGuiResources\n");
517    UserEnterShared();
518 
519    Status = ObReferenceObjectByHandle(hProcess,
520                                       PROCESS_QUERY_INFORMATION,
521                                       *PsProcessType,
522                                       ExGetPreviousMode(),
523                                       (PVOID*)&Process,
524                                       NULL);
525 
526    if(!NT_SUCCESS(Status))
527    {
528       SetLastNtError(Status);
529       RETURN( 0);
530    }
531 
532    W32Process = (PPROCESSINFO)Process->Win32Process;
533    if(!W32Process)
534    {
535       ObDereferenceObject(Process);
536       EngSetLastError(ERROR_INVALID_PARAMETER);
537       RETURN( 0);
538    }
539 
540    switch(uiFlags)
541    {
542       case GR_GDIOBJECTS:
543          {
544             Ret = (DWORD)W32Process->GDIHandleCount;
545             break;
546          }
547       case GR_USEROBJECTS:
548          {
549             Ret = (DWORD)W32Process->UserHandleCount;
550             break;
551          }
552       default:
553          {
554             EngSetLastError(ERROR_INVALID_PARAMETER);
555             break;
556          }
557    }
558 
559    ObDereferenceObject(Process);
560 
561    RETURN( Ret);
562 
563 CLEANUP:
564    TRACE("Leave NtUserGetGuiResources, ret=%lu\n",_ret_);
565    UserLeave();
566    END_CLEANUP;
567 }
568 
569 VOID FASTCALL
570 IntSetWindowState(PWND pWnd, UINT Flag)
571 {
572    UINT bit;
573    if (gptiCurrent->ppi != pWnd->head.pti->ppi) return;
574    bit = 1 << LOWORD(Flag);
575    TRACE("SWS %x\n",bit);
576    switch(HIWORD(Flag))
577    {
578       case 0:
579           pWnd->state |= bit;
580           break;
581       case 1:
582           pWnd->state2 |= bit;
583           break;
584       case 2:
585           pWnd->ExStyle2 |= bit;
586           break;
587    }
588 }
589 
590 VOID FASTCALL
591 IntClearWindowState(PWND pWnd, UINT Flag)
592 {
593    UINT bit;
594    if (gptiCurrent->ppi != pWnd->head.pti->ppi) return;
595    bit = 1 << LOWORD(Flag);
596    TRACE("CWS %x\n",bit);
597    switch(HIWORD(Flag))
598    {
599       case 0:
600           pWnd->state &= ~bit;
601           break;
602       case 1:
603           pWnd->state2 &= ~bit;
604           break;
605       case 2:
606           pWnd->ExStyle2 &= ~bit;
607           break;
608    }
609 }
610 
611 NTSTATUS FASTCALL
612 IntSafeCopyUnicodeString(PUNICODE_STRING Dest,
613                          PUNICODE_STRING Source)
614 {
615    NTSTATUS Status;
616    PWSTR Src;
617 
618    Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING));
619    if(!NT_SUCCESS(Status))
620    {
621       return Status;
622    }
623 
624    if(Dest->Length > 0x4000)
625    {
626       return STATUS_UNSUCCESSFUL;
627    }
628 
629    Src = Dest->Buffer;
630    Dest->Buffer = NULL;
631    Dest->MaximumLength = Dest->Length;
632 
633    if(Dest->Length > 0 && Src)
634    {
635       Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING);
636       if(!Dest->Buffer)
637       {
638          return STATUS_NO_MEMORY;
639       }
640 
641       Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length);
642       if(!NT_SUCCESS(Status))
643       {
644          ExFreePoolWithTag(Dest->Buffer, TAG_STRING);
645          Dest->Buffer = NULL;
646          return Status;
647       }
648 
649 
650       return STATUS_SUCCESS;
651    }
652 
653    /* String is empty */
654    return STATUS_SUCCESS;
655 }
656 
657 NTSTATUS FASTCALL
658 IntSafeCopyUnicodeStringTerminateNULL(PUNICODE_STRING Dest,
659                                       PUNICODE_STRING Source)
660 {
661    NTSTATUS Status;
662    PWSTR Src;
663 
664    Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING));
665    if(!NT_SUCCESS(Status))
666    {
667       return Status;
668    }
669 
670    if(Dest->Length > 0x4000)
671    {
672       return STATUS_UNSUCCESSFUL;
673    }
674 
675    Src = Dest->Buffer;
676    Dest->Buffer = NULL;
677    Dest->MaximumLength = 0;
678 
679    if(Dest->Length > 0 && Src)
680    {
681       Dest->MaximumLength = Dest->Length + sizeof(WCHAR);
682       Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING);
683       if(!Dest->Buffer)
684       {
685          return STATUS_NO_MEMORY;
686       }
687 
688       Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length);
689       if(!NT_SUCCESS(Status))
690       {
691          ExFreePoolWithTag(Dest->Buffer, TAG_STRING);
692          Dest->Buffer = NULL;
693          return Status;
694       }
695 
696       /* Make sure the string is null-terminated */
697       Src = (PWSTR)((PBYTE)Dest->Buffer + Dest->Length);
698       *Src = L'\0';
699 
700       return STATUS_SUCCESS;
701    }
702 
703    /* String is empty */
704    return STATUS_SUCCESS;
705 }
706 
707 void UserDbgAssertThreadInfo(BOOL showCaller)
708 {
709     PTEB Teb;
710     PPROCESSINFO ppi;
711     PCLIENTINFO pci;
712     PTHREADINFO pti;
713 
714     ppi = PsGetCurrentProcessWin32Process();
715     pti = PsGetCurrentThreadWin32Thread();
716     Teb = NtCurrentTeb();
717     pci = GetWin32ClientInfo();
718 
719     ASSERT(Teb);
720     ASSERT(pti);
721     ASSERT(pti->ppi == ppi);
722     ASSERT(pti->pClientInfo == pci);
723     ASSERT(Teb->Win32ThreadInfo == pti);
724     ASSERT(pci->ppi == ppi);
725     ASSERT(pci->fsHooks == pti->fsHooks);
726     ASSERT(pci->ulClientDelta == DesktopHeapGetUserDelta());
727     if (pti->pcti && pci->pDeskInfo)
728         ASSERT(pci->pClientThreadInfo == (PVOID)((ULONG_PTR)pti->pcti - pci->ulClientDelta));
729     //if (pti->pcti && IsListEmpty(&pti->SentMessagesListHead))
730     //    ASSERT((pti->pcti->fsChangeBits & QS_SENDMESSAGE) == 0);
731     if (pti->KeyboardLayout)
732         ASSERT(pci->hKL == pti->KeyboardLayout->hkl);
733     if(pti->rpdesk != NULL)
734         ASSERT(pti->pDeskInfo == pti->rpdesk->pDeskInfo);
735 
736     /*too bad we still get this assertion*/
737 
738     // Why? Not all flags are passed to the user and doing so could crash the system........
739 
740     /* ASSERT(pci->dwTIFlags == pti->TIF_flags); */
741 /*    if(pci->dwTIFlags != pti->TIF_flags)
742     {
743         ERR("pci->dwTIFlags(0x%x) doesn't match pti->TIF_flags(0x%x)\n", pci->dwTIFlags, pti->TIF_flags);
744         if(showCaller)
745         {
746             DbgPrint("Caller:\n");
747             KeRosDumpStackFrames(NULL, 10);
748         }
749         pci->dwTIFlags = pti->TIF_flags;
750     }
751 */
752 }
753 
754 void
755 NTAPI
756 UserDbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments)
757 {
758     UserDbgAssertThreadInfo(FALSE);
759 }
760 
761 ULONG_PTR
762 NTAPI
763 UserDbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult)
764 {
765     /* Make sure that the first syscall is NtUserInitialize */
766     /* too bad this fails */
767     // ASSERT(gpepCSRSS);
768 
769     UserDbgAssertThreadInfo(TRUE);
770 
771     return ulResult;
772 }
773 
774 
775 PPROCESSINFO
776 GetW32ProcessInfo(VOID)
777 {
778     return (PPROCESSINFO)PsGetCurrentProcessWin32Process();
779 }
780 
781 PTHREADINFO
782 GetW32ThreadInfo(VOID)
783 {
784     UserDbgAssertThreadInfo(TRUE);
785     return (PTHREADINFO)PsGetCurrentThreadWin32Thread();
786 }
787 
788 
789 NTSTATUS
790 GetProcessLuid(
791     IN PETHREAD Thread OPTIONAL,
792     IN PEPROCESS Process OPTIONAL,
793     OUT PLUID Luid)
794 {
795     NTSTATUS Status;
796     PACCESS_TOKEN Token = NULL;
797     SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
798     BOOLEAN CopyOnOpen, EffectiveOnly;
799 
800     if (Thread && Process)
801         return STATUS_INVALID_PARAMETER;
802 
803     /* If nothing has been specified, use the current thread */
804     if (!Thread && !Process)
805         Thread = PsGetCurrentThread();
806 
807     if (Thread)
808     {
809         /* Use a thread token */
810         ASSERT(!Process);
811         Token = PsReferenceImpersonationToken(Thread,
812                                               &CopyOnOpen,
813                                               &EffectiveOnly,
814                                               &ImpersonationLevel);
815 
816         /* If we don't have a thread token, use a process token */
817         if (!Token)
818             Process = PsGetThreadProcess(Thread);
819     }
820     if (!Token && Process)
821     {
822         /* Use a process token */
823         Token = PsReferencePrimaryToken(Process);
824 
825         /* If we don't have a token, fail */
826         if (!Token)
827             return STATUS_NO_TOKEN;
828     }
829     ASSERT(Token);
830 
831     /* Query the LUID */
832     Status = SeQueryAuthenticationIdToken(Token, Luid);
833 
834     /* Get rid of the token and return */
835     ObDereferenceObject(Token);
836     return Status;
837 }
838 
839 /* EOF */
840