Exemplo n.º 1
0
/*
 * 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;
}
Exemplo n.º 2
0
/*
 * @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;
}
Exemplo n.º 3
0
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);
}            
Exemplo n.º 4
0
/*
 * @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;
}
Exemplo n.º 5
0
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;
}