示例#1
0
BOOL
GetImeHotKey(
    DWORD dwHotKeyID,
    PUINT puModifiers,
    PUINT puVKey,
    HKL   *phKL )
{
    PIMEHOTKEYOBJ ph;

    ph = FindImeHotKeyByID( gpImeHotKeyListHeader, dwHotKeyID );
    if ( ph == NULL ) {
        RIPERR0(ERROR_HOTKEY_NOT_REGISTERED, RIP_WARNING, "No such IME hotkey");
        return (FALSE);
    }

    //
    // it is OK for NULL phKL, if the target hKL is NULL
    //
    if ( phKL ) {
       *phKL = ph->hk.hKL;
    } else if ( ph->hk.hKL != NULL ) {
        RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "phKL is null");
        return (FALSE);
    } 

    *puModifiers = ph->hk.uModifiers;
    *puVKey = ph->hk.uVKey;

    return (TRUE);
}
示例#2
0
文件: classc.c 项目: conioh/os-design
WORD GetClassWord(
    HWND hwnd,
    int index)
{
    PWND pwnd;
    PCLS pclsClient;

    pwnd = ValidateHwnd(hwnd);

    if (pwnd == NULL)
        return 0;

    pclsClient = (PCLS)REBASEALWAYS(pwnd, pcls);

    if (index == GCW_ATOM) {
        return (WORD)_GetClassData(pclsClient, pwnd, index, FALSE);
    } else {
        if ((index < 0) || (index + (int)sizeof(WORD) > pclsClient->cbclsExtra)) {
            RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
            return 0;
        } else {
            WORD UNALIGNED *puw;
            puw = (WORD UNALIGNED *)((BYTE *)(pclsClient + 1) + index);
            return *puw;
        }
    }
}
示例#3
0
文件: mnapi.c 项目: conioh/os-design
BOOL xxxSetMenu(
    PWND  pwnd,
    PMENU pMenu,
    BOOL  fRedraw)
{
    CheckLock(pwnd);
    CheckLock(pMenu);

    if (!TestwndChild(pwnd)) {

        LockWndMenu(pwnd, &pwnd->spmenu, pMenu);

        /*
         * only redraw the frame if the window is non-minimized --
         * even if it's not visible, we need RedrawFrame to recalc the NC size
         *
         * Added a check for (redraw) since the MDISetMenu() only needs to
         * set the menu and not perform any redraws.
         */
        if (!TestWF(pwnd, WFMINIMIZED) && fRedraw)
            xxxRedrawFrame(pwnd);

        return TRUE;
    }

    RIPERR0(ERROR_CHILD_WINDOW_MENU, RIP_VERBOSE, "");
    return FALSE;
}
示例#4
0
void MNPositionSysMenu(
    PWND pwnd,
    PMENU pmenusys)
{
    RECT rc;
    PITEM pItem;

    if (pmenusys == NULL) {
        RIPERR0(ERROR_INVALID_HANDLE,
                RIP_WARNING,
                "Invalid menu handle pmenusys (NULL) to MNPositionSysMenu");

        return;
    }

    /*
     * Setup the SysMenu hit rectangle.
     */
    rc.top = rc.left = 0;

    if (TestWF(pwnd, WEFTOOLWINDOW)) {
        rc.right = SYSMET(CXSMSIZE);
        rc.bottom = SYSMET(CYSMSIZE);
    } else {
        rc.right = SYSMET(CXSIZE);
        rc.bottom = SYSMET(CYSIZE);
    }

    if (!TestWF(pwnd, WFMINIMIZED)) {
        int cBorders;

        cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE);
        OffsetRect(&rc, cBorders*SYSMET(CXBORDER), cBorders*SYSMET(CYBORDER));
    }

    /*
     * Offset the System popup menu.
     */
    Lock(&pmenusys->spwndNotify, pwnd);

    if (!TestMF(pmenusys, MF_POPUP) && (pmenusys->cItems > 0)) {
        pItem = pmenusys->rgItems;
        if (pItem) {
            pItem->yItem = rc.top;
            pItem->xItem = rc.left;
            pItem->cyItem = rc.bottom - rc.top;
            pItem->cxItem = rc.right - rc.left;
        }
    }
    else
        // BOGUS -- MF_POPUP should never be set on a MENU -- only a MENU ITEM
        UserAssert(FALSE);
}
示例#5
0
int DlgDirSelectComboBoxExW(
    HWND hwndDlg,
    LPWSTR pwszOut,
    int cchOut,
    int idComboBox)
{
    BOOL fRet;
    TL tlpwndComboBox;
    TL tlpwndList;
    PWND pwndDlg;
    PWND pwndComboBox;
    PCBOX pcbox;

    pwndDlg = ValidateHwnd(hwndDlg);

    if (pwndDlg == NULL)
        return FALSE;

    pwndComboBox = _GetDlgItem(pwndDlg, idComboBox);
    if (pwndComboBox == NULL) {
        RIPERR0(ERROR_CONTROL_ID_NOT_FOUND, RIP_VERBOSE, "");
        return 0;
    }
    pcbox = ((PCOMBOWND)pwndComboBox)->pcbox;
    if (pcbox == NULL) {
        RIPERR0(ERROR_WINDOW_NOT_COMBOBOX, RIP_VERBOSE, "");
        return 0;
    }

    ThreadLockAlways(pwndComboBox, &tlpwndComboBox);
    ThreadLock(pcbox->spwndList, &tlpwndList);
    fRet = xxxDlgDirSelectHelper(pwndComboBox, pwszOut, cchOut, pcbox->spwndList);
    ThreadUnlock(&tlpwndList);
    ThreadUnlock(&tlpwndComboBox);

    return fRet;
}
示例#6
0
HANDLE xxxLoadHmodIndex(
    int iatom,
    BOOL bWx86KnownDll)
{
    WCHAR pszLibName[MAX_PATH];
    HANDLE hmod;
    UNICODE_STRING strLibrary;
    PTHREADINFO    ptiCurrent = PtiCurrent();

    UserAssert((!gptiRit || gptiRit->ppi != PtiCurrent()->ppi) &&
                "Shouldn't load global hooks on system process - gptiRit->ppi is the system process");

    if (iatom >= catomSysTableEntries) {
        RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Index out of range");
        return NULL;
    }

    UserGetAtomName(aatomSysLoaded[iatom], pszLibName, sizeof(pszLibName)/sizeof(WCHAR));

    /*
     * Call back the client to load the library.
     */
    RtlInitUnicodeString(&strLibrary, pszLibName);
    hmod = ClientLoadLibrary(&strLibrary, bWx86KnownDll);

    if (hmod != NULL) {
        /*
         * Check to make sure another thread hasn't loaded this library
         * while we were outside the critical section.
         */
        if (!TESTHMODLOADED(ptiCurrent, iatom)) {
            /*
             * Go ahead and bump the reference count.
             */
            acatomSysUse[iatom]++;
            SETHMODLOADED(ptiCurrent, iatom, hmod);

        } else {
            /*
             * Another thread loaded it while we were outside the
             * critical section.  Unload it so the system's
             * reference count is correct.
             */
            ClientFreeLibrary(ptiCurrent->ppi->ahmodLibLoaded[iatom]);
        }
    }

    return hmod;
}
示例#7
0
BOOL _UnregisterHotKey(
    PWND pwnd,
    int id)
{
    PHOTKEY phk;
    BOOL fKeysExist;

    phk = FindHotKey(PtiCurrent(), pwnd, id, 0, 0, TRUE, &fKeysExist);

    /*
     * No hotkey to unregister, return FALSE.
     */
    if (phk == NULL) {
        RIPERR0(ERROR_HOTKEY_NOT_REGISTERED, RIP_VERBOSE, "");
        return FALSE;
    }

    return TRUE;
}
示例#8
0
文件: classc.c 项目: conioh/os-design
ULONG_PTR _GetClassLongPtr(
    PWND pwnd,
    int index,
    BOOL bAnsi)
{
    PCLS pcls = REBASEALWAYS(pwnd, pcls);

    if (index < 0) {
        return _GetClassData(pcls, pwnd, index, bAnsi);
    } else {
        if (index + (int)sizeof(ULONG_PTR) > pcls->cbclsExtra) {
            RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
            return 0;
        } else {
            ULONG_PTR UNALIGNED *pudw;
            pudw = (ULONG_PTR UNALIGNED *)((BYTE *)(pcls + 1) + index);
            return *pudw;
        }
    }
}
示例#9
0
文件: mnapi.c 项目: conioh/os-design
BOOL xxxSetSystemMenu(
    PWND pwnd,
    PMENU pMenu)
{
    CheckLock(pwnd);
    CheckLock(pMenu);

    if (TestWF(pwnd, WFSYSMENU)) {
        PMENU pmenuT = pwnd->spmenuSys;
        if (LockWndMenu(pwnd, &pwnd->spmenuSys, pMenu))
            _DestroyMenu(pmenuT);

        MNPositionSysMenu(pwnd, pMenu);

        return TRUE;
    }

    RIPERR0(ERROR_NO_SYSTEM_MENU, RIP_VERBOSE, "");
    return FALSE;
}
示例#10
0
文件: sbapi.c 项目: conioh/os-design
BOOL SetScrollRange(
    HWND hwnd,
    int code,
    int posMin,
    int posMax,
    BOOL fRedraw)
{
    SCROLLINFO si;

    /*
     * Validate the window handle first, because the further call
     * to NtUserSetScrollInfo will return the position of the scrollbar
     * and not FALSE if the hwnd is invalid
     */
    if ( ValidateHwnd((hwnd)) == NULL)
        return FALSE;

    /*
     * Check if the 'Range'(Max - Min) can be represented by an integer;
     * If not, it is an error;
     * Fix for Bug #1089 -- SANKAR -- 20th Sep, 1989 --.
     */
    if ((unsigned int)(posMax - posMin) > MAXLONG) {
        RIPERR0(ERROR_INVALID_SCROLLBAR_RANGE, RIP_VERBOSE, "");
        return FALSE;
    }

    si.fMask  = SIF_RANGE;
    si.nMin   = posMin;
    si.nMax   = posMax;
    si.cbSize = sizeof(SCROLLINFO);

    NtUserSetScrollInfo(hwnd, code, &si, fRedraw);

    return TRUE;
}
示例#11
0
文件: classc.c 项目: conioh/os-design
DWORD _GetClassLong(
    PWND pwnd,
    int index,
    BOOL bAnsi)
{
    PCLS pcls = REBASEALWAYS(pwnd, pcls);

    if (index < 0) {
        if (index < INDEX_OFFSET || afClassDWord[index - INDEX_OFFSET] > sizeof(DWORD)) {
            RIPERR1(ERROR_INVALID_INDEX, RIP_WARNING, "GetClassLong: invalid index %d", index);
            return 0;
        }
        return (DWORD)_GetClassData(pcls, pwnd, index, bAnsi);
    } else {
        if (index + (int)sizeof(DWORD) > pcls->cbclsExtra) {
            RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
            return 0;
        } else {
            DWORD UNALIGNED *pudw;
            pudw = (DWORD UNALIGNED *)((BYTE *)(pcls + 1) + index);
            return *pudw;
        }
    }
}
示例#12
0
文件: wmicon.c 项目: conioh/os-design
/***************************************************************************\
* DrawIconEx
*
* Draws icon in desired size.
*
\***************************************************************************/
BOOL _DrawIconEx(
    HDC     hdc,
    int     x,
    int     y,
    PCURSOR pcur,
    int     cx,
    int     cy,
    UINT    istepIfAniCur,
    HBRUSH  hbr,
    UINT    diFlags)
{
    BOOL fSuccess = FALSE;

    /*
     * If this is an animated cursor, just grab the ith frame and use it
     * for drawing.
     */
    if (pcur->CURSORF_flags & CURSORF_ACON) {

        if ((int)istepIfAniCur >= ((PACON)pcur)->cicur) {
            RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "DrawIconEx, icon step out of range.");
            goto Done;
        }

        pcur = ((PACON)pcur)->aspcur[((PACON)pcur)->aicur[istepIfAniCur]];
    }

    /*
     * Setup defaults.
     */
    cx = GetCWidth(cx, diFlags, pcur->cx);
    cy = GetCHeight(cy, diFlags, (pcur->cy / 2));

    if (hbr) {

        HBITMAP    hbmpT = NULL;
        HDC        hdcT;
        HBITMAP    hbmpOld;
        POLYPATBLT PolyData;

        if (hdcT = GreCreateCompatibleDC(hdc)) {

            if (hbmpT = GreCreateCompatibleBitmap(hdc, cx, cy)) {
                POINT pt;
                BOOL bRet;

                hbmpOld = GreSelectBitmap(hdcT, hbmpT);

                /*
                 * Set new dc's brush origin in same relative
                 * location as passed-in dc's.
                 */
                bRet = GreGetBrushOrg(hdc, &pt);
                /*
                 * Bug 292396 - joejo
                 * Stop overactive asserts by replacing with RIPMSG.
                 */
                if (bRet != TRUE) {
                    RIPMSG0(RIP_WARNING, "DrawIconEx, GreGetBrushOrg failed.");
                }

                bRet = GreSetBrushOrg(hdcT, pt.x, pt.y, NULL);
                if (bRet != TRUE) {
                    RIPMSG0(RIP_WARNING, "DrawIconEx, GreSetBrushOrg failed.");
                }

                PolyData.x         = 0;
                PolyData.y         = 0;
                PolyData.cx        = cx;
                PolyData.cy        = cy;
                PolyData.BrClr.hbr = hbr;

                bRet = GrePolyPatBlt(hdcT, PATCOPY, &PolyData, 1, PPB_BRUSH);
                if (bRet != TRUE) {
                    RIPMSG0(RIP_WARNING, "DrawIconEx, GrePolyPatBlt failed.");
                }

                /*
                 * Output the image to the temporary memoryDC.
                 */
                BltIcon(hdcT, 0, 0, cx, cy, ghdcMem, pcur, TRUE, SRCAND);
                BltIcon(hdcT, 0, 0, cx, cy, ghdcMem, pcur, FALSE, SRCINVERT);

                /*
                 * Blt the bitmap to the original DC.
                 */
                GreBitBlt(hdc, x, y, cx, cy, hdcT, 0, 0, SRCCOPY, (COLORREF)-1);

                GreSelectBitmap(hdcT, hbmpOld);

                bRet = GreDeleteObject(hbmpT);
                if (bRet != TRUE) {
                    RIPMSG0(RIP_WARNING, "DrawIconEx, GreDeleteObject failed. Possible Leak");
                }

                fSuccess = TRUE;
            }

            GreDeleteDC(hdcT);
        }

    } else {

        if (diFlags & DI_MASK) {

            BltIcon(hdc,
                    x,
                    y,
                    cx,
                    cy,
                    ghdcMem,
                    pcur,
                    TRUE,
                    ((diFlags & DI_IMAGE) ? SRCAND : SRCCOPY));
        }

        if (diFlags & DI_IMAGE) {

            BltIcon(hdc,
                    x,
                    y,
                    cx,
                    cy,
                    ghdcMem,
                    pcur,
                    FALSE,
                    ((diFlags & DI_MASK) ? SRCINVERT : SRCCOPY));
        }

        fSuccess = TRUE;
    }

