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