NTSTATUS NTAPI UserCreateThreadInfo(struct _ETHREAD *Thread) { struct _EPROCESS *Process; PCLIENTINFO pci; PTHREADINFO ptiCurrent; int i; NTSTATUS Status = STATUS_SUCCESS; PTEB pTeb; LARGE_INTEGER LargeTickCount; Process = Thread->ThreadsProcess; pTeb = NtCurrentTeb(); ASSERT(pTeb); ptiCurrent = ExAllocatePoolWithTag(NonPagedPool, sizeof(THREADINFO), USERTAG_THREADINFO); if (ptiCurrent == NULL) { ERR_CH(UserThread, "Failed to allocate pti for TID %p\n", Thread->Cid.UniqueThread); return STATUS_NO_MEMORY; } TRACE_CH(UserThread,"Create pti 0x%p eThread 0x%p\n", ptiCurrent, Thread); RtlZeroMemory(ptiCurrent, sizeof(THREADINFO)); /* Initialize the THREADINFO */ PsSetThreadWin32Thread(Thread, ptiCurrent, NULL); IntReferenceThreadInfo(ptiCurrent); ptiCurrent->pEThread = Thread; ptiCurrent->ppi = PsGetCurrentProcessWin32Process(); pTeb->Win32ThreadInfo = ptiCurrent; ptiCurrent->pClientInfo = (PCLIENTINFO)pTeb->Win32ClientInfo; TRACE_CH(UserThread, "Allocated pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread); InitializeListHead(&ptiCurrent->WindowListHead); InitializeListHead(&ptiCurrent->W32CallbackListHead); InitializeListHead(&ptiCurrent->PostedMessagesListHead); InitializeListHead(&ptiCurrent->SentMessagesListHead); InitializeListHead(&ptiCurrent->DispatchingMessagesHead); InitializeListHead(&ptiCurrent->LocalDispatchingMessagesHead); InitializeListHead(&ptiCurrent->PtiLink); for (i = 0; i < NB_HOOKS; i++) { InitializeListHead(&ptiCurrent->aphkStart[i]); } ptiCurrent->ptiSibling = ptiCurrent->ppi->ptiList; ptiCurrent->ppi->ptiList = ptiCurrent; ptiCurrent->ppi->cThreads++; ptiCurrent->hEventQueueClient = NULL; Status = ZwCreateEvent(&ptiCurrent->hEventQueueClient, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); if (!NT_SUCCESS(Status)) { goto error; } Status = ObReferenceObjectByHandle(ptiCurrent->hEventQueueClient, 0, *ExEventObjectType, KernelMode, (PVOID*)&ptiCurrent->pEventQueueServer, NULL); if (!NT_SUCCESS(Status)) { ZwClose(ptiCurrent->hEventQueueClient); ptiCurrent->hEventQueueClient = NULL; goto error; } KeQueryTickCount(&LargeTickCount); ptiCurrent->timeLast = LargeTickCount.u.LowPart; ptiCurrent->MessageQueue = MsqCreateMessageQueue(ptiCurrent); if(ptiCurrent->MessageQueue == NULL) { ERR_CH(UserThread,"Failed to allocate message loop\n"); Status = STATUS_NO_MEMORY; goto error; } ptiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout(); if (ptiCurrent->KeyboardLayout) UserReferenceObject(ptiCurrent->KeyboardLayout); ptiCurrent->TIF_flags &= ~TIF_INCLEANUP; if (Process == gpepCSRSS) /* If this thread is owned by CSRSS, mark it as such */ ptiCurrent->TIF_flags |= TIF_CSRSSTHREAD; ptiCurrent->pcti = &ptiCurrent->cti; /* Initialize the CLIENTINFO */ pci = (PCLIENTINFO)pTeb->Win32ClientInfo; RtlZeroMemory(pci, sizeof(CLIENTINFO)); pci->ppi = ptiCurrent->ppi; pci->fsHooks = ptiCurrent->fsHooks; pci->dwTIFlags = ptiCurrent->TIF_flags; if (ptiCurrent->KeyboardLayout) { pci->hKL = ptiCurrent->KeyboardLayout->hkl; pci->CodePage = ptiCurrent->KeyboardLayout->CodePage; } /* Assign a default window station and desktop to the process */ /* Do not try to open a desktop or window station before winlogon initializes */ if(ptiCurrent->ppi->hdeskStartup == NULL && LogonProcess != NULL) { HWINSTA hWinSta = NULL; HDESK hDesk = NULL; UNICODE_STRING DesktopPath; PDESKTOP pdesk; PRTL_USER_PROCESS_PARAMETERS ProcessParams; /* * inherit the thread desktop and process window station (if not yet inherited) from the process startup * info structure. See documentation of CreateProcess() */ ProcessParams = pTeb->ProcessEnvironmentBlock->ProcessParameters; Status = STATUS_UNSUCCESSFUL; if(ProcessParams && ProcessParams->DesktopInfo.Length > 0) { Status = IntSafeCopyUnicodeStringTerminateNULL(&DesktopPath, &ProcessParams->DesktopInfo); } if(!NT_SUCCESS(Status)) { RtlInitUnicodeString(&DesktopPath, NULL); } Status = IntParseDesktopPath(Process, &DesktopPath, &hWinSta, &hDesk); if (DesktopPath.Buffer) ExFreePoolWithTag(DesktopPath.Buffer, TAG_STRING); if(!NT_SUCCESS(Status)) { ERR_CH(UserThread, "Failed to assign default dekstop and winsta to process\n"); goto error; } if(!UserSetProcessWindowStation(hWinSta)) { Status = STATUS_UNSUCCESSFUL; ERR_CH(UserThread,"Failed to set initial process winsta\n"); goto error; } /* Validate the new desktop. */ Status = IntValidateDesktopHandle(hDesk, UserMode, 0, &pdesk); if(!NT_SUCCESS(Status)) { ERR_CH(UserThread,"Failed to validate initial desktop handle\n"); goto error; } /* Store the parsed desktop as the initial desktop */ ptiCurrent->ppi->hdeskStartup = hDesk; ptiCurrent->ppi->rpdeskStartup = pdesk; } if (ptiCurrent->ppi->hdeskStartup != NULL) { if (!IntSetThreadDesktop(ptiCurrent->ppi->hdeskStartup, FALSE)) { ERR_CH(UserThread,"Failed to set thread desktop\n"); Status = STATUS_UNSUCCESSFUL; goto error; } } /* mark the thread as fully initialized */ ptiCurrent->TIF_flags |= TIF_GUITHREADINITIALIZED; if (!(ptiCurrent->ppi->W32PF_flags & (W32PF_ALLOWFOREGROUNDACTIVATE | W32PF_APPSTARTING)) && (gptiForeground && gptiForeground->ppi == ptiCurrent->ppi )) { ptiCurrent->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; } ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; TRACE_CH(UserThread,"UserCreateW32Thread pti 0x%p\n",ptiCurrent); return STATUS_SUCCESS; error: ERR_CH(UserThread,"UserCreateThreadInfo failed! Freeing pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread); UserDestroyThreadInfo(Thread); return Status; }
BOOL APIENTRY NtUserGetObjectInformation( HANDLE hObject, DWORD nIndex, PVOID pvInformation, DWORD nLength, PDWORD nLengthNeeded) { PWINSTATION_OBJECT WinStaObject; PDESKTOP DesktopObject = NULL; NTSTATUS Status; PVOID pvData = NULL; DWORD nDataSize = 0; _SEH2_TRY { if (nLengthNeeded) ProbeForWrite(nLengthNeeded, sizeof(*nLengthNeeded), 1); ProbeForWrite(pvInformation, nLength, 1); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastNtError(_SEH2_GetExceptionCode()); return FALSE; } _SEH2_END; /* try windowstation */ TRACE("Trying to open window station %p\n", hObject); Status = ObReferenceObjectByHandle(hObject, 0, ExWindowStationObjectType, UserMode, (PVOID*)&WinStaObject, NULL); if (Status == STATUS_OBJECT_TYPE_MISMATCH) { /* try desktop */ TRACE("Trying to open desktop %p\n", hObject); WinStaObject = NULL; Status = IntValidateDesktopHandle(hObject, UserMode, 0, &DesktopObject); } if (!NT_SUCCESS(Status)) { ERR("Failed: 0x%x\n", Status); goto Exit; } TRACE("WinSta or Desktop opened!!\n"); /* get data */ switch (nIndex) { case UOI_FLAGS: nDataSize = sizeof(USEROBJECTFLAGS); if (nLength >= nDataSize) { PUSEROBJECTFLAGS ObjectFlags = pvInformation; ObjectFlags->fInherit = 0; ObjectFlags->fReserved = 0; ObjectFlags->dwFlags = 0; Status = STATUS_SUCCESS; } else { Status = STATUS_BUFFER_TOO_SMALL; } ERR("UOI_FLAGS unimplemented!\n"); break; case UOI_NAME: if (WinStaObject != NULL) { pvData = WinStaObject->Name.Buffer; nDataSize = WinStaObject->Name.Length + sizeof(WCHAR); Status = STATUS_SUCCESS; } else if (DesktopObject != NULL) { pvData = DesktopObject->pDeskInfo->szDesktopName; nDataSize = (wcslen(DesktopObject->pDeskInfo->szDesktopName) + 1) * sizeof(WCHAR); Status = STATUS_SUCCESS; } else Status = STATUS_INVALID_PARAMETER; break; case UOI_TYPE: if (WinStaObject != NULL) { pvData = L"WindowStation"; nDataSize = sizeof(L"WindowStation"); Status = STATUS_SUCCESS; } else if (DesktopObject != NULL) { pvData = L"Desktop"; nDataSize = sizeof(L"Desktop"); Status = STATUS_SUCCESS; } else Status = STATUS_INVALID_PARAMETER; break; case UOI_USER_SID: Status = STATUS_NOT_IMPLEMENTED; ERR("UOI_USER_SID unimplemented!\n"); break; default: Status = STATUS_INVALID_PARAMETER; break; } Exit: if (Status == STATUS_SUCCESS && nLength < nDataSize) Status = STATUS_BUFFER_TOO_SMALL; _SEH2_TRY { if (nLengthNeeded) *nLengthNeeded = nDataSize; /* try to copy data to caller */ if (Status == STATUS_SUCCESS) { TRACE("Trying to copy data to caller (len = %lu, len needed = %lu)\n", nLength, nDataSize); RtlCopyMemory(pvInformation, pvData, nDataSize); } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; /* release objects */ if (WinStaObject != NULL) ObDereferenceObject(WinStaObject); if (DesktopObject != NULL) ObDereferenceObject(DesktopObject); if (!NT_SUCCESS(Status)) { SetLastNtError(Status); return FALSE; } return TRUE; }
BOOL APIENTRY NtUserGetObjectInformation( HANDLE hObject, DWORD nIndex, PVOID pvInformation, DWORD nLength, PDWORD nLengthNeeded) { PWINSTATION_OBJECT WinStaObject = NULL; PDESKTOP DesktopObject = NULL; NTSTATUS Status; PVOID pvData = NULL; DWORD nDataSize = 0; /* try windowstation */ TRACE("Trying to open window station 0x%x\n", hObject); Status = ObReferenceObjectByHandle( hObject, 0, ExWindowStationObjectType, UserMode, (PVOID*)&WinStaObject, NULL); if (Status == STATUS_OBJECT_TYPE_MISMATCH) { /* try desktop */ TRACE("Trying to open desktop 0x%x\n", hObject); Status = IntValidateDesktopHandle( hObject, UserMode, 0, &DesktopObject); } if (!NT_SUCCESS(Status)) { ERR("Failed: 0x%x\n", Status); SetLastNtError(Status); return FALSE; } TRACE("WinSta or Desktop opened!!\n"); /* get data */ switch (nIndex) { case UOI_FLAGS: Status = STATUS_NOT_IMPLEMENTED; ERR("UOI_FLAGS unimplemented!\n"); break; case UOI_NAME: if (WinStaObject != NULL) { pvData = WinStaObject->Name.Buffer; nDataSize = WinStaObject->Name.Length + sizeof(WCHAR); Status = STATUS_SUCCESS; } else if (DesktopObject != NULL) { pvData = DesktopObject->pDeskInfo->szDesktopName; nDataSize = (wcslen(DesktopObject->pDeskInfo->szDesktopName) + 1) * sizeof(WCHAR); Status = STATUS_SUCCESS; } else Status = STATUS_INVALID_PARAMETER; break; case UOI_TYPE: if (WinStaObject != NULL) { pvData = L"WindowStation"; nDataSize = sizeof(L"WindowStation"); Status = STATUS_SUCCESS; } else if (DesktopObject != NULL) { pvData = L"Desktop"; nDataSize = sizeof(L"Desktop"); Status = STATUS_SUCCESS; } else Status = STATUS_INVALID_PARAMETER; break; case UOI_USER_SID: Status = STATUS_NOT_IMPLEMENTED; ERR("UOI_USER_SID unimplemented!\n"); break; default: Status = STATUS_INVALID_PARAMETER; break; } /* try to copy data to caller */ if (Status == STATUS_SUCCESS) { TRACE("Trying to copy data to caller (len = %d, len needed = %d)\n", nLength, nDataSize); *nLengthNeeded = nDataSize; if (nLength >= nDataSize) Status = MmCopyToCaller(pvInformation, pvData, nDataSize); else Status = STATUS_BUFFER_TOO_SMALL; } /* release objects */ if (WinStaObject != NULL) ObDereferenceObject(WinStaObject); if (DesktopObject != NULL) ObDereferenceObject(DesktopObject); if (!NT_SUCCESS(Status)) { SetLastNtError(Status); return FALSE; } return TRUE; }