Done:

    return fSuccess;
}
示例#13
0
BOOL _DestroyCursor(
    PCURSOR pcur,
    DWORD   cmdDestroy)
{
    PPROCESSINFO ppi;
    PPROCESSINFO ppiCursor;
    int          i;
    extern BOOL DestroyAniIcon(PACON pacon);

    if (pcur == NULL) {
        UserAssert(FALSE);
        return(TRUE);
    }
    ppi = PpiCurrent();
    ppiCursor = GETPPI(pcur);

    /*
     * Remove this icon from the caption icon cache.
     */
    for (i = 0; i < CCACHEDCAPTIONS; i++) {
        if (cachedCaptions[i].spcursor == pcur) {
            Unlock( &(cachedCaptions[i].spcursor) );
        }
    }

    /*
     * First step in destroying an cursor
     */
    switch (cmdDestroy) {

    case CURSOR_ALWAYSDESTROY:

        /*
         * Always destroy? then don't do any checking...
         */
        break;

    case CURSOR_CALLFROMCLIENT:

        /*
         * Can't destroy public cursors/icons.
         */
        if (ppiCursor == NULL)
            /*
             * Fake success if its a resource loaded icon because
             * this is how win95 responded.
             */
            return !!(pcur->CURSORF_flags & CURSORF_FROMRESOURCE);

        /*
         * If this cursor was loaded from a resource, don't free it till the
         * process exits.  This is the way we stay compatible with win3.0's
         * cursors which were actually resources.  Resources under win3 have
         * reference counting and other "features" like handle values that
         * never change.  Read more in the comment in
         * ServerLoadCreateCursorIcon().
         */
        if (pcur->CURSORF_flags & (CURSORF_LRSHARED | CURSORF_SECRET)) {
            return TRUE;
        }

        /*
         * One thread can't destroy the objects created by another.
         */
        if (ppiCursor != ppi) {
            RIPERR0(ERROR_DESTROY_OBJECT_OF_OTHER_THREAD, RIP_VERBOSE, "");
            return FALSE;
        }

        /*
         * fall through.
         */

    case CURSOR_THREADCLEANUP:

        /*
         * Don't destroy public objects either (pretend it worked though).
         */
        if (ppiCursor == NULL)
            return TRUE;
        break;
    }

    /*
     * First mark the object for destruction.  This tells the locking code that
     * we want to destroy this object when the lock count goes to 0.  If this
     * returns FALSE, we can't destroy the object yet.
     */
    if (!HMMarkObjectDestroy((PHEAD)pcur))
        return FALSE;

    if (pcur->strName.Length != 0) {
        UserFreePool((LPSTR)pcur->strName.Buffer);
    }

    if (pcur->atomModName != 0) {
        DeleteAtom(pcur->atomModName);
    }

    /*
     * If this is an ACON call its special routine to destroy it.
     */
    if (pcur->CURSORF_flags & CURSORF_ACON) {
        DestroyAniIcon((PACON)pcur);
    } else {
        if (pcur->hbmMask != NULL) {
            GreDeleteObject(pcur->hbmMask);
        }
        if (pcur->hbmColor != NULL) {
            GreDeleteObject(pcur->hbmColor);
        }
    }

    /*
     * Ok to destroy...  Free the handle (which will free the object and the
     * handle).
     */
    DestroyEmptyCursorObject(pcur);
    return TRUE;
}
示例#14
0
文件: wow.c 项目: conioh/os-design
PWND _GetWindow(
    PWND pwnd,
    UINT cmd)
{
    PWND pwndT;
    BOOL fRebase = FALSE;

    /*
     * If this is a desktop window, return NULL for sibling or
     * parent information.
     */
    if (GETFNID(pwnd) == FNID_DESKTOP) {
        switch (cmd) {
        case GW_CHILD:
            break;

        default:
            return NULL;
            break;
        }
    }

    /*
     * Rebase the returned window at the end of the routine
     * to avoid multiple test for pwndT == NULL.
     */
    pwndT = NULL;
    switch (cmd) {
    case GW_HWNDNEXT:
        pwndT = pwnd->spwndNext;
        fRebase = TRUE;
        break;

    case GW_HWNDFIRST:
        if (pwnd->spwndParent) {
            pwndT = REBASEPWND(pwnd, spwndParent);
            pwndT = REBASEPWND(pwndT, spwndChild);
            if (GetAppCompatFlags(NULL) & GACF_IGNORETOPMOST) {
                while (pwndT != NULL) {
                    if (!TestWF(pwndT, WEFTOPMOST))
                        break;
                    pwndT = REBASEPWND(pwndT, spwndNext);
                }
            }
        }
        break;

    case GW_HWNDLAST:
        pwndT = GetPrevPwnd(pwnd, NULL);
        break;

    case GW_HWNDPREV:
        pwndT = GetPrevPwnd(pwnd, pwnd);
        break;

    case GW_OWNER:
        pwndT = pwnd->spwndOwner;
        fRebase = TRUE;
        break;

    case GW_CHILD:
        pwndT = pwnd->spwndChild;
        fRebase = TRUE;
        break;

#if !defined(_USERK_)
    case GW_ENABLEDPOPUP:
       pwndT = (PWND)NtUserCallHwnd(PtoHq(pwnd), SFI_DWP_GETENABLEDPOPUP);
       fRebase = TRUE;
       break;
#endif

    default:
        RIPERR0(ERROR_INVALID_GW_COMMAND, RIP_VERBOSE, "");
        return NULL;
    }

    if (pwndT != NULL && fRebase)
        pwndT = REBASEPTR(pwnd, pwndT);

    return pwndT;
}
示例#15
0
WORD _GetWindowWord(
    PWND pwnd,
    int index)
{
    if (GETFNID(pwnd) != 0) {
        if ((index >= 0) && (index <
                (int)(CBFNID(pwnd->fnid)-sizeof(WND)))) {

            switch (GETFNID(pwnd)) {
            case FNID_MDICLIENT:
                if (index == 0)
                    break;
                goto DoDefault;

            case FNID_BUTTON:
                /*
                 * CorelDraw does a get/set on the first button window word.
                 * Allow it to.
                 */
                if (index == 0) {
                    /*
                     *  Since we now use a lookaside buffer for the control's
                     *  private data, we need to indirect into this structure.
                     */
                    PBUTN pbutn = ((PBUTNWND)pwnd)->pbutn;
                    if (!pbutn || (LONG)pbutn == (LONG)-1) {
                        return 0;
                    } else {
                        return (WORD)(pbutn->buttonState);
                    }
                }
                goto DoDefault;

            case FNID_DIALOG:
                if (index == DWL_USER)
                    return LOWORD(((PDIALOG)pwnd)->unused);
                if (index == DWL_USER+2)
                    return HIWORD(((PDIALOG)pwnd)->unused);
                goto DoDefault;

            default:
DoDefault:
                RIPERR3(ERROR_INVALID_INDEX,
                        RIP_WARNING,
                        "GetWindowWord: Trying to read private server data pwnd=(%lX) index=(%ld) fnid=(%lX)",
                        pwnd, index, (DWORD)pwnd->fnid);
                return 0;
                break;
            }
        }
    }

    if (index == GWL_USERDATA)
        return (WORD)pwnd->dwUserData;

    if ((index < 0) || (index + (int)sizeof(WORD) > pwnd->cbwndExtra)) {
        RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
        return 0;
    } else {
        return *((WORD UNALIGNED *)((BYTE *)(pwnd + 1) + index));
    }
}
示例#16
0
DWORD _GetClassData(
    PCLS pcls,
    PWND pwnd,   // used for transition to kernel-mode for GCL_WNDPROC
    int index,
    BOOL bAnsi)
{
    DWORD dwData;
    DWORD dwCPDType = 0;

    index -= INDEX_OFFSET;

    if (index < 0) {
        RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
        return 0;
    }

    UserAssert(index >= 0);
    UserAssert(index < sizeof(afClassDWord));
    UserAssert(sizeof(afClassDWord) == sizeof(aiClassOffset));
    if (afClassDWord[index]) {
        dwData = *(DWORD *)(((BYTE *)pcls) + aiClassOffset[index]);
    } else {
        dwData = (DWORD)*(WORD *)(((BYTE *)pcls) + aiClassOffset[index]);
    }

    index += INDEX_OFFSET;

    /*
     * If we're returning an icon or cursor handle, do the reverse
     * mapping here.
     */
    switch(index) {
    case GCL_MENUNAME:
        if (pcls->lpszMenuName != MAKEINTRESOURCE(pcls->lpszMenuName)) {
            /*
             * The Menu Name is a real string: return the client-side address.
             * (If the class was registered by another app this returns an
             * address in that app's addr. space, but it's the best we can do)
             */
            dwData = bAnsi ?
                    (DWORD)pcls->lpszClientAnsiMenuName :
                    (DWORD)pcls->lpszClientUnicodeMenuName;
        }
        break;

    case GCL_HICON:
    case GCL_HCURSOR:
    case GCL_HICONSM:
        /*
         * We have to go to the kernel to convert the pcursor to a handle because
         * cursors are allocated out of POOL, which is not accessable from the client.
         */
        if (dwData) {
            dwData = NtUserCallOneParam(dwData, SFI_KERNELPTOH);
        }
        break;

    case GCL_WNDPROC:
        {

        /*
         * Always return the client wndproc in case this is a server
         * window class.
         */

        if (pcls->flags & CSF_SERVERSIDEPROC) {
            dwData = MapServerToClientPfn(dwData, bAnsi);
        } else {
            DWORD dwT = dwData;

            dwData = MapClientNeuterToClientPfn(pcls, dwT, bAnsi);

            /*
             * If the client mapping didn't change the window proc then see if
             * we need a callproc handle.
             */
            if (dwData == dwT) {
                /*
                 * Need to return a CallProc handle if there is an Ansi/Unicode mismatch
                 */
                if (bAnsi != !!(pcls->flags & CSF_ANSIPROC)) {
                    dwCPDType |= bAnsi ? CPD_ANSI_TO_UNICODE : CPD_UNICODE_TO_ANSI;
                }
            }
        }

        if (dwCPDType) {
            DWORD dwCPD;

            dwCPD = GetCPD(pwnd, dwCPDType | CPD_WNDTOCLS, dwData);

            if (dwCPD) {
                dwData = dwCPD;
            } else {
                RIPMSG0(RIP_WARNING, "GetClassLong unable to alloc CPD returning handle\n");
            }
        }
        }
        break;

    /*
     * WOW uses a pointer straight into the class structure.
     */
    case GCL_WOWWORDS:
        return (DWORD) pcls->adwWOW;
    }

    return dwData;
}
示例#17
0
BOOL _RegisterHotKey(
    PWND pwnd,
    int id,
    UINT fsModifiers,
    UINT vk)
{
    PHOTKEY phk;
    BOOL fKeysExist;
    PTHREADINFO ptiCurrent;
    PWINDOWSTATION pwinsta = _GetProcessWindowStation(NULL);

    ptiCurrent = PtiCurrent();

    /*
     * Blow it off if the caller is not the windowstation init thread
     * and doesn't have the proper access rights
     */
    if (grpwinstaList && !CheckWinstaWriteAttributesAccess()) {
        return FALSE;
    }

    /*
     * Can't register hotkey for a window of another queue.
     * Return FALSE in this case.
     */
    if ((pwnd != PWND_FOCUS) && (pwnd != PWND_INPUTOWNER)) {
        if (GETPTI(pwnd) != ptiCurrent) {
            RIPERR0(ERROR_WINDOW_OF_OTHER_THREAD, RIP_VERBOSE, "");
            return FALSE;
        }
    }

    phk = FindHotKey(ptiCurrent, pwnd, id, fsModifiers, vk, FALSE, &fKeysExist);

    /*
     * If the keys have already been registered, return FALSE.
     */
    if (fKeysExist) {
        RIPERR0(ERROR_HOTKEY_ALREADY_REGISTERED, RIP_VERBOSE, "");
        return FALSE;
    }

    if (phk == NULL) {
        /*
         * This hotkey doesn't exist yet.
         */
        phk = (PHOTKEY)UserAllocPool(sizeof(HOTKEY), TAG_HOTKEY);

        /*
         * If the allocation failed, bail out.
         */
        if (phk == NULL) {
            return FALSE;
        }

        phk->pti = ptiCurrent;

        if ((pwnd != PWND_FOCUS) && (pwnd != PWND_INPUTOWNER)) {
            phk->spwnd = NULL;
            Lock(&phk->spwnd, pwnd);
        } else {
            phk->spwnd = pwnd;
        }
        phk->fsModifiers = fsModifiers;
        phk->vk = vk;
        phk->id = id;

        /*
         * Link the new hotkey to the front of the list.
         */
        phk->phkNext = gphkFirst;
        gphkFirst = phk;

    } else {

        /*
         * Hotkey already exists, reset the keys.
         */
        phk->fsModifiers = fsModifiers;
        phk->vk = vk;
    }

    return TRUE;
}
示例#18
0
文件: classc.c 项目: conioh/os-design
ULONG_PTR _GetClassData(
    PCLS pcls,
    PWND pwnd,   // used for transition to kernel-mode for GCL_WNDPROC
    int index,
    BOOL bAnsi)
{
    KERNEL_ULONG_PTR dwData;
    DWORD dwCPDType = 0;

    index -= INDEX_OFFSET;

    if (index < 0) {
        RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
        return 0;
    }

    UserAssert(index >= 0);
    UserAssert(index < sizeof(afClassDWord));
    UserAssert(sizeof(afClassDWord) == sizeof(aiClassOffset));
    if (afClassDWord[index] == sizeof(DWORD)) {
        dwData = *(DWORD *)(((BYTE *)pcls) + aiClassOffset[index]);
    } else if (afClassDWord[index] == sizeof(KERNEL_ULONG_PTR)) {
        dwData = *(KERNEL_ULONG_PTR *)(((BYTE *)pcls) + aiClassOffset[index]);
    } else {
        dwData = (DWORD)*(WORD *)(((BYTE *)pcls) + aiClassOffset[index]);
    }

    index += INDEX_OFFSET;

    /*
     * If we're returning an icon or cursor handle, do the reverse
     * mapping here.
     */
    switch(index) {
    case GCLP_MENUNAME:
        if (IS_PTR(pcls->lpszMenuName)) {
            /*
             * The Menu Name is a real string: return the client-side address.
             * (If the class was registered by another app this returns an
             * address in that app's addr. space, but it's the best we can do)
             */
            dwData = bAnsi ?
                    (ULONG_PTR)pcls->lpszClientAnsiMenuName :
                    (ULONG_PTR)pcls->lpszClientUnicodeMenuName;
        }
        break;

    case GCLP_HICON:
    case GCLP_HCURSOR:
    case GCLP_HICONSM:
        /*
         * We have to go to the kernel to convert the pcursor to a handle because
         * cursors are allocated out of POOL, which is not accessable from the client.
         */
        if (dwData) {
            dwData = NtUserCallHwndParam(PtoH(pwnd), index, SFI_GETCLASSICOCUR);
        }
        break;

    case GCLP_WNDPROC:
        {

        /*
         * Always return the client wndproc in case this is a server
         * window class.
         */

        if (pcls->CSF_flags & CSF_SERVERSIDEPROC) {
            dwData = MapServerToClientPfn(dwData, bAnsi);
        } else {
            KERNEL_ULONG_PTR dwT = dwData;

            dwData = MapClientNeuterToClientPfn(pcls, dwT, bAnsi);

            /*
             * If the client mapping didn't change the window proc then see if
             * we need a callproc handle.
             */
            if (dwData == dwT) {
                /*
                 * Need to return a CallProc handle if there is an Ansi/Unicode mismatch
                 */
                if (bAnsi != !!(pcls->CSF_flags & CSF_ANSIPROC)) {
                    dwCPDType |= bAnsi ? CPD_ANSI_TO_UNICODE : CPD_UNICODE_TO_ANSI;
                }
            }
        }

        if (dwCPDType) {
            ULONG_PTR dwCPD;

            dwCPD = GetCPD(pwnd, dwCPDType | CPD_WNDTOCLS, KERNEL_ULONG_PTR_TO_ULONG_PTR(dwData));

            if (dwCPD) {
                dwData = dwCPD;
            } else {
                RIPMSG0(RIP_WARNING, "GetClassLong unable to alloc CPD returning handle\n");
            }
        }
        }
        break;

    case GCL_CBCLSEXTRA:
        if ((pcls->CSF_flags & CSF_WOWCLASS) && (pcls->CSF_flags & CSF_WOWEXTRA)) {
            /*
             * The 16-bit app changed its Extra bytes value.  Return the changed
             * value.  FritzS
             */

            return PWCFromPCLS(pcls)->iClsExtra;
        }
        else
            return pcls->cbclsExtra;

        break;

    /*
     * WOW uses a pointer straight into the class structure.
     */
    case GCLP_WOWWORDS:
        if (pcls->CSF_flags & CSF_WOWCLASS) {
            return ((ULONG_PTR)PWCFromPCLS(pcls));
        } else
            return 0;

    case GCL_STYLE:
        dwData &= CS_VALID;
        break;
    }

    return KERNEL_ULONG_PTR_TO_ULONG_PTR(dwData);
}
示例#19
0
//
// Insert/remove the specified IME hotkey into/from 
// the IME hotkey list (gpImeHotKeyListHeader).
// 
BOOL 
SetImeHotKey(
    DWORD  dwHotKeyID,
    UINT   uModifiers,
    UINT   uVKey,
    HKL    hKL,
    DWORD  dwAction )
{
    PIMEHOTKEYOBJ ph;

    switch ( dwAction ) {
    case ISHK_REMOVE:
        ph = FindImeHotKeyByID( gpImeHotKeyListHeader, dwHotKeyID );
        if ( ph != NULL ) {
            if ( DeleteImeHotKey( &gpImeHotKeyListHeader, ph ) == ph ) {
                UserFreePool( ph );
                return ( TRUE );
            } else {
                RIPMSG0( RIP_ERROR, "IME hotkey list is messed up" );
                return ( FALSE );
            }
        } else { 
            RIPERR0( ERROR_INVALID_PARAMETER, 
                     RIP_WARNING, 
                     "no such IME hotkey registered");
            return ( FALSE );     
        }
        break;

    case ISHK_INITIALIZE:
        ph = gpImeHotKeyListHeader;
        while ( ph != NULL ) {
            PIMEHOTKEYOBJ phNext;

            phNext = ph->pNext;
            UserFreePool( ph );
            ph = phNext;
        }
        gpImeHotKeyListHeader = NULL;
        return TRUE;

    case ISHK_ADD:
        ph = FindImeHotKeyByKey( gpImeHotKeyListHeader,
                                 uModifiers & MOD_MODIFY_KEYS,
                                 uModifiers & MOD_BOTH_SIDES, 
                                 uVKey );
        if ( ph != NULL ) {    
            if ( ph->hk.dwHotKeyID != dwHotKeyID ) {
                RIPERR0( ERROR_HOTKEY_ALREADY_REGISTERED, 
                         RIP_WARNING, 
                         "There is an IME hotkey that has the same vkey/modifiers");
                return ( FALSE );
            } 
            // So far we found a hotkey that has the 
            // same vkey and same ID. 
            // But because modifiers may be slightly 
            // different, so go ahead and change it.
        } else {
            //
            // the specified vkey/modifiers combination cound not be found
            // in the hotkey list. The caller may want to change the key
            // assignment of an existing hotkey or add a new hotkey.
            //
            ph = FindImeHotKeyByID( gpImeHotKeyListHeader, dwHotKeyID );
        }

        if ( ph == NULL ) {         
        //
        // adding a new hotkey
        //
            ph = (PIMEHOTKEYOBJ)UserAllocPool( sizeof(IMEHOTKEY), TAG_IMEHOTKEY );
            if ( ph == NULL ) {
                RIPERR0( ERROR_OUTOFMEMORY,
                         RIP_WARNING,
                        "Memory allocation failed in SetImeHotKey");
                return ( FALSE );
            }
            ph->hk.dwHotKeyID = dwHotKeyID;
            ph->hk.uModifiers = uModifiers;
            ph->hk.uVKey = uVKey;
            ph->hk.hKL = hKL;
            ph->pNext = NULL;
            AddImeHotKey( &gpImeHotKeyListHeader, ph );

        } else {
        //
        // changing an existing hotkey
        //
            ph->hk.uModifiers = uModifiers;
            ph->hk.uVKey = uVKey;
            ph->hk.hKL = hKL;

        }
        return ( TRUE );
        break;
    };
}
示例#20
0
BOOL CliImmSetHotKeyWorker(
    DWORD dwID,
    UINT uModifiers,
    UINT uVKey,
    HKL hkl,
    DWORD dwAction)
{
    //
    // if we're adding an IME hotkey entry, let's check
    // the parameters before calling the kernel side code
    //
    if (dwAction == ISHK_ADD) {

        if (dwID >= IME_HOTKEY_DSWITCH_FIRST &&
                dwID <= IME_HOTKEY_DSWITCH_LAST) {
            //
            // IME direct switching hot key - switch to
            // the keyboard layout specified.
            // We need to specify keyboard layout.
            //
            if (hkl == NULL) {
                RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "hkl should be specified");
                return FALSE;
            }

        } else {
            //
            // normal hot keys - change the mode of current iME
            //
            // Because it should be effective in all IME no matter
            // which IME is active we should not specify a target IME
            //
            if (hkl != NULL) {
                RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "hkl shouldn't be specified");
                return FALSE;
            }

            if (dwID >= IME_KHOTKEY_FIRST && dwID <= IME_KHOTKEY_LAST) {
                RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Hotkey for Korean IMEs are invalid.");
                return FALSE;
            }
        }

        if (uModifiers & MOD_MODIFY_KEYS) {
            //
            // Because normal keyboard has left and right key for
            // these keys, you should specify left or right ( or both )
            //
            if ((uModifiers & MOD_BOTH_SIDES) == 0) {
                RIPERR3(ERROR_INVALID_PARAMETER, RIP_WARNING, "invalid modifiers %x for id %x vKey %x", uModifiers, dwID, uVKey);
                return FALSE;
            }
        }

