/* * co_UserActivateKbl * * Activates given layout in specified thread */ static PKL co_UserActivateKbl(PTHREADINFO pti, PKL pKl, UINT Flags) { PKL pklPrev; pklPrev = pti->KeyboardLayout; if (pklPrev) UserDereferenceObject(pklPrev); pti->KeyboardLayout = pKl; pti->pClientInfo->hKL = pKl->hkl; UserReferenceObject(pKl); if (Flags & KLF_SETFORPROCESS) { // FIXME } // Send WM_INPUTLANGCHANGE to thread's focus window co_IntSendMessage(pti->MessageQueue->spwndFocus ? UserHMGetHandle(pti->MessageQueue->spwndFocus) : 0, WM_INPUTLANGCHANGE, (WPARAM)pKl->iBaseCharset, // FIXME: How to set it? (LPARAM)pKl->hkl); // hkl return pklPrev; }
/* * @implemented */ BOOL APIENTRY NtUserGetIconSize( HANDLE hCurIcon, UINT istepIfAniCur, PLONG plcx, // &size.cx PLONG plcy) // &size.cy { PCURICON_OBJECT CurIcon; NTSTATUS Status = STATUS_SUCCESS; BOOL bRet = FALSE; TRACE("Enter NtUserGetIconSize\n"); UserEnterExclusive(); if (!(CurIcon = UserGetCurIconObject(hCurIcon))) { goto cleanup; } if(CurIcon->CURSORF_flags & CURSORF_ACON) { /* Use first frame for animated cursors */ PACON AniCurIcon = (PACON)CurIcon; CurIcon = AniCurIcon->aspcur[0]; UserDereferenceObject(AniCurIcon); UserReferenceObject(CurIcon); } _SEH2_TRY { ProbeForWrite(plcx, sizeof(LONG), 1); *plcx = CurIcon->cx; ProbeForWrite(plcy, sizeof(LONG), 1); *plcy = CurIcon->cy; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END if (NT_SUCCESS(Status)) bRet = TRUE; else SetLastNtError(Status); // Maybe not, test this UserDereferenceObject(CurIcon); cleanup: TRACE("Leave NtUserGetIconSize, ret=%i\n", bRet); UserLeave(); return bRet; }
VOID FASTCALL IntNotifyWinEvent( DWORD Event, PWND pWnd, LONG idObject, LONG idChild, DWORD flags) { PEVENTHOOK pEH; PLIST_ENTRY pLE; PTHREADINFO pti, ptiCurrent; TRACE("IntNotifyWinEvent GlobalEvents = 0x%x pWnd 0x%x\n",GlobalEvents, pWnd); if (!GlobalEvents || !GlobalEvents->Counts) return; if (pWnd && pWnd->state & WNDS_DESTROYED) return; ptiCurrent = PsGetCurrentThreadWin32Thread(); if (pWnd && flags & WEF_SETBYWNDPTI) pti = pWnd->head.pti; else pti = ptiCurrent; pLE = GlobalEvents->Events.Flink; pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain); do { if (!pEH) break; UserReferenceObject(pEH); // Must be inside the event window. if ( (pEH->eventMin <= Event) && (pEH->eventMax >= Event)) { // if all process || all thread || other thread same process // if ^skip own thread && ((Pid && CPid == Pid && ^skip own process) || all process) if ( (!pEH->idProcess || pEH->idProcess == PtrToUint(pti->pEThread->Cid.UniqueProcess)) && (!(pEH->Flags & WINEVENT_SKIPOWNPROCESS) || pEH->head.pti->ppi != pti->ppi) && (!pEH->idThread || pEH->idThread == PtrToUint(pti->pEThread->Cid.UniqueThread)) && (!(pEH->Flags & WINEVENT_SKIPOWNTHREAD) || pEH->head.pti != pti) && pEH->head.pti->rpdesk == ptiCurrent->rpdesk ) // Same as hooks. { // Send message to the thread if pEH is not current. if (pEH->head.pti != ptiCurrent) { ERR("Global Event 0x%x, idObject %d\n", Event, idObject); IntCallLowLevelEvent( pEH, Event, UserHMGetHandle(pWnd), idObject, idChild); } else { ERR("Local Event 0x%x, idObject %d\n", Event, idObject); co_IntCallEventProc( UserHMGetHandle(pEH), Event, UserHMGetHandle(pWnd), idObject, idChild, PtrToUint(NtCurrentTeb()->ClientId.UniqueThread), (DWORD)EngGetTickCount(), pEH->Proc); } } } UserDereferenceObject(pEH); pLE = pEH->Chain.Flink; pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain); } while (pLE != &GlobalEvents->Events); }
/* * @implemented */ BOOL APIENTRY NtUserSetCursorIconData( _In_ HCURSOR Handle, _In_opt_ PUNICODE_STRING pustrModule, _In_opt_ PUNICODE_STRING pustrRsrc, _In_ const CURSORDATA* pCursorData) { PCURICON_OBJECT CurIcon; NTSTATUS Status = STATUS_SUCCESS; BOOLEAN Ret = FALSE; BOOLEAN IsShared = FALSE, IsAnim = FALSE; DWORD numFrames; UINT i = 0; TRACE("Enter NtUserSetCursorIconData\n"); UserEnterExclusive(); if (!(CurIcon = UserGetCurIconObject(Handle))) { UserLeave(); EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } _SEH2_TRY { ProbeForRead(pCursorData, sizeof(*pCursorData), 1); if(pCursorData->CURSORF_flags & CURSORF_ACON) { /* This is an animated cursor */ PACON AniCurIcon = (PACON)CurIcon; DWORD numSteps; numFrames = AniCurIcon->cpcur = pCursorData->cpcur; numSteps = AniCurIcon->cicur = pCursorData->cicur; AniCurIcon->iicur = pCursorData->iicur; AniCurIcon->rt = pCursorData->rt; /* Calculate size: one cursor object for each frame, and a frame index and jiffies for each "step" */ AniCurIcon->aspcur = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, /* Let SEH catch allocation failures */ numFrames * sizeof(CURICON_OBJECT*) + numSteps * (sizeof(DWORD) + sizeof(INT)), USERTAG_CURSOR); AniCurIcon->aicur = (DWORD*)(AniCurIcon->aspcur + numFrames); AniCurIcon->ajifRate = (INT*)(AniCurIcon->aicur + numSteps); RtlZeroMemory(AniCurIcon->aspcur, numFrames * sizeof(CURICON_OBJECT*)); ProbeForRead(pCursorData->aicur, numSteps * sizeof(DWORD), 1); RtlCopyMemory(AniCurIcon->aicur, pCursorData->aicur, numSteps * sizeof(DWORD)); ProbeForRead(pCursorData->ajifRate, numSteps * sizeof(INT), 1); RtlCopyMemory(AniCurIcon->ajifRate, pCursorData->ajifRate, numSteps * sizeof(INT)); AniCurIcon->CURSORF_flags = pCursorData->CURSORF_flags; pCursorData = pCursorData->aspcur; IsAnim = TRUE; } else { CurIcon->xHotspot = pCursorData->xHotspot; CurIcon->yHotspot = pCursorData->yHotspot; CurIcon->cx = pCursorData->cx; CurIcon->cy = pCursorData->cy; CurIcon->rt = pCursorData->rt; CurIcon->bpp = pCursorData->bpp; CurIcon->hbmMask = pCursorData->hbmMask; CurIcon->hbmColor = pCursorData->hbmColor; CurIcon->hbmAlpha = pCursorData->hbmAlpha; CurIcon->CURSORF_flags = pCursorData->CURSORF_flags; } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END if (!NT_SUCCESS(Status)) { SetLastNtError(Status); goto done; } if(IsAnim) { PACON AniCurIcon = (PACON)CurIcon; /* This is an animated cursor. Create a cursor object for each frame and set up the data */ for(i = 0; i < numFrames; i++) { HANDLE hCurFrame = IntCreateCurIconHandle(FALSE); if(!NtUserSetCursorIconData(hCurFrame, NULL, NULL, pCursorData)) goto done; AniCurIcon->aspcur[i] = UserGetCurIconObject(hCurFrame); if(!AniCurIcon->aspcur[i]) goto done; pCursorData++; } } if(CurIcon->CURSORF_flags & CURSORF_LRSHARED) { IsShared = TRUE; if(pustrRsrc && pustrModule) { UNICODE_STRING ustrModuleSafe; /* We use this convenient function, because INTRESOURCEs and ATOMs are the same */ Status = ProbeAndCaptureUnicodeStringOrAtom(&CurIcon->strName, pustrRsrc); if(!NT_SUCCESS(Status)) goto done; Status = ProbeAndCaptureUnicodeString(&ustrModuleSafe, UserMode, pustrModule); if(!NT_SUCCESS(Status)) goto done; Status = RtlAddAtomToAtomTable(gAtomTable, ustrModuleSafe.Buffer, &CurIcon->atomModName); ReleaseCapturedUnicodeString(&ustrModuleSafe, UserMode); if(!NT_SUCCESS(Status)) goto done; } } if(!CurIcon->hbmMask) { ERR("NtUserSetCursorIconData was got no hbmMask.\n"); EngSetLastError(ERROR_INVALID_PARAMETER); goto done; } GreSetObjectOwner(CurIcon->hbmMask, GDI_OBJ_HMGR_PUBLIC); if(CurIcon->hbmColor) GreSetObjectOwner(CurIcon->hbmColor, GDI_OBJ_HMGR_PUBLIC); if(CurIcon->hbmAlpha) GreSetObjectOwner(CurIcon->hbmAlpha, GDI_OBJ_HMGR_PUBLIC); if(IsShared) { /* Update process cache in case of shared cursor */ PPROCESSINFO ppi = CurIcon->head.ppi; UserReferenceObject(CurIcon); CurIcon->pcurNext = ppi->pCursorCache; ppi->pCursorCache = CurIcon; } Ret = TRUE; done: if(!Ret && IsShared) { if(!IS_INTRESOURCE(CurIcon->strName.Buffer)) ExFreePoolWithTag(CurIcon->strName.Buffer, TAG_STRING); } if(!Ret && IsAnim) { PACON AniCurIcon = (PACON)CurIcon; for(i = 0; i < numFrames; i++) { if(AniCurIcon->aspcur[i]) IntDestroyCurIconObject(AniCurIcon->aspcur[i], TRUE); } AniCurIcon->cicur = 0; AniCurIcon->cpcur = 0; ExFreePoolWithTag(AniCurIcon->aspcur, USERTAG_CURSOR); AniCurIcon->aspcur = NULL; AniCurIcon->aicur = NULL; AniCurIcon->ajifRate = NULL; } UserDereferenceObject(CurIcon); TRACE("Leave NtUserSetCursorIconData, ret=%i\n",Ret); UserLeave(); return Ret; }
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; }