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