[NtUser] Fix Theme Non Client Painting.
[reactos.git] / win32ss / user / ntuser / misc.c
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 SHORT
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 (SHORT) 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 LARGE_INTEGER LargeTickCount;
299 pti = PsGetCurrentThreadWin32Thread();
300 KeQueryTickCount(&LargeTickCount);
301 pti->timeLast = LargeTickCount.u.LowPart;
302 pti->pcti->tickLastMsgChecked = LargeTickCount.u.LowPart;
303 }
304 break;
305
306 case THREADSTATE_GETINPUTSTATE:
307 ret = LOWORD(IntGetQueueStatus(QS_POSTMESSAGE|QS_TIMER|QS_PAINT|QS_SENDMESSAGE|QS_INPUT)) & (QS_KEY | QS_MOUSEBUTTON);
308 break;
309
310 case THREADSTATE_FOREGROUNDTHREAD:
311 ret = (gpqForeground == GetW32ThreadInfo()->MessageQueue);
312 break;
313 case THREADSTATE_GETCURSOR:
314 ret = (DWORD_PTR) (GetW32ThreadInfo()->MessageQueue->CursorObject ?
315 UserHMGetHandle(GetW32ThreadInfo()->MessageQueue->CursorObject) : 0);
316 break;
317 case THREADSTATE_GETMESSAGEEXTRAINFO:
318 ret = (DWORD_PTR)MsqGetMessageExtraInfo();
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;
384 PETHREAD Thread = NULL;
385
386 DECLARE_RETURN(BOOLEAN);
387
388 TRACE("Enter NtUserGetGUIThreadInfo\n");
389 UserEnterShared();
390
391 Status = MmCopyFromCaller(&SafeGui, lpgui, sizeof(DWORD));
392 if(!NT_SUCCESS(Status))
393 {
394 SetLastNtError(Status);
395 RETURN( FALSE);
396 }
397
398 if(SafeGui.cbSize != sizeof(GUITHREADINFO))
399 {
400 EngSetLastError(ERROR_INVALID_PARAMETER);
401 RETURN( FALSE);
402 }
403
404 if (idThread)
405 {
406 Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)idThread, &Thread);
407 if(!NT_SUCCESS(Status))
408 {
409 EngSetLastError(ERROR_ACCESS_DENIED);
410 RETURN( FALSE);
411 }
412 W32Thread = (PTHREADINFO)Thread->Tcb.Win32Thread;
413 Desktop = W32Thread->rpdesk;
414
415 if (!Thread || !Desktop )
416 {
417 if(Thread)
418 ObDereferenceObject(Thread);
419 EngSetLastError(ERROR_ACCESS_DENIED);
420 RETURN( FALSE);
421 }
422
423 if ( W32Thread->MessageQueue )
424 MsgQueue = W32Thread->MessageQueue;
425 else
426 {
427 if ( Desktop ) MsgQueue = Desktop->ActiveMessageQueue;
428 }
429 }
430 else
431 { /* Get the foreground thread */
432 /* FIXME: Handle NULL queue properly? */
433 MsgQueue = IntGetFocusMessageQueue();
434 if(!MsgQueue)
435 {
436 EngSetLastError(ERROR_ACCESS_DENIED);
437 RETURN( FALSE);
438 }
439 }
440
441 CaretInfo = &MsgQueue->CaretInfo;
442
443 SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0);
444 /*
445 if (W32Thread->pMenuState->pGlobalPopupMenu)
446 {
447 SafeGui.flags |= GUI_INMENUMODE;
448
449 if (W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify)
450 SafeGui.hwndMenuOwner = UserHMGetHandle(W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify);
451
452 if (W32Thread->pMenuState->pGlobalPopupMenu->fHasMenuBar)
453 {
454 if (W32Thread->pMenuState->pGlobalPopupMenu->fIsSysMenu)
455 {
456 SafeGui.flags |= GUI_SYSTEMMENUMODE;
457 }
458 }
459 else
460 {
461 SafeGui.flags |= GUI_POPUPMENUMODE;
462 }
463 }
464 */
465 SafeGui.hwndMenuOwner = MsgQueue->MenuOwner;
466
467 if (MsgQueue->MenuOwner)
468 SafeGui.flags |= GUI_INMENUMODE | MsgQueue->MenuState;
469
470 if (MsgQueue->MoveSize)
471 SafeGui.flags |= GUI_INMOVESIZE;
472
473 /* FIXME: Add flag GUI_16BITTASK */
474
475 SafeGui.hwndActive = MsgQueue->spwndActive ? UserHMGetHandle(MsgQueue->spwndActive) : 0;
476 SafeGui.hwndFocus = MsgQueue->spwndFocus ? UserHMGetHandle(MsgQueue->spwndFocus) : 0;
477 SafeGui.hwndCapture = MsgQueue->spwndCapture ? UserHMGetHandle(MsgQueue->spwndCapture) : 0;
478 SafeGui.hwndMoveSize = MsgQueue->MoveSize;
479 SafeGui.hwndCaret = CaretInfo->hWnd;
480
481 SafeGui.rcCaret.left = CaretInfo->Pos.x;
482 SafeGui.rcCaret.top = CaretInfo->Pos.y;
483 SafeGui.rcCaret.right = SafeGui.rcCaret.left + CaretInfo->Size.cx;
484 SafeGui.rcCaret.bottom = SafeGui.rcCaret.top + CaretInfo->Size.cy;
485
486 if (idThread)
487 ObDereferenceObject(Thread);
488
489 Status = MmCopyToCaller(lpgui, &SafeGui, sizeof(GUITHREADINFO));
490 if(!NT_SUCCESS(Status))
491 {
492 SetLastNtError(Status);
493 RETURN( FALSE);
494 }
495
496 RETURN( TRUE);
497
498 CLEANUP:
499 TRACE("Leave NtUserGetGUIThreadInfo, ret=%u\n",_ret_);
500 UserLeave();
501 END_CLEANUP;
502 }
503
504
505 DWORD
506 APIENTRY
507 NtUserGetGuiResources(
508 HANDLE hProcess,
509 DWORD uiFlags)
510 {
511 PEPROCESS Process;
512 PPROCESSINFO W32Process;
513 NTSTATUS Status;
514 DWORD Ret = 0;
515 DECLARE_RETURN(DWORD);
516
517 TRACE("Enter NtUserGetGuiResources\n");
518 UserEnterShared();
519
520 Status = ObReferenceObjectByHandle(hProcess,
521 PROCESS_QUERY_INFORMATION,
522 *PsProcessType,
523 ExGetPreviousMode(),
524 (PVOID*)&Process,
525 NULL);
526
527 if(!NT_SUCCESS(Status))
528 {
529 SetLastNtError(Status);
530 RETURN( 0);
531 }
532
533 W32Process = (PPROCESSINFO)Process->Win32Process;
534 if(!W32Process)
535 {
536 ObDereferenceObject(Process);
537 EngSetLastError(ERROR_INVALID_PARAMETER);
538 RETURN( 0);
539 }
540
541 switch(uiFlags)
542 {
543 case GR_GDIOBJECTS:
544 {
545 Ret = (DWORD)W32Process->GDIHandleCount;
546 break;
547 }
548 case GR_USEROBJECTS:
549 {
550 Ret = (DWORD)W32Process->UserHandleCount;
551 break;
552 }
553 default:
554 {
555 EngSetLastError(ERROR_INVALID_PARAMETER);
556 break;
557 }
558 }
559
560 ObDereferenceObject(Process);
561
562 RETURN( Ret);
563
564 CLEANUP:
565 TRACE("Leave NtUserGetGuiResources, ret=%lu\n",_ret_);
566 UserLeave();
567 END_CLEANUP;
568 }
569
570 VOID FASTCALL
571 IntSetWindowState(PWND pWnd, UINT Flag)
572 {
573 UINT bit;
574 if (gptiCurrent->ppi != pWnd->head.pti->ppi) return;
575 bit = 1 << LOWORD(Flag);
576 TRACE("SWS %x\n",bit);
577 switch(HIWORD(Flag))
578 {
579 case 0:
580 pWnd->state |= bit;
581 break;
582 case 1:
583 pWnd->state2 |= bit;
584 break;
585 case 2:
586 pWnd->ExStyle2 |= bit;
587 break;
588 }
589 }
590
591 VOID FASTCALL
592 IntClearWindowState(PWND pWnd, UINT Flag)
593 {
594 UINT bit;
595 if (gptiCurrent->ppi != pWnd->head.pti->ppi) return;
596 bit = 1 << LOWORD(Flag);
597 TRACE("CWS %x\n",bit);
598 switch(HIWORD(Flag))
599 {
600 case 0:
601 pWnd->state &= ~bit;
602 break;
603 case 1:
604 pWnd->state2 &= ~bit;
605 break;
606 case 2:
607 pWnd->ExStyle2 &= ~bit;
608 break;
609 }
610 }
611
612 NTSTATUS FASTCALL
613 IntSafeCopyUnicodeString(PUNICODE_STRING Dest,
614 PUNICODE_STRING Source)
615 {
616 NTSTATUS Status;
617 PWSTR Src;
618
619 Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING));
620 if(!NT_SUCCESS(Status))
621 {
622 return Status;
623 }
624
625 if(Dest->Length > 0x4000)
626 {
627 return STATUS_UNSUCCESSFUL;
628 }
629
630 Src = Dest->Buffer;
631 Dest->Buffer = NULL;
632 Dest->MaximumLength = Dest->Length;
633
634 if(Dest->Length > 0 && Src)
635 {
636 Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING);
637 if(!Dest->Buffer)
638 {
639 return STATUS_NO_MEMORY;
640 }
641
642 Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length);
643 if(!NT_SUCCESS(Status))
644 {
645 ExFreePoolWithTag(Dest->Buffer, TAG_STRING);
646 Dest->Buffer = NULL;
647 return Status;
648 }
649
650
651 return STATUS_SUCCESS;
652 }
653
654 /* String is empty */
655 return STATUS_SUCCESS;
656 }
657
658 NTSTATUS FASTCALL
659 IntSafeCopyUnicodeStringTerminateNULL(PUNICODE_STRING Dest,
660 PUNICODE_STRING Source)
661 {
662 NTSTATUS Status;
663 PWSTR Src;
664
665 Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING));
666 if(!NT_SUCCESS(Status))
667 {
668 return Status;
669 }
670
671 if(Dest->Length > 0x4000)
672 {
673 return STATUS_UNSUCCESSFUL;
674 }
675
676 Src = Dest->Buffer;
677 Dest->Buffer = NULL;
678 Dest->MaximumLength = 0;
679
680 if(Dest->Length > 0 && Src)
681 {
682 Dest->MaximumLength = Dest->Length + sizeof(WCHAR);
683 Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING);
684 if(!Dest->Buffer)
685 {
686 return STATUS_NO_MEMORY;
687 }
688
689 Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length);
690 if(!NT_SUCCESS(Status))
691 {
692 ExFreePoolWithTag(Dest->Buffer, TAG_STRING);
693 Dest->Buffer = NULL;
694 return Status;
695 }
696
697 /* Make sure the string is null-terminated */
698 Src = (PWSTR)((PBYTE)Dest->Buffer + Dest->Length);
699 *Src = L'\0';
700
701 return STATUS_SUCCESS;
702 }
703
704 /* String is empty */
705 return STATUS_SUCCESS;
706 }
707
708 void UserDbgAssertThreadInfo(BOOL showCaller)
709 {
710 PTEB Teb;
711 PPROCESSINFO ppi;
712 PCLIENTINFO pci;
713 PTHREADINFO pti;
714
715 ppi = PsGetCurrentProcessWin32Process();
716 pti = PsGetCurrentThreadWin32Thread();
717 Teb = NtCurrentTeb();
718 pci = GetWin32ClientInfo();
719
720 ASSERT(Teb);
721 ASSERT(pti);
722 ASSERT(pti->ppi == ppi);
723 ASSERT(pti->pClientInfo == pci);
724 ASSERT(Teb->Win32ThreadInfo == pti);
725 ASSERT(pci->ppi == ppi);
726 ASSERT(pci->fsHooks == pti->fsHooks);
727 ASSERT(pci->ulClientDelta == DesktopHeapGetUserDelta());
728 if (pti->pcti && pci->pDeskInfo)
729 ASSERT(pci->pClientThreadInfo == (PVOID)((ULONG_PTR)pti->pcti - pci->ulClientDelta));
730 if (pti->pcti && IsListEmpty(&pti->SentMessagesListHead))
731 ASSERT((pti->pcti->fsChangeBits & QS_SENDMESSAGE) == 0);
732 if (pti->KeyboardLayout)
733 ASSERT(pci->hKL == pti->KeyboardLayout->hkl);
734 if(pti->rpdesk != NULL)
735 ASSERT(pti->pDeskInfo == pti->rpdesk->pDeskInfo);
736
737 /*too bad we still get this assertion*/
738
739 // Why? Not all flags are passed to the user and doing so could crash the system........
740
741 /* ASSERT(pci->dwTIFlags == pti->TIF_flags); */
742 /* if(pci->dwTIFlags != pti->TIF_flags)
743 {
744 ERR("pci->dwTIFlags(0x%x) doesn't match pti->TIF_flags(0x%x)\n", pci->dwTIFlags, pti->TIF_flags);
745 if(showCaller)
746 {
747 DbgPrint("Caller:\n");
748 KeRosDumpStackFrames(NULL, 10);
749 }
750 pci->dwTIFlags = pti->TIF_flags;
751 }
752 */
753 }
754
755 void
756 NTAPI
757 UserDbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments)
758 {
759 UserDbgAssertThreadInfo(FALSE);
760 }
761
762 ULONG_PTR
763 NTAPI
764 UserDbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult)
765 {
766 /* Make sure that the first syscall is NtUserInitialize */
767 /* too bad this fails */
768 // ASSERT(gpepCSRSS);
769
770 UserDbgAssertThreadInfo(TRUE);
771
772 return ulResult;
773 }
774
775
776 PPROCESSINFO
777 GetW32ProcessInfo(VOID)
778 {
779 return (PPROCESSINFO)PsGetCurrentProcessWin32Process();
780 }
781
782 PTHREADINFO
783 GetW32ThreadInfo(VOID)
784 {
785 UserDbgAssertThreadInfo(TRUE);
786 return (PTHREADINFO)PsGetCurrentThreadWin32Thread();
787 }
788
789
790 NTSTATUS
791 GetProcessLuid(
792 IN PETHREAD Thread OPTIONAL,
793 IN PEPROCESS Process OPTIONAL,
794 OUT PLUID Luid)
795 {
796 NTSTATUS Status;
797 PACCESS_TOKEN Token = NULL;
798 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
799 BOOLEAN CopyOnOpen, EffectiveOnly;
800
801 if (Thread && Process)
802 return STATUS_INVALID_PARAMETER;
803
804 /* If nothing has been specified, use the current thread */
805 if (!Thread && !Process)
806 Thread = PsGetCurrentThread();
807
808 if (Thread)
809 {
810 /* Use a thread token */
811 ASSERT(!Process);
812 Token = PsReferenceImpersonationToken(Thread,
813 &CopyOnOpen,
814 &EffectiveOnly,
815 &ImpersonationLevel);
816
817 /* If we don't have a thread token, use a process token */
818 if (!Token)
819 Process = PsGetThreadProcess(Thread);
820 }
821 if (!Token && Process)
822 {
823 /* Use a process token */
824 Token = PsReferencePrimaryToken(Process);
825
826 /* If we don't have a token, fail */
827 if (!Token)
828 return STATUS_NO_TOKEN;
829 }
830 ASSERT(Token);
831
832 /* Query the LUID */
833 Status = SeQueryAuthenticationIdToken(Token, Luid);
834
835 /* Get rid of the token and return */
836 ObDereferenceObject(Token);
837 return Status;
838 }
839
840 /* EOF */