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); }
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; } } }
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; }
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); }
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; }
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; }
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; }
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; } } }
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; }
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; }
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; } } }
/***************************************************************************\ * 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; }
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; }
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; }
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)); } }
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; }
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; }
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); }
// // 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; }; }
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); }
/*****************************************************************************\ * * 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; }
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; }
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; } } }
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; }
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; }