NTSTATUS APIENTRY Win32kThreadCallback(struct _ETHREAD *Thread, PSW32THREADCALLOUTTYPE Type) { NTSTATUS Status; UserEnterExclusive(); ASSERT(NtCurrentTeb()); if (Type == PsW32ThreadCalloutInitialize) { ASSERT(PsGetThreadWin32Thread(Thread) == NULL); Status = UserCreateThreadInfo(Thread); } else { ASSERT(PsGetThreadWin32Thread(Thread) != NULL); Status = UserDestroyThreadInfo(Thread); } UserLeave(); return Status; }
/* * UserGetKeyboardLayout * * Returns hkl of given thread keyboard layout */ HKL FASTCALL UserGetKeyboardLayout( DWORD dwThreadId) { NTSTATUS Status; PETHREAD pThread; PTHREADINFO pti; PKL pKl; HKL hKl; if (!dwThreadId) { pti = PsGetCurrentThreadWin32Thread(); pKl = pti->KeyboardLayout; return pKl ? pKl->hkl : NULL; } Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)dwThreadId, &pThread); if (!NT_SUCCESS(Status)) { EngSetLastError(ERROR_INVALID_PARAMETER); return NULL; } pti = PsGetThreadWin32Thread(pThread); pKl = pti->KeyboardLayout; hKl = pKl ? pKl->hkl : NULL;; ObDereferenceObject(pThread); return hKl; }
/* * Test the Thread to verify and validate it. Hard to the core tests are required. */ PTHREADINFO FASTCALL IntTID2PTI(HANDLE id) { NTSTATUS Status; PETHREAD Thread; PTHREADINFO pti; Status = PsLookupThreadByThreadId(id, &Thread); if (!NT_SUCCESS(Status)) { return NULL; } if (PsIsThreadTerminating(Thread)) { ObDereferenceObject(Thread); return NULL; } pti = PsGetThreadWin32Thread(Thread); if (!pti) { ObDereferenceObject(Thread); return NULL; } // Validate and verify! _SEH2_TRY { if (pti->TIF_flags & TIF_INCLEANUP) pti = NULL; if (pti && !(pti->TIF_flags & TIF_GUITHREADINITIALIZED)) pti = NULL; if (PsGetThreadId(Thread) != id) pti = NULL; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { pti = NULL; } _SEH2_END ObDereferenceObject(Thread); return pti; }
NTSTATUS DispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); PDEVICE_EXTENSION extension = DeviceObject->DeviceExtension; switch(irpStack->Parameters.DeviceIoControl.IoControlCode){ case IOCTL_GET_HOOKS: { unsigned int i,j; PETHREAD pethread; PTHREADINFO ptiCurrent; PDESKTOPINFO pdesktopinfo; PPROCESSINFO ppi; PARAMS_GET_HOOKS *params; DATA_GET_HOOKS *data; PHOOK* aphkStart; if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DATA_GET_HOOKS)) { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(PARAMS_GET_HOOKS)) { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } params = ExAllocatePoolWithTag(PagedPool, sizeof(PARAMS_GET_HOOKS), 'tdkh'); if (!params) { break; } memcpy(params, Irp->AssociatedIrp.SystemBuffer, sizeof(PARAMS_GET_HOOKS)); pethread = PsGetCurrentThread(); ptiCurrent = PsGetThreadWin32Thread(pethread); if (g_win7) { pdesktopinfo = (PDESKTOPINFO)((unsigned int*)ptiCurrent)[0xCC/4]; ppi = (PPROCESSINFO)&((char*)ptiCurrent)[0xB8]; aphkStart = (PHOOK*)&((char*)pdesktopinfo)[0x10]; } else { pdesktopinfo = ptiCurrent->pDeskInfo; ppi = ptiCurrent->ppi; aphkStart = pdesktopinfo->aphkStart; } data = (DATA_GET_HOOKS*)Irp->AssociatedIrp.SystemBuffer; memset(data, 0, sizeof(DATA_GET_HOOKS)); retrieve_hooks(aphkStart, ppi, data->global_hook); data->threads=0; j=0; for (i=0;i<params->threads;i++) { if (PsLookupThreadByThreadId((HANDLE)params->thread_id[i], &pethread) != STATUS_SUCCESS) { continue; } if (g_win7) { if (PsGetThreadSessionId(pethread) != PsGetCurrentProcessSessionId()) { ObDereferenceObject(pethread); continue; } } ptiCurrent = PsGetThreadWin32Thread(pethread); if (ptiCurrent) { if (g_win7) { aphkStart = (PHOOK*)&((char*)ptiCurrent)[0x198]; ppi = (PPROCESSINFO)&((char*)ptiCurrent)[0xB8]; } else { aphkStart = (PHOOK*)&((char*)ptiCurrent)[0xf4]; ppi = ptiCurrent->ppi; } if (has_hooks(aphkStart)) { data->threads++; if (j<MAX_OUT_THREADS) { retrieve_hooks(aphkStart, ppi, data->thread[j].hook); data->thread[j].thread_id = params->thread_id[i]; j++; } } } ObDereferenceObject(pethread); } ExFreePool(params); ntStatus = STATUS_SUCCESS; break; } case IOCTL_HMOD_TBL_INX_TO_MOD_NAME: { DATA_HMOD_TBL_INX_TO_MOD_NAME *data; PARAMS_HMOD_TBL_INX_TO_MOD_NAME *params; WCHAR tmp; int hmod_table_index; if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DATA_HMOD_TBL_INX_TO_MOD_NAME)) { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(PARAMS_HMOD_TBL_INX_TO_MOD_NAME)) { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } params = Irp->AssociatedIrp.SystemBuffer; UserGetAtomName = (UserGetAtomName_ptr)params->UserGetAtomName_address; aatomSysLoaded = (ATOM*)params->aatomSysLoaded_address; hmod_table_index = params->hmod_table_index; if (UserGetAtomName && aatomSysLoaded) { __try { (*UserGetAtomName)(aatomSysLoaded[0], &tmp, 1); } __except (EXCEPTION_EXECUTE_HANDLER) { UserGetAtomName = 0; } } data = Irp->AssociatedIrp.SystemBuffer; if (UserGetAtomName) { (*UserGetAtomName)(aatomSysLoaded[hmod_table_index], data->module_name, MAX_PATH); } else { data->module_name[0] = 0; } ntStatus = STATUS_SUCCESS; break; } }
NTSTATUS NTAPI UserDestroyThreadInfo(struct _ETHREAD *Thread) { PTHREADINFO *ppti; PSINGLE_LIST_ENTRY psle; PPROCESSINFO ppiCurrent; struct _EPROCESS *Process; PTHREADINFO ptiCurrent; Process = Thread->ThreadsProcess; /* Get the Win32 Thread */ ptiCurrent = PsGetThreadWin32Thread(Thread); ASSERT(ptiCurrent); TRACE_CH(UserThread,"Destroying pti 0x%p eThread 0x%p\n", ptiCurrent, Thread); ptiCurrent->TIF_flags |= TIF_INCLEANUP; ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; ppiCurrent = ptiCurrent->ppi; ASSERT(ppiCurrent); IsRemoveAttachThread(ptiCurrent); ptiCurrent->TIF_flags |= TIF_DONTATTACHQUEUE; ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; /* Decrement thread count and check if its 0 */ ppiCurrent->cThreads--; if(ptiCurrent->TIF_flags & TIF_GUITHREADINITIALIZED) { /* Do now some process cleanup that requires a valid win32 thread */ if(ptiCurrent->ppi->cThreads == 0) { /* Check if we have registered the user api hook */ if(ptiCurrent->ppi == ppiUahServer) { /* Unregister the api hook */ UserUnregisterUserApiHook(); } /* Notify logon application to restart shell if needed */ if(ptiCurrent->pDeskInfo) { if(ptiCurrent->pDeskInfo->ppiShellProcess == ppiCurrent) { DWORD ExitCode = PsGetProcessExitStatus(Process); TRACE_CH(UserProcess, "Shell process is exiting (%lu)\n", ExitCode); UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_SHELL_EXITED, ExitCode); ptiCurrent->pDeskInfo->ppiShellProcess = NULL; } } } DceFreeThreadDCE(ptiCurrent); HOOK_DestroyThreadHooks(Thread); EVENT_DestroyThreadEvents(Thread); DestroyTimersForThread(ptiCurrent); KeSetEvent(ptiCurrent->pEventQueueServer, IO_NO_INCREMENT, FALSE); UnregisterThreadHotKeys(ptiCurrent); /* if (IsListEmpty(&ptiCurrent->WindowListHead)) { ERR_CH(UserThread,"Thread Window List is Empty!\n"); } */ co_DestroyThreadWindows(Thread); if (ppiCurrent && ppiCurrent->ptiList == ptiCurrent && !ptiCurrent->ptiSibling && ppiCurrent->W32PF_flags & W32PF_CLASSESREGISTERED) { TRACE_CH(UserThread,"DestroyProcessClasses\n"); /* no process windows should exist at this point, or the function will assert! */ DestroyProcessClasses(ppiCurrent); ppiCurrent->W32PF_flags &= ~W32PF_CLASSESREGISTERED; } IntBlockInput(ptiCurrent, FALSE); IntCleanupThreadCallbacks(ptiCurrent); /* cleanup user object references stack */ psle = PopEntryList(&ptiCurrent->ReferencesList); while (psle) { PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(psle, USER_REFERENCE_ENTRY, Entry); TRACE_CH(UserThread,"thread clean: remove reference obj 0x%p\n",ref->obj); UserDereferenceObject(ref->obj); psle = PopEntryList(&ptiCurrent->ReferencesList); } } /* Find the THREADINFO in the PROCESSINFO's list */ ppti = &ppiCurrent->ptiList; while (*ppti != NULL && *ppti != ptiCurrent) { ppti = &((*ppti)->ptiSibling); } /* we must have found it */ ASSERT(*ppti == ptiCurrent); /* Remove it from the list */ *ppti = ptiCurrent->ptiSibling; if (ptiCurrent->KeyboardLayout) UserDereferenceObject(ptiCurrent->KeyboardLayout); if (gptiForeground == ptiCurrent) { // IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0); // IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, NULL, OBJID_WINDOW, CHILDID_SELF, 0); gptiForeground = NULL; } // Fixes CORE-6384 & CORE-7030. /* if (ptiLastInput == ptiCurrent) { if (!ppiCurrent->ptiList) ptiLastInput = gptiForeground; else ptiLastInput = ppiCurrent->ptiList; ERR_CH(UserThread,"DTI: ptiLastInput is Cleared!!\n"); } */ TRACE_CH(UserThread,"Freeing pti 0x%p\n", ptiCurrent); /* Free the THREADINFO */ IntDereferenceThreadInfo(ptiCurrent); return STATUS_SUCCESS; }