#if 0   // Skip this check for now
        //
        // It doesn't make sense if vkey is same as modifiers
        //
        if ( ((uModifiers & MOD_ALT) && (uVKey == VK_MENU))        ||
             ((uModifiers & MOD_CONTROL) && (uVKey == VK_CONTROL)) ||
             ((uModifiers & MOD_SHIFT) && (uVKey == VK_SHIFT))     ||
             ((uModifiers & MOD_WIN) && ((uVKey == VK_LWIN)||(uVKey == VK_RWIN)))
           ) {

            RIPERR0( ERROR_INVALID_PARAMETER, RIP_WARNING, "vkey and modifiers are same");
            return FALSE;
        }
#endif
    }
    return NtUserSetImeHotKey(dwID, uModifiers, uVKey, hkl, dwAction);
}
示例#21
0
/*****************************************************************************\
*
*  GetGUIThreadInfo()
*
*  This gets GUI information out of context.  If you pass in a NULL thread ID,
*  we will get the 'global' information, using the foreground thread.  This
*  is guaranteed to be the real active window, focus window, etc.  Yes, you
*  could do it yourself by calling GetForegroundWindow, getting the thread ID
*  of that window via GetWindowThreadProcessId, then passing the ID into
*  GetGUIThreadInfo().  However, that takes three calls and aside from being
*  a pain, anything could happen in the middle.  So passing in NULL gets
*  you stuff in one call and hence also works right.
*
*  This function returns FALSE if the thread doesn't have a queue or the
*  thread ID is bogus.
*
\*****************************************************************************/
BOOL WINAPI
_GetGUIThreadInfo(PTHREADINFO pti, PGUITHREADINFO pgui)
{
    PQ pq;

    /*
     * Validate threadinfo structure
     */
    if (pgui->cbSize != sizeof(GUITHREADINFO)) {
        RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "GUITHREADINFO.cbSize %d is wrong", pgui->cbSize);
        return FALSE;
    }

    /*
     * Is this a valid initialized GUI thread?
     */
    if (pti != NULL) {
        if ((pq = pti->pq) == NULL) {
            // does this ever happen?
            RIPMSG1(RIP_ERROR, "GetGUIThreadInfo: No queue for pti %lx", pti);
            return FALSE;
        }
    } else {
        /*
         * Use the foreground queue. To get menu state information we must also
         * figure out the right pti.  This matches _GetForegroundWindow() logic.
         */
        if ((pq = gpqForeground) == NULL) {
            // this does sometimes happen...
            RIPMSG0(RIP_WARNING, "GetGUIThreadInfo: No foreground queue");
            return FALSE;
        }

        if (pq->spwndActive && (GETPTI(pq->spwndActive)->pq == pq)) {
            pti = GETPTI(pq->spwndActive);
            if (PtiCurrentShared()->rpdesk != pti->rpdesk) {
                RIPERR0(ERROR_ACCESS_DENIED, RIP_VERBOSE, "Foreground window on different desktop");
                return FALSE;
            }
        }
    }

    UserAssert(pq != NULL);

    /*
     * For C2 security, verify that pq and pti are on the current thread's desktop.
     * We can't directly determine which desktop pq belongs to, but we can at
     * least ensure that any caret info we return is not from another desktop
     */
    if (pq->caret.spwnd &&
            (GETPTI(pq->caret.spwnd)->rpdesk != PtiCurrentShared()->rpdesk)) {
        RIPERR0(ERROR_ACCESS_DENIED, RIP_VERBOSE, "Foreground caret on different desktop");
        return FALSE;
    }
    if (pti && (pti->rpdesk != PtiCurrentShared()->rpdesk)) {
        RIPERR0(ERROR_ACCESS_DENIED, RIP_VERBOSE, "Foreground thread on different desktop");
        return FALSE;
    }

    pgui->flags        = 0;
    pgui->hwndMoveSize = NULL;
    pgui->hwndMenuOwner = NULL;

    /*
     * Get Menu information from the THREADINFO
     */
    if (pti != NULL) {
        if (pti->pmsd && !pti->pmsd->fTrackCancelled && pti->pmsd->spwnd) {
            pgui->flags |= GUI_INMOVESIZE;
            pgui->hwndMoveSize = HWq(pti->pmsd->spwnd);
        }

        if (pti->pMenuState && pti->pMenuState->pGlobalPopupMenu) {
            pgui->flags |= GUI_INMENUMODE;

            if (pti->pMenuState->pGlobalPopupMenu->fHasMenuBar) {
                if (pti->pMenuState->pGlobalPopupMenu->fIsSysMenu) {
                    pgui->flags |= GUI_SYSTEMMENUMODE;
                }
            } else {
                pgui->flags |= GUI_POPUPMENUMODE;
            }

            if (pti->pMenuState->pGlobalPopupMenu->spwndNotify)
                pgui->hwndMenuOwner = HWq(pti->pMenuState->pGlobalPopupMenu->spwndNotify);
        }
    }

    /*
     * Get the rest of the information from the queue
     */
    pgui->hwndActive   = HW(pq->spwndActive);
    pgui->hwndFocus    = HW(pq->spwndFocus);
    pgui->hwndCapture  = HW(pq->spwndCapture);

    pgui->hwndCaret    = NULL;

    if (pq->caret.spwnd) {
        pgui->hwndCaret = HWq(pq->caret.spwnd);

        /*
         * These coords are always relative to the client of hwndCaret
         * of course.
         */
        pgui->rcCaret.left   = pq->caret.x;
        pgui->rcCaret.right  = pgui->rcCaret.left + pq->caret.cx;
        pgui->rcCaret.top    = pq->caret.y;
        pgui->rcCaret.bottom = pgui->rcCaret.top + pq->caret.cy;

        if (pq->caret.iHideLevel == 0)
            pgui->flags |= GUI_CARETBLINKING;
    } else if (pti && (pti->ppi->W32PF_Flags & W32PF_CONSOLEHASFOCUS)) {
        /*
         * The thread is running in the console window with focus. Pull
         * out the info from the console pseudo caret.
         */
        pgui->hwndCaret = pti->rpdesk->cciConsole.hwnd;
        pgui->rcCaret = pti->rpdesk->cciConsole.rc;
    } else {
        SetRectEmpty(&pgui->rcCaret);
    }

    return TRUE;
}
示例#22
0
int GetHmodTableIndex(
    PUNICODE_STRING pstrLibName)
{
    int i;
    ATOM atom;
    UNICODE_STRING strLibName;

    /*
     * Probe string
     */
    try {
        strLibName = ProbeAndReadUnicodeString(pstrLibName);
        ProbeForReadUnicodeStringBuffer(strLibName);
        atom = UserAddAtom(strLibName.Buffer, FALSE);
    } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
        return -1;
    }

    /*
     * If we can't add the atom we're hosed
     * so return an error.
     */
    if (atom == 0) {
        return -1;
    }

    /*
     * Search for atom index
     */
    for (i = 0; i < catomSysTableEntries && aatomSysLoaded[i] != atom; i++)
        ;

    if (i == catomSysTableEntries) {

        /*
         * Find empty entry for atom
         */
        for (i = 0; i < catomSysTableEntries && aatomSysLoaded[i]; i++)
            ;

        /*
         * Check if no empty entry found
         */
        if (i == catomSysTableEntries) {
            if (i == CLIBS) {
                UserDeleteAtom(atom);
                RIPERR0(ERROR_NOT_ENOUGH_MEMORY,
                        RIP_WARNING,
                        "Memory allocation failed in GetHmodTableIndex");

                return -1;
            }

            /*
             * Increase table size
             */
            catomSysTableEntries++;
        }

        /*
         * Set entry
         */
        aatomSysLoaded[i] = atom;
        acatomSysUse[i] = 0;
        acatomSysDepends[i] = 0;
    } else {
        UserDeleteAtom(atom);
    }

    return i;
}
示例#23
0
文件: getset.c 项目: conioh/os-design
WORD _SetWindowWord(
    PWND pwnd,
    int  index,
    WORD value)
{
    WORD wOld;

    /*
     * Don't allow setting of words belonging to a system thread if the caller
     * is not a system thread. Same goes for winlogon.
     */
    if (!FCallerOk(pwnd)) {
        RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
        return 0;
    }

    /*
     * Applications can not set a WORD into a dialog Proc or any of the
     * non-public reserved bytes in DLGWINDOWEXTRA (usersrv stores pointers
     * theres)
     */
    if (TestWF(pwnd, WFDIALOGWINDOW)) {
        if  (((index >= DWLP_DLGPROC) && (index < DWLP_MSGRESULT)) ||
                ((index > DWLP_USER+sizeof(LONG_PTR)-sizeof(WORD)) && (index < DLGWINDOWEXTRA))) {
            RIPERR3(ERROR_INVALID_INDEX, RIP_WARNING,
                  "SetWindowWord: Trying to set WORD of a windowproc pwnd=(%#p) index=(%ld) fnid (%lX)",
                pwnd, index, (DWORD)pwnd->fnid);
            return 0;
        } else {

            /*
             * If this is really a dialog and not some other server class
             * where usersrv has stored some data (Windows Compuserve -
             * wincim - does this) then store the data now that we have
             * verified the index limits.
             */
            if (GETFNID(pwnd) == FNID_DIALOG)
                goto DoSetWord;
        }
    }

    if (index == GWLP_USERDATA) {
        wOld = (WORD)pwnd->dwUserData;
        pwnd->dwUserData = MAKELONG(value, HIWORD(pwnd->dwUserData));
        return wOld;
    }

    // fix for RedShift, they call SetWindowWord
    // tn play with the low word of the style dword
    if (index == GWL_STYLE) {
        wOld = (WORD)pwnd->style;
        pwnd->style = MAKELONG(value, HIWORD(pwnd->style));
        return wOld;
    }

    if (GETFNID(pwnd) != 0) {
        if (index >= 0 &&
                (index < (int)(CBFNID(pwnd->fnid)-sizeof(WND)))) {
            switch (GETFNID(pwnd)) {
            case FNID_MDICLIENT:
                if (index == 0)
                    break;
                goto DoDefault;

            case FNID_BUTTON:
                /*
                 * CorelDraw, Direct Access 1.0 and WordPerfect 6.0 do a
                 * get/set on the first button window word.  Allow this
                 * for compatibility.
                 */
                if (index == 0) {
                    /*
                     *  Since we now use a lookaside buffer for the control's
                     *  private data, we need to indirect into this structure.
                     */
                    PBUTN pbutn = ((PBUTNWND)pwnd)->pbutn;
                    if (!pbutn || (LONG_PTR)pbutn == (LONG_PTR)-1) {
                        return 0;
                    } else {
                        try {
                            wOld = (WORD)ProbeAndReadUlong(&pbutn->buttonState);
                            pbutn->buttonState = value;
                        } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
                            wOld = 0;
                        }
                        return wOld;
                    }
                }
                goto DoDefault;

            default:
DoDefault:
                RIPERR3(ERROR_INVALID_INDEX,
                        RIP_WARNING,
                        "SetWindowWord: Trying to set private server data pwnd=(%#p) index=(%ld) fnid (%lX)",
                        pwnd, index, (DWORD)pwnd->fnid);
                return 0;
                break;
            }
        }
    }
示例#24
0
BOOL xxxShowWindow(
    PWND pwnd,
    DWORD cmdShowAnimate)
{
    BOOL fVisOld, fVisNew;
    UINT swpFlags = SWP_NOMOVE | SWP_NOSIZE;
    PTHREADINFO pti;
    BOOL bFirstMain = FALSE;
    int cmdShow = LOWORD(cmdShowAnimate);

    CheckLock(pwnd);

    fVisOld = TestWF(pwnd, WFVISIBLE);
    pti = PtiCurrent();

    /*
     * See if this is the first "main" top level
     * window being created by this application - if show, assume it
     * is showing with the SW_SHOWDEFAULT command.
     *
     * Checks for:
     * - cmdShow is a "default" show command
     * - we haven't done startupinfo yet (we only use it once)
     * - this is not a child (it is a top level window)
     * - this has a titlebar (indicator of the main window)
     * - it isn't owned (indicator of the main window)
     */
    if ((pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW) &&
            !TestwndChild(pwnd) &&
            (TestWF(pwnd, WFBORDERMASK) == (BYTE)LOBYTE(WFCAPTION)) &&
            (pwnd->spwndOwner == NULL)) {

        bFirstMain = TRUE;

        switch (cmdShow) {
        case SW_SHOWNORMAL:
        case SW_SHOW:

            /*
             * Then assume default!
             */
            cmdShow = SW_SHOWDEFAULT;
            break;
        }
    }

    /*
     * If this application specified SW_SHOWDEFAULT, then we get the
     * real SW_* command from the application's STARTUPINFO structure
     * (STARTUPINFO is passed to CreateProcess() when this application
     * was launched).
     */
    if (cmdShow == SW_SHOWDEFAULT) {

        /*
         * Call the client to get the SW_* command from the STARTUPINFO
         * for this process.
         */
        if (pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW) {

            bFirstMain = TRUE;

            cmdShow = pti->ppi->usi.wShowWindow;
#if 0
            switch (cmdShow) {
            case SW_SHOWMINIMIZED:
            case SW_MINIMIZE:

                /*
                 * If the default show was "minimized", then make sure it doesn't
                 * become active.  Minimized is effectively "background".
                 */
                cmdShow = SW_SHOWMINNOACTIVE;
                break;
            }
#endif
        }
    }

    //
    // This is in case someone said SW_SHOWDEFAULT but has no startupinfo.
    // Or in case cmdShow inside of STARTUPINFO is SW_SHOWDEFAULT.
    //
    if (cmdShow == SW_SHOWDEFAULT)
        cmdShow = SW_SHOWNORMAL;

    /*
     * Turn off startup info.  We turn this off after the first call to
     * ShowWindow.  If we don't apps can be started by progman with
     * the start info being minimized and then be restored and then
     * call ShowWindow(SW_SHOW) and the app would minimize again.
     * Notepad had that problem 2985.
     */
    if (bFirstMain) {
        pti->ppi->usi.dwFlags &= ~(STARTF_USESHOWWINDOW|STARTF_USESIZE \
                | STARTF_USEPOSITION);
    }


    /*
     * Take care of all the OLD show commands with columns & iconslot.
     */
    if (cmdShow & 0xFF00) {
        if ((cmdShow & 0xFF80) == (int)0xFF80)
            cmdShow = SW_SHOWMINNOACTIVE;
        else
            cmdShow = SW_SHOW;
    }

    /*
     * Change to new fullscreen if needed and in same desktop
     */
    if ((pwnd->bFullScreen != WINDOWED)
            && (pwnd->head.rpdesk == grpdeskRitInput)) {
        if ((cmdShow == SW_SHOWNORMAL) ||
            (cmdShow == SW_RESTORE) ||
            (cmdShow == SW_MAXIMIZE) ||
            (cmdShow == SW_SHOWMAXIMIZED)) {
            cmdShow = SW_SHOWMINIMIZED;

            if (pwnd->bFullScreen == FULLSCREENMIN) {
                pwnd->bFullScreen = FULLSCREEN;
            }

            if (gpqForeground != NULL &&
                gpqForeground->spwndActive == pwnd) {
                xxxMakeWindowForegroundWithState(NULL, 0);
            }
        }
    }

    switch (cmdShow) {
    case SW_SHOWNOACTIVATE:
    case SW_SHOWNORMAL:
    case SW_RESTORE:

        /*
         * If min/max, let xxxMinMaximize() do all the work.
         */
        if (TestWF(pwnd, WFMINIMIZED) || TestWF(pwnd, WFMAXIMIZED)) {
            xxxMinMaximize(pwnd, (UINT)cmdShow, cmdShowAnimate & MINMAX_ANIMATE);
            return fVisOld;

        } else {

            /*
             * Ignore if the window is already visible.
             */
            if (fVisOld) {
                return fVisOld;
            }

            swpFlags |= SWP_SHOWWINDOW;
            if (   cmdShow == SW_SHOWNOACTIVATE) {
                swpFlags |= SWP_NOZORDER;
#ifdef NEVER
                /*
                 * This is what win3.1 does. On NT, since each "queue" has
                 * its own active window, there is often no active window.
                 * In this case, win3.1 turns a SHOWNOACTIVATE into a "SHOW
                 * with activate". Since win3.1 almost always has an active
                 * window, this almost never happens. So on NT, we're not
                 * going to do this check - that way we'll be more compatible
                 * with win3.1 because we'll usally not activate (like win3.1).
                 * With this check, this causes FoxPro 2.5 for Windows to not
                 * properly activate its command window when first coming up.
                 */
                if (pti->pq->spwndActive != NULL)
                    swpFlags |= SWP_NOACTIVATE;
#else
                swpFlags |= SWP_NOACTIVATE;
#endif
            }
        }
        break;

    case SW_SHOWMINNOACTIVE:
    case SW_SHOWMINIMIZED:
    case SW_SHOWMAXIMIZED:
    case SW_MINIMIZE:
        xxxMinMaximize(pwnd, (UINT)cmdShow, cmdShowAnimate & MINMAX_ANIMATE);
        return fVisOld;

    case SW_SHOWNA:
        swpFlags |= SWP_SHOWWINDOW | SWP_NOACTIVATE;

        // LATER removed this to be compatible with SHOWNOACTIVATE
        //if (pti->pq->spwndActive != NULL)
        //    swpFlags |= SWP_NOACTIVATE;
        break;

    case SW_SHOW:

        /*
         * Don't bother if it is already visible.
         */
        if (fVisOld)
            return fVisOld;

        swpFlags |= SWP_SHOWWINDOW;
        if (cmdShow == SW_SHOWNOACTIVATE)
        {
            swpFlags |= SWP_NOZORDER | SWP_NOACTIVATE;
        }
        break;

    case SW_HIDE:

        /*
         * Don't bother if it is already hidden.
         */
        if (!fVisOld)
            return fVisOld;

        swpFlags |= SWP_HIDEWINDOW;
        if (pwnd != pti->pq->spwndActive)
            swpFlags |= (SWP_NOACTIVATE | SWP_NOZORDER);
        break;

    default:
        RIPERR0(ERROR_INVALID_SHOWWIN_COMMAND, RIP_VERBOSE, "");
        return fVisOld;
    }

    /*
     * If we're changing from visible to hidden or vise-versa, send
     * WM_SHOWWINDOW.
     */
    fVisNew = !(cmdShow == SW_HIDE);
    if (fVisNew != fVisOld) {
        xxxSendMessage(pwnd, WM_SHOWWINDOW, fVisNew, 0L);
        if (!TestWF(pwnd, WFWIN31COMPAT)) {
            xxxSendMessage(pwnd, WM_SETVISIBLE, fVisNew, 0L);
        }
    }

    if (!TestwndChild(pwnd)) {
        if (TestCF(pwnd, CFSAVEBITS)) {

            /*
             * Activate to prevent discarding saved bits???
             */
            if (cmdShow == SW_SHOW || cmdShow == SW_SHOWNORMAL) {
                xxxActivateWindow(pwnd, AW_USE);
                swpFlags |= SWP_NOZORDER | SWP_NOACTIVATE;
            }
        }
    } else {

        /*
         * Children can't get activation...
         */
        swpFlags |= (SWP_NOACTIVATE | SWP_NOZORDER);
    }

    /*
     * If our parent is hidden, don't bother to call xxxSetWindowPos.
     */
    if (_FChildVisible(pwnd)) {
        xxxSetWindowPos(pwnd, (PWND)NULL, 0, 0, 0, 0, swpFlags);
    } else {
        if (cmdShow == SW_HIDE)
            ClrWF(pwnd, WFVISIBLE);
        else
            SetWF(pwnd, WFVISIBLE);
    }

    /*
     * Send size and move messages AFTER repainting
     */
    if (TestWF(pwnd, WFSENDSIZEMOVE)) {
        ClrWF(pwnd, WFSENDSIZEMOVE);
        if (TestWF(pwnd, WFMINIMIZED)) {
            xxxSendSizeMessage(pwnd, SIZEICONIC);
        } else if (TestWF(pwnd, WFMAXIMIZED)) {
            xxxSendSizeMessage(pwnd, SIZEFULLSCREEN);
        } else {
            xxxSendSizeMessage(pwnd, SIZENORMAL);
        }
        if (pwnd->spwndParent) {
            xxxSendMessage(pwnd, WM_MOVE, 0, MAKELONG(
                    pwnd->rcClient.left - pwnd->spwndParent->rcClient.left,
                    pwnd->rcClient.top - pwnd->spwndParent->rcClient. top));
        } else {
            /*
             * NULL parent implies this window is a zombie
             */
            xxxSendMessage(pwnd, WM_MOVE, 0, MAKELONG(
                    pwnd->rcClient.left, pwnd->rcClient.top));
        }
    }

    /*
     * If hiding and is active-foreground window, activate someone else.
     * If hiding a active window make someone active.
     */
    if (cmdShow == SW_HIDE) {
        if ((pwnd == pti->pq->spwndActive) && (pti->pq == gpqForeground)) {
            xxxActivateWindow(pwnd, AW_SKIP);
        } else {
            xxxCheckFocus(pwnd);
        }
    }

    return fVisOld;
}
示例#25
0
文件: lb1.c 项目: conioh/os-design
LRESULT APIENTRY ListBoxWndProcWorker(
    PWND pwnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam,
    DWORD fAnsi)
{
    HWND hwnd = HWq(pwnd);
    PAINTSTRUCT ps;
    HDC         hdc;
    LPRECT      lprc;
    PLBIV plb;    /* List Box Instance Variable */
    INT iSel;     /* Index of selected item */
    DWORD dw;
    TL tlpwndParent;
    UINT wFlags;
    LPWSTR lpwsz = NULL;
    LRESULT lReturn = 0;
    static BOOL fInit = TRUE;

    CheckLock(pwnd);

    VALIDATECLASSANDSIZE(pwnd, FNID_LISTBOX);
    INITCONTROLLOOKASIDE(&ListboxLookaside, LBIV, spwnd, 4);

    /*
     * Get the plb for the given window now since we will use it a lot in
     * various handlers. This was stored using SetWindowLong(hwnd,0,plb)
     * when the listbox was first created (by INITCONTROLLOOKASIDE above)
     */
    plb = ((PLBWND)pwnd)->pLBIV;

    /*
     * Handle ANSI translations of input parameters
     */
    if (fAnsi) {
        switch (message) {
        case LB_ADDSTRING:
        case LB_ADDSTRINGUPPER:
        case LB_ADDSTRINGLOWER:
        case LB_FINDSTRING:
        case LB_FINDSTRINGEXACT:
        case LB_INSERTSTRING:
        case LB_INSERTSTRINGUPPER:
        case LB_INSERTSTRINGLOWER:
        case LB_SELECTSTRING:
            if (!plb->fHasStrings) {
                break;
            }
            // Fall through...
        case LB_ADDFILE:
        case LB_DIR:
            if (lParam) {
                if (!MBToWCS((LPSTR)lParam, -1, &lpwsz, -1, TRUE))
                    return LB_ERR;
            }
            break;
        default:
            break;
        }
        if (lpwsz) {
            lParam = (LPARAM)lpwsz;
        }
    }

    switch (message) {

    case LB_GETTOPINDEX:        // Return index of top item displayed.
        return plb->iTop;

    case LB_SETTOPINDEX:
        if (wParam && ((INT)wParam < 0 || (INT)wParam >= plb->cMac)) {
            RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
            return LB_ERR;
        }
        if (plb->cMac) {
            xxxNewITop(plb, (INT)wParam);
        }
        break;

    case WM_STYLECHANGED:
        plb->fRtoLReading = (TestWF(pwnd, WEFRTLREADING) != 0);
        plb->fRightAlign  = (TestWF(pwnd, WEFRIGHT) != 0);
        xxxCheckRedraw(plb, FALSE, 0);
        break;

    case WM_WINDOWPOSCHANGED:

        /*
         * If we are in the middle of creation, ignore this
         * message because it will generate a WM_SIZE message.
         * See xxxLBCreate().
         */
        if (!plb->fIgnoreSizeMsg)
            goto CallDWP;
        break;

    case WM_SIZE:

        /*
         * If we are in the middle of creation, ignore size
         * messages.  See xxxLBCreate().
         */
        if (!plb->fIgnoreSizeMsg)
            xxxLBSize(plb, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
        break;

    case WM_ERASEBKGND:
        ThreadLock(plb->spwndParent, &tlpwndParent);
        FillWindow(HW(plb->spwndParent), hwnd, (HDC)wParam,
                (HBRUSH)CTLCOLOR_LISTBOX);
        ThreadUnlock(&tlpwndParent);
        return TRUE;

    case LB_RESETCONTENT:
        xxxLBResetContent(plb);
        break;

    case WM_TIMER:
        if (wParam == IDSYS_LBSEARCH) {
            plb->iTypeSearch = 0;
            NtUserKillTimer(hwnd, IDSYS_LBSEARCH);
            xxxInvertLBItem(plb, plb->iSel, TRUE);
            break;
        }

        message = WM_MOUSEMOVE;
        xxxTrackMouse(plb, message, plb->ptPrev);
        break;

        /*
         * Fall through
         */
    case WM_MOUSEMOVE:
    case WM_LBUTTONDOWN:
    case WM_LBUTTONUP:
    case WM_LBUTTONDBLCLK:
        {
            POINT pt;

            POINTSTOPOINT(pt, lParam);
            xxxTrackMouse(plb, message, pt);
        }
        break;

    case WM_MBUTTONDOWN:
        EnterReaderModeHelper(hwnd);
        break;

    case WM_CAPTURECHANGED:
            //
            // Note that this message should be handled only on unexpected
            // capture changes currently.
            //
        UserAssert(TestWF(pwnd, WFWIN40COMPAT));
        if (plb->fCaptured)
            xxxLBButtonUp(plb, LBUP_NOTIFY);
        break;

    case LBCB_STARTTRACK:
        //
        // Start tracking mouse moves in the listbox, setting capture
        //
        if (!plb->pcbox)
            break;

        plb->fCaptured = FALSE;
        if (wParam) {
            POINT pt;

            POINTSTOPOINT(pt, lParam);

            _ScreenToClient(pwnd, &pt);
            xxxTrackMouse(plb, WM_LBUTTONDOWN, pt);
        } else {
            NtUserSetCapture(hwnd);
            plb->fCaptured = TRUE;
            plb->iLastSelection = plb->iSel;
        }
        break;

    case LBCB_ENDTRACK:
        // Kill capture, tracking, etc.
        if (plb->fCaptured)
            xxxLBButtonUp(plb, LBUP_RELEASECAPTURE | (wParam ? LBUP_SELCHANGE :
                LBUP_RESETSELECTION));
        break;

    case WM_PRINTCLIENT:
        xxxLBPaint(plb, (HDC) wParam, NULL);
        break;

    case WM_PAINT:
        if (wParam) {
            hdc = (HDC) wParam;
            lprc = NULL;
        } else {
            hdc = NtUserBeginPaint(hwnd, &ps);
            lprc = &(ps.rcPaint);
        }

        if (IsLBoxVisible(plb))
            xxxLBPaint(plb, hdc, lprc);

        if (!wParam)
            NtUserEndPaint(hwnd, &ps);
        break;

    case WM_NCDESTROY:
    case WM_FINALDESTROY:
        xxxDestroyLBox(plb, pwnd);
        break;

    case WM_SETFOCUS:
// DISABLED in Win 3.1        xxxUpdateWindow(pwnd);
        CaretCreate(plb);
        xxxLBSetCaret(plb, TRUE);
        xxxNotifyOwner(plb, LBN_SETFOCUS);
        if (FWINABLE()) {
            if (_IsWindowVisible(pwnd)) {
                LBEvent(plb, EVENT_OBJECT_FOCUS, plb->iSelBase);
            }
        }
        break;

    case WM_KILLFOCUS:
        /*
         * Reset the wheel delta count.
         */
        gcWheelDelta = 0;

        xxxLBSetCaret(plb, FALSE);
        xxxCaretDestroy(plb);
        xxxNotifyOwner(plb, LBN_KILLFOCUS);
        if (plb->iTypeSearch) {
            plb->iTypeSearch = 0;
            NtUserKillTimer(hwnd, IDSYS_LBSEARCH);
        }
        if (plb->pszTypeSearch) {
            UserLocalFree(plb->pszTypeSearch);
            plb->pszTypeSearch = NULL;
        }
        break;

    case WM_MOUSEWHEEL:
        {
            int     cDetants;
            int     cPage;
            int     cLines;
            RECT    rc;
            int     windowWidth;
            int     cPos;

            /*
             * Don't handle zoom and datazoom.
             */
            if (wParam & (MK_SHIFT | MK_CONTROL)) {
                goto CallDWP;
            }

            lReturn = 1;
            gcWheelDelta -= (short) HIWORD(wParam);
            cDetants = gcWheelDelta / WHEEL_DELTA;
            if (    cDetants != 0 &&
                    gpsi->ucWheelScrollLines > 0 &&
                    (pwnd->style & (WS_VSCROLL | WS_HSCROLL))) {

                gcWheelDelta = gcWheelDelta % WHEEL_DELTA;

                if (pwnd->style & WS_VSCROLL) {
                    cPage = max(1, (plb->cItemFullMax - 1));
                    cLines = cDetants *
                            (int) min((UINT) cPage, gpsi->ucWheelScrollLines);

                    cPos = max(0, min(plb->iTop + cLines, plb->cMac - 1));
                    if (cPos != plb->iTop) {
                        xxxLBoxCtlScroll(plb, SB_THUMBPOSITION, cPos);
                        xxxLBoxCtlScroll(plb, SB_ENDSCROLL, 0);
                    }
                } else if (plb->fMultiColumn) {
                    cPage = max(1, plb->numberOfColumns);
                    cLines = cDetants * (int) min((UINT) cPage, gpsi->ucWheelScrollLines);
                    cPos = max(
                            0,
                            min((plb->iTop / plb->itemsPerColumn) + cLines,
                                plb->cMac - 1 - ((plb->cMac - 1) % plb->itemsPerColumn)));

                    if (cPos != plb->iTop) {
                        xxxLBoxCtlHScrollMultiColumn(plb, SB_THUMBPOSITION, cPos);
                        xxxLBoxCtlHScrollMultiColumn(plb, SB_ENDSCROLL, 0);
                    }
                } else {
                    _GetClientRect(plb->spwnd, &rc);
                    windowWidth = rc.right;
                    cPage = max(plb->cxChar, (windowWidth / 3) * 2) /
                            plb->cxChar;

                    cLines = cDetants *
                            (int) min((UINT) cPage, gpsi->ucWheelScrollLines);

                    cPos = max(
                            0,
                            min(plb->xOrigin + (cLines * plb->cxChar),
                                plb->maxWidth));

                    if (cPos != plb->xOrigin) {
                        xxxLBoxCtlHScroll(plb, SB_THUMBPOSITION, cPos);
                        xxxLBoxCtlHScroll(plb, SB_ENDSCROLL, 0);
                    }
                }
            }
        }
        break;

    case WM_VSCROLL:
        xxxLBoxCtlScroll(plb, LOWORD(wParam), HIWORD(wParam));
        break;

    case WM_HSCROLL:
        xxxLBoxCtlHScroll(plb, LOWORD(wParam), HIWORD(wParam));
        break;

    case WM_GETDLGCODE:
        return DLGC_WANTARROWS | DLGC_WANTCHARS;

    case WM_CREATE:
        return xxxLBCreate(plb, pwnd, (LPCREATESTRUCT) lParam);

    case WM_SETREDRAW:

        /*
         * If wParam is nonzero, the redraw flag is set
         * If wParam is zero, the flag is cleared
         */
        xxxLBSetRedraw(plb, (wParam != 0));
        break;

    case WM_ENABLE:
        xxxLBInvalidateRect(plb, NULL, !plb->OwnerDraw);
        break;

    case WM_SETFONT:
        xxxLBSetFont(plb, (HANDLE)wParam, LOWORD(lParam));
        break;

    case WM_GETFONT:
        return (LRESULT)plb->hFont;

    case WM_DRAGSELECT:
    case WM_DRAGLOOP:
    case WM_DRAGMOVE:
    case WM_DROPFILES:
        ThreadLock(plb->spwndParent, &tlpwndParent);
        lReturn = SendMessage(HW(plb->spwndParent), message, wParam, lParam);
        ThreadUnlock(&tlpwndParent);
        return lReturn;


    case WM_QUERYDROPOBJECT:
    case WM_DROPOBJECT:

        /*
         * fix up control data, then pass message to parent
         */
        LBDropObjectHandler(plb, (PDROPSTRUCT)lParam);
        ThreadLock(plb->spwndParent, &tlpwndParent);
        lReturn = SendMessage(HW(plb->spwndParent), message, wParam, lParam);
        ThreadUnlock(&tlpwndParent);
        return lReturn;

    case LB_GETITEMRECT:
        return LBGetItemRect(plb, (INT)wParam, (LPRECT)lParam);

    case LB_GETITEMDATA:
        return LBGetItemData(plb, (INT)wParam);  // wParam = item index

    case LB_SETITEMDATA:

        /*
         * wParam is item index
         */
        return LBSetItemData(plb, (INT)wParam, lParam);

    case LB_ADDSTRINGUPPER:
        wFlags = UPPERCASE | LBI_ADD;
        goto CallInsertItem;

    case LB_ADDSTRINGLOWER:
        wFlags = LOWERCASE | LBI_ADD;
        goto CallInsertItem;

    case LB_ADDSTRING:
        wFlags = LBI_ADD;
        goto CallInsertItem;

    case LB_INSERTSTRINGUPPER:
        wFlags = UPPERCASE;
        goto CallInsertItem;

    case LB_INSERTSTRINGLOWER:
        wFlags = LOWERCASE;
        goto CallInsertItem;

    case LB_INSERTSTRING:
        wFlags = 0;
CallInsertItem:
        lReturn = ((LRESULT) xxxLBInsertItem(plb, (LPWSTR) lParam, (int) wParam, wFlags));
        break;

    case LB_INITSTORAGE:
        return xxxLBInitStorage(plb, fAnsi, (INT)wParam, (INT)lParam);

    case LB_DELETESTRING:
        return xxxLBoxCtlDelete(plb, (INT)wParam);

    case LB_DIR:
        /*
         * wParam - Dos attribute value.
         * lParam - Points to a file specification string
         */
        lReturn = xxxLbDir(plb, (INT)wParam, (LPWSTR)lParam);
        break;

    case LB_ADDFILE:
        lReturn = xxxLbInsertFile(plb, (LPWSTR)lParam);
        break;

    case LB_SETSEL:
        return xxxLBSetSel(plb, (wParam != 0), (INT)lParam);

    case LB_SETCURSEL:
        /*
         * If window obscured, update so invert will work correctly
         */
// DISABLED in Win 3.1        xxxUpdateWindow(pwnd);
        return xxxLBSetCurSel(plb, (INT)wParam);

    case LB_GETSEL:
        if (wParam >= (UINT) plb->cMac)
                return((LRESULT) LB_ERR);

        return IsSelected(plb, (INT)wParam, SELONLY);

    case LB_GETCURSEL:
        if (plb->wMultiple == SINGLESEL) {
            return plb->iSel;
        }
        return plb->iSelBase;

    case LB_SELITEMRANGE:
        if (plb->wMultiple == SINGLESEL) {
            /*
             * Can't select a range if only single selections are enabled
             */
            RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE,"Invalid index passed to LB_SELITEMRANGE");
            return LB_ERR;
        }

        xxxLBSelRange(plb, LOWORD(lParam), HIWORD(lParam), (wParam != 0));
        break;

    case LB_SELITEMRANGEEX:
        if (plb->wMultiple == SINGLESEL) {
            /*
             * Can't select a range if only single selections are enabled
             */
            RIPERR0(ERROR_INVALID_LB_MESSAGE, RIP_VERBOSE,"LB_SELITEMRANGEEX:Can't select a range if only single selections are enabled");
            return LB_ERR;
        } else {
            BOOL fHighlight = ((DWORD)lParam > (DWORD)wParam);
            if (fHighlight == FALSE) {
                ULONG_PTR temp = lParam;
                lParam = wParam;
                wParam = temp;
            }
            xxxLBSelRange(plb, (INT)wParam, (INT)lParam, fHighlight);
        }
        break;

    case LB_GETTEXTLEN:
        if (lParam != 0) {
            RIPMSG1(RIP_WARNING, "LB_GETTEXTLEN with lParam = %lx\n", lParam);
        }
        lReturn = LBGetText(plb, TRUE, fAnsi, (INT)wParam, NULL);
        break;

    case LB_GETTEXT:
        lReturn = LBGetText(plb, FALSE, fAnsi, (INT)wParam, (LPWSTR)lParam);
        break;

    case LB_GETCOUNT:
        // Lotus Approach calls CallWndProc(ListWndProc, LB_GETCOUNT,...)
        // on a window that doesn't have a plb yet. So, we need to make
        // this check. Bug #6675 - 11/7/94 --
        if(plb)
            return((LRESULT) plb->cMac);
        else
            return(0);

    case LB_SETCOUNT:
        return xxxLBSetCount(plb, (INT)wParam);

    case LB_SELECTSTRING:
    case LB_FINDSTRING:
        iSel = xxxFindString(plb, (LPWSTR)lParam, (INT)wParam, PREFIX, TRUE);
        if (message == LB_FINDSTRING || iSel == LB_ERR) {
            lReturn = iSel;
        } else {
            lReturn = xxxLBSetCurSel(plb, iSel);
        }
        break;

    case LB_GETLOCALE:
        return plb->dwLocaleId;

    case LB_SETLOCALE:

        /*
         * Validate locale
         */
        wParam = ConvertDefaultLocale((LCID)wParam);
        if (!IsValidLocale((LCID)wParam, LCID_INSTALLED))
            return LB_ERR;

        dw = plb->dwLocaleId;
        plb->dwLocaleId = (DWORD)wParam;
        return dw;

    case WM_KEYDOWN:

        /*
         * IanJa: Use LOWORD() to get low 16-bits of wParam - this should
         * work for Win16 & Win32.  The value obtained is the virtual key
         */
        xxxLBoxCtlKeyInput(plb, message, LOWORD(wParam));
        break;

    case WM_CHAR:
        xxxLBoxCtlCharInput(plb, LOWORD(wParam), fAnsi);
        break;

    case LB_GETSELITEMS:
    case LB_GETSELCOUNT:

        /*
         * IanJa/Win32 should this be LPWORD now?
         */
        return LBoxGetSelItems(plb, (message == LB_GETSELCOUNT), (INT)wParam,
                (LPINT)lParam);

    case LB_SETTABSTOPS:

        /*
         * IanJa/Win32: Tabs given by array of INT for backwards compatability
         */
        return LBSetTabStops(plb, (INT)wParam, (LPINT)lParam);

    case LB_GETHORIZONTALEXTENT:

        /*
         * Return the max width of the listbox used for horizontal scrolling
         */
        return plb->maxWidth;

    case LB_SETHORIZONTALEXTENT:

        /*
         * Set the max width of the listbox used for horizontal scrolling
         */
        if (plb->maxWidth != (INT)wParam) {
            plb->maxWidth = (INT)wParam;

            /*
             * When horizontal extent is set, Show/hide the scroll bars.
             * NOTE: LBShowHideScrollBars() takes care if Redraw is OFF.
             * Fix for Bug #2477 -- 01/14/91 -- SANKAR --
             */
            xxxLBShowHideScrollBars(plb); //Try to show or hide scroll bars
            if (plb->fHorzBar && plb->fRightAlign && !(plb->fMultiColumn || plb->OwnerDraw)) {
                /*
                 * origin to right
                 */
                xxxLBoxCtlHScroll(plb, SB_BOTTOM, 0);
            }
        }
        break;    /* originally returned register ax (message) ! */

    case LB_SETCOLUMNWIDTH:

        /*
         * Set the width of a column in a multicolumn listbox
         */
        plb->cxColumn = (INT)wParam;
        LBCalcItemRowsAndColumns(plb);
        if (IsLBoxVisible(plb))
            NtUserInvalidateRect(hwnd, NULL, TRUE);
        xxxLBShowHideScrollBars(plb);
        break;

    case LB_SETANCHORINDEX:
        if ((INT)wParam >= plb->cMac) {
            RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE,"Invalid index passed to LB_SETANCHORINDEX");
            return LB_ERR;
        }
        plb->iMouseDown = (INT)wParam;
        plb->iLastMouseMove = (INT)wParam;
        xxxInsureVisible(plb, (int) wParam, (BOOL)(lParam != 0));
        break;

    case LB_GETANCHORINDEX:
        return plb->iMouseDown;

    case LB_SETCARETINDEX:
        if ( (plb->iSel == -1) || ((plb->wMultiple != SINGLESEL) &&
                    (plb->cMac > (INT)wParam))) {

            /*
             * Set's the iSelBase to the wParam
             * if lParam, then don't scroll if partially visible
             * else scroll into view if not fully visible
             */
            xxxInsureVisible(plb, (INT)wParam, (BOOL)LOWORD(lParam));
            xxxSetISelBase(plb, (INT)wParam);
            break;
        } else {
            if ((INT)wParam >= plb->cMac) {
                RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE,"Invalid index passed to LB_SETCARETINDEX");
            }
            return LB_ERR;
        }
        break;

    case LB_GETCARETINDEX:
        return plb->iSelBase;

    case LB_SETITEMHEIGHT:
    case LB_GETITEMHEIGHT:
        return LBGetSetItemHeightHandler(plb, message, (INT)wParam, LOWORD(lParam));
        break;

    case LB_FINDSTRINGEXACT:
        lReturn = xxxFindString(plb, (LPWSTR)lParam, (INT)wParam, EQ, TRUE);
        break;

    case LB_ITEMFROMPOINT: {
        POINT pt;
        BOOL bOutside;
        DWORD dwItem;

        POINTSTOPOINT(pt, lParam);
        bOutside = ISelFromPt(plb, pt, &dwItem);
        UserAssert(bOutside == 1 || bOutside == 0);
        return (LRESULT)MAKELONG(dwItem, bOutside);
    }

    case LBCB_CARETON:

        /*
         * Internal message for combo box support
         */
        CaretCreate(plb);
        // Set up the caret in the proper location for drop downs.
        plb->iSelBase = plb->iSel;
        xxxLBSetCaret(plb, TRUE);
        if (FWINABLE()) {
            if (_IsWindowVisible(pwnd)) {
                LBEvent(plb, EVENT_OBJECT_FOCUS, plb->iSelBase);
            }
        }
        return(plb->iSel);

    case LBCB_CARETOFF:

        /*
         * Internal message for combo box support
         */
        xxxLBSetCaret(plb, FALSE);
        xxxCaretDestroy(plb);
        break;

    case WM_NCCREATE:
        if ((pwnd->style & LBS_MULTICOLUMN) && (pwnd->style & WS_VSCROLL))
        {
            DWORD mask = WS_VSCROLL;
            DWORD flags = 0;
            if (!TestWF(pwnd, WFWIN40COMPAT)) {
                mask |= WS_HSCROLL;
                flags = WS_HSCROLL;
            }
            NtUserAlterWindowStyle(hwnd, mask, flags);
        }
        goto CallDWP;

     default:
CallDWP:
        return DefWindowProcWorker(pwnd, message, wParam, lParam, fAnsi);
    }

    /*
     * Handle translation of ANSI output data and free buffer
     */
    if (lpwsz) {
        UserLocalFree(lpwsz);
    }

    return lReturn;
}