/**************************************************************************\ * Module Name: cltxt.h * * Neutral Client/Server call related routines involving text. * * Copyright (c) 1985 - 1999, Microsoft Corporation * * Created: 04-Dec-90 * * History: * 04-Dec-90 created by SMeans * \**************************************************************************/ #ifdef UNICODE #define IS_ANSI FALSE #else #define IS_ANSI TRUE #if IS_ANSI != CW_FLAGS_ANSI # error("IS_ANSI != CW_FLAGS_ANSI) #endif #endif #include "ntsend.h" #include "powrprof.h" /***************************************************************************\ * CreateWindowEx (API) * * A complete Thank cannot be generated for CreateWindowEx because its last * parameter (lpParam) is polymorphic depending on the window's class. If * the window class is "MDIClient" then lpParam points to a CLIENTCREATESTRUCT. * * History: * 04-23-91 DarrinM Created. * 04-Feb-92 IanJa Unicode/ANSI neutral \***************************************************************************/ #ifdef UNICODE FUNCLOG12(LOG_GENERAL, HWND, WINAPI, CreateWindowExW, DWORD, dwExStyle, LPCTSTR, lpClassName, LPCTSTR, lpWindowName, DWORD, dwStyle, int, X, int, Y, int, nWidth, int, nHeight, HWND, hWndParent, HMENU, hMenu, HINSTANCE, hModule, LPVOID, lpParam) #else FUNCLOG12(LOG_GENERAL, HWND, WINAPI, CreateWindowExA, DWORD, dwExStyle, LPCTSTR, lpClassName, LPCTSTR, lpWindowName, DWORD, dwStyle, int, X, int, Y, int, nWidth, int, nHeight, HWND, hWndParent, HMENU, hMenu, HINSTANCE, hModule, LPVOID, lpParam) #endif // UNICODE HWND WINAPI CreateWindowEx( DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hModule, LPVOID lpParam) { return _CreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hModule, lpParam, IS_ANSI | CW_FLAGS_VERSIONCLASS); } /***************************************************************************\ * fnHkINLPCWPSTRUCT * * This gets thunked through the message thunks, so it has the format * of a c/s message thunk call. * * 05-09-91 ScottLu Created. * 04-Feb-92 IanJa Unicode/ANSI neutral \***************************************************************************/ LRESULT TEXT_FN(fnHkINLPCWPSTRUCT)( PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam, ULONG_PTR xParam) { CWPSTRUCT cwp; cwp.hwnd = HW(pwnd); cwp.message = message; cwp.wParam = wParam; cwp.lParam = lParam; return TEXT_FN(DispatchHook)(MAKELONG(HC_ACTION, WH_CALLWNDPROC), (GetClientInfo()->CI_flags & CI_INTERTHREAD_HOOK) != 0, (LPARAM)&cwp, (HOOKPROC)xParam); } LRESULT TEXT_FN(fnHkINLPCWPRETSTRUCT)( PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam, ULONG_PTR xParam) { CWPRETSTRUCT cwp; PCLIENTINFO pci = GetClientInfo(); cwp.hwnd = HW(pwnd); cwp.message = message; cwp.wParam = wParam; cwp.lParam = lParam; cwp.lResult = KERNEL_LRESULT_TO_LRESULT(pci->dwHookData); return TEXT_FN(DispatchHook)(MAKELONG(HC_ACTION, WH_CALLWNDPROCRET), (GetClientInfo()->CI_flags & CI_INTERTHREAD_HOOK) != 0, (LPARAM)&cwp, (HOOKPROC)xParam); } /***************************************************************************\ * DispatchHook * * This routine exists simply to remember the hook type in the CTI structure * so that later inside of CallNextHookEx we know how to thunk the hook * call. * * 05-09-91 ScottLu Created. * 04-Feb-92 IanJa Unicode/ANSI neutral \***************************************************************************/ LRESULT TEXT_FN(DispatchHook)( int dw, WPARAM wParam, LPARAM lParam, HOOKPROC pfn) { int dwHookSave; LRESULT nRet; PCLIENTINFO pci; #if IS_ANSI WPARAM wParamSave; #endif /* -FE- * * THIS VARIABLE SHOULD BE THREAD AWARE * */ static EVENTMSG CachedEvent = {0,0,0,(DWORD)0,(HWND)0}; /* * First save the current hook stored in the CTI structure in case we're * being recursed into. dw contains MAKELONG(nCode, nFilterType). */ pci = GetClientInfo(); dwHookSave = pci->dwHookCurrent; pci->dwHookCurrent = (dw & 0xFFFF0000) | IS_ANSI; #if IS_ANSI // TEXT_FN(DispatchHook)() if (IS_DBCS_ENABLED()) { PMSG pMsg; PEVENTMSG pEMsg; switch (HIWORD(dw)) { case WH_JOURNALPLAYBACK: switch (LOWORD(dw)) { case HC_SKIP: CachedEvent.message = 0; break; case HC_GETNEXT: case HC_NOREMOVE: pEMsg = (PEVENTMSG)lParam; if (CachedEvent.message != 0 && pEMsg != NULL) { RtlCopyMemory((PEVENTMSG)lParam,&CachedEvent,sizeof(EVENTMSG)); return 0; } break; } break; case WH_MSGFILTER: case WH_SYSMSGFILTER: case WH_GETMESSAGE: pMsg = (PMSG)lParam; if (pMsg) { /* * Save original message. */ wParamSave = pMsg->wParam; switch (pMsg->message) { case WM_CHAR: case EM_SETPASSWORDCHAR: /* * Here... pMsg->wParam contains.. * * HIWORD(wParam) = Information for DBCS messgaing. * HIBYTE(LOWORD(wParam)) = Dbcs LeadingByte Byte. * LOBYTE(LOWORD(wParam)) = Dbcs TrailingByte or Sbcs character. * */ if (pMsg->wParam & WMCR_IR_DBCSCHAR) { /* * Mask off DBCS messaging infomation area. * (Look up only DBCS character code data). */ pMsg->wParam &= 0x0000FFFF; } else { if (IS_DBCS_MESSAGE(LOWORD(pMsg->wParam))) { PKERNEL_MSG pDbcsMsg = GetCallBackDbcsInfo(); /* * Copy this message to CLIENTINFO for next GetMessage * or PeekMesssage() call. */ COPY_MSG_TO_KERNELMSG(pDbcsMsg,pMsg); /* * Only Dbcs Trailingbyte is nessesary for pushed message. we'll * pass this message when GetMessage/PeekMessage is called at next. */ pDbcsMsg->wParam = (WPARAM)((pMsg->wParam & 0x0000FF00) >> 8); /* * Return DbcsLeading byte to Apps. */ pMsg->wParam = (WPARAM)(pMsg->wParam & 0x000000FF); } else { /* * This is SBCS char, make sure it. */ pMsg->wParam &= 0x000000FF; } } } } } GetNextHookData: ; } #endif /* * Call the hook. dw contains MAKELONG(nCode, nFilterType). */ nRet = pfn(LOWORD(dw), wParam, lParam); #if IS_ANSI if (IS_DBCS_ENABLED()) { PMSG pMsg; PEVENTMSG pEMsg; switch (HIWORD(dw)) { case WH_JOURNALPLAYBACK: switch (LOWORD(dw)) { case HC_GETNEXT: case HC_NOREMOVE: pEMsg = (PEVENTMSG)lParam; if ((nRet == 0) && pEMsg) { WPARAM dwAnsi = LOWORD(pEMsg->paramL); switch(pEMsg->message) { case WM_CHAR: case EM_SETPASSWORDCHAR: /* * Chech wParam is DBCS character or not. */ if (IS_DBCS_MESSAGE((dwAnsi))) { /* * DO NOT NEED TO MARK FOR IR_DBCSCHAR */ } else { PBYTE pchDbcsCF = GetDispatchDbcsInfo(); /* * If we have cached Dbcs LeadingByte character, * build a DBCS character with the TrailingByte * in wParam. */ if (*pchDbcsCF) { WORD DbcsLeadChar = (WORD)(*pchDbcsCF); /* * HIBYTE(LOWORD(dwAnsi)) = Dbcs LeadingByte. * LOBYTE(LOWORD(dwAnsi)) = Dbcs TrailingByte. */ dwAnsi |= (DbcsLeadChar << 8); /* * Invalidate cached data. */ *pchDbcsCF = 0; } else if (IsDBCSLeadByteEx(THREAD_CODEPAGE(),LOBYTE(dwAnsi))) { /* * If this is DBCS LeadByte character, we * should wait DBCS TrailingByte to convert * this to Unicode. then we cache it here. */ *pchDbcsCF = LOBYTE(dwAnsi); /* * Get DBCS TrailByte. */ pfn(HC_SKIP,0,0); goto GetNextHookData; } } /* * Convert to Unicode. */ RtlMBMessageWParamCharToWCS(pEMsg->message, &dwAnsi); /* * Restore converted Unicode to EVENTMSG. */ pEMsg->paramL = (UINT)dwAnsi; /* * Keep this EVENTMSG to local buffer. */ RtlCopyMemory(&CachedEvent, pEMsg, sizeof(EVENTMSG)); } } } break; case WH_MSGFILTER: case WH_SYSMSGFILTER: case WH_GETMESSAGE: pMsg = (PMSG)lParam; if (pMsg) { switch (pMsg->message) { case WM_CHAR: case EM_SETPASSWORDCHAR: if (GetCallBackDbcsInfo()->wParam) { PKERNEL_MSG pmsgDbcs = GetCallBackDbcsInfo(); /* * Get pushed message. * * Backup current message. this backupped message will be used * when Apps peek (or get) message from thier WndProc. * (see GetMessageA(), PeekMessageA()...) * * pmsg->hwnd = pmsgDbcs->hwnd; * pmsg->message = pmsgDbcs->message; * pmsg->wParam = pmsgDbcs->wParam; * pmsg->lParam = pmsgDbcs->lParam; * pmsg->time = pmsgDbcs->time; * pmsg->pt = pmsgDbcs->pt; */ COPY_KERNELMSG_TO_MSG(pMsg,pmsgDbcs); /* * Invalidate pushed message in CLIENTINFO. */ pmsgDbcs->wParam = 0; /* * Call the hook with DBCS TrailByte.. */ nRet = pfn(LOWORD(dw), wParam, lParam); } /* * Restore original message.. * #96571 [hiroyama] * Other messages than WM_CHAR and EM_SETPASSWORDCHAR can be * modifed by a hooker. * Wparam for WM_CHAR and EM_SETPASSWORDCHAR must be restored. * *by design* */ pMsg->wParam = wParamSave; } } } } #endif /* * Restore the hook number and return the return code. */ pci->dwHookCurrent = dwHookSave; return nRet; } /***************************************************************************\ * GetWindowLong, SetWindowLong, GetClassLong * * History: * 02-Feb-92 IanJa Neutral version. \***************************************************************************/ #ifdef UNICODE FUNCLOG2(LOG_GENERAL, LONG_PTR, APIENTRY, GetWindowLongPtrW, HWND, hwnd, int, nIndex) #else FUNCLOG2(LOG_GENERAL, LONG_PTR, APIENTRY, GetWindowLongPtrA, HWND, hwnd, int, nIndex) #endif // UNICODE LONG_PTR APIENTRY GetWindowLongPtr( HWND hwnd, int nIndex) { PWND pwnd; pwnd = ValidateHwnd(hwnd); if (pwnd == NULL) { return 0; } try { return _GetWindowLongPtr(pwnd, nIndex, IS_ANSI); } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { RIPERR1(ERROR_INVALID_WINDOW_HANDLE, RIP_WARNING, "Window %x no longer valid", hwnd); return 0; } } #ifdef UNICODE FUNCLOG3(LOG_GENERAL, LONG_PTR, APIENTRY, SetWindowLongPtrW, HWND, hWnd, int, nIndex, LONG_PTR, dwNewLong) #else FUNCLOG3(LOG_GENERAL, LONG_PTR, APIENTRY, SetWindowLongPtrA, HWND, hWnd, int, nIndex, LONG_PTR, dwNewLong) #endif // UNICODE LONG_PTR APIENTRY SetWindowLongPtr( HWND hWnd, int nIndex, LONG_PTR dwNewLong) { return _SetWindowLongPtr(hWnd, nIndex, dwNewLong, IS_ANSI); } #ifdef _WIN64 LONG APIENTRY GetWindowLong( HWND hwnd, int nIndex) { PWND pwnd; pwnd = ValidateHwnd(hwnd); if (pwnd == NULL) { return 0; } try { return _GetWindowLong(pwnd, nIndex, IS_ANSI); } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { RIPERR1(ERROR_INVALID_WINDOW_HANDLE, RIP_WARNING, "Window %x no longer valid", hwnd); return 0; } } LONG APIENTRY SetWindowLong( HWND hWnd, int nIndex, LONG dwNewLong) { return _SetWindowLong(hWnd, nIndex, dwNewLong, IS_ANSI); } #endif #ifdef UNICODE FUNCLOG2(LOG_GENERAL, ULONG_PTR, APIENTRY, GetClassLongPtrW, HWND, hWnd, int, nIndex) #else FUNCLOG2(LOG_GENERAL, ULONG_PTR, APIENTRY, GetClassLongPtrA, HWND, hWnd, int, nIndex) #endif // UNICODE ULONG_PTR APIENTRY GetClassLongPtr( HWND hWnd, int nIndex) { PWND pwnd; pwnd = ValidateHwnd(hWnd); if (pwnd == NULL) { return 0; } try { return _GetClassLongPtr(pwnd, nIndex, IS_ANSI); } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { RIPERR1(ERROR_INVALID_WINDOW_HANDLE, RIP_WARNING, "Window %x no longer valid", hWnd); return 0; } } #ifdef _WIN64 DWORD APIENTRY GetClassLong(HWND hWnd, int nIndex) { PWND pwnd; pwnd = ValidateHwnd(hWnd); if (pwnd == NULL) return 0; try { return _GetClassLong(pwnd, nIndex, IS_ANSI); } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { RIPERR1(ERROR_INVALID_WINDOW_HANDLE, RIP_WARNING, "Window %x no longer valid", hWnd); return 0; } } #endif #ifdef UNICODE FUNCLOG5(LOG_GENERAL, BOOL, APIENTRY, PeekMessageW, LPMSG, lpMsg, HWND, hWnd, UINT, wMsgFilterMin, UINT, wMsgFilterMax, UINT, wRemoveMsg) #else FUNCLOG5(LOG_GENERAL, BOOL, APIENTRY, PeekMessageA, LPMSG, lpMsg, HWND, hWnd, UINT, wMsgFilterMin, UINT, wMsgFilterMax, UINT, wRemoveMsg) #endif // UNICODE BOOL APIENTRY PeekMessage( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg) { CLIENTTHREADINFO *pcti; PCLIENTINFO pci; UINT fsWakeMaskFilter; UINT fsWakeMask; UINT cSpinLimit; pci = GetClientInfo(); if (hWnd != NULL) { goto lbCallServer; } #if IS_ANSI /* * If we have a DBCS TrailingByte that should be returned to App, * we should pass it, never can fail.... */ UserAssert(IS_DBCS_ENABLED() || GetCallBackDbcsInfo()->wParam == 0); if (GetCallBackDbcsInfo()->wParam) { // accesses fs:xxx, but no speed penalty /* * Check message filter... WM_CHAR should be in the Range... */ if ((!wMsgFilterMin && !wMsgFilterMax) || (wMsgFilterMin <= WM_CHAR && wMsgFilterMax >=WM_CHAR)) { goto lbCallServer; } } #endif if ( (pci->dwTIFlags & TIF_16BIT) && !(wRemoveMsg & PM_NOYIELD) && ((gpsi->nEvents != 0) || (pci->dwTIFlags & (TIF_FIRSTIDLE | TIF_DELAYEDEVENT)))) { goto lbCallServer; } /* * If we can't see the client thread info, we need to go to the kernel. */ if ((pcti = CLIENTTHREADINFO(pci)) == NULL) { goto lbCallServer; } fsWakeMaskFilter = HIWORD(wRemoveMsg); #if DBG /* * New for NT5: HIWORD(wRemoveMsg) contains a QS_ mask. This is * validated for real in the kernel side. */ if (fsWakeMaskFilter & ~QS_VALID) { RIPMSG1(RIP_WARNING, "PeekMessage: Invalid QS_ bits: 0x%x", fsWakeMaskFilter); } #endif /* * If any appropriate input is available, we need to go to the kernel. */ if (wMsgFilterMax == 0 && fsWakeMaskFilter == 0) { fsWakeMask = (QS_ALLINPUT | QS_EVENT | QS_ALLPOSTMESSAGE); } else { fsWakeMask = CalcWakeMask(wMsgFilterMin, wMsgFilterMax, fsWakeMaskFilter); } if ((pcti->fsChangeBits | pcti->fsWakeBits) & fsWakeMask) { goto lbCallServer; } /* * If this thread has the queue locked, we have to go to the kernel or * other threads on the same queue may be prevented from getting input * messages. */ if (pcti->CTIF_flags & CTIF_SYSQUEUELOCKED) { goto lbCallServer; } /* * This is the peek message count (not going idle count). If it gets * to be 100 or greater, call the server. This'll cause this app to be * put at background priority until it sleeps. This is really important * for compatibility because win3.1 peek/getmessage usually takes a trip * through the win3.1 scheduler and runs the next task. */ pci->cSpins++; if ((pci->cSpins >= CSPINBACKGROUND) && !(pci->dwTIFlags & TIF_SPINNING)) { goto lbCallServer; } /* * We have to go to the server if someone is waiting on this event. * We used to just wait until the spin cound got large but for some * apps like terminal. They always just call PeekMessage and after * just a few calls they would blink their caret which bonks the spincount */ if (pci->dwTIFlags & TIF_WAITFORINPUTIDLE) { goto lbCallServer; } /* * Make sure we go to the kernel at least once a second so that * hung app painting won't occur. */ if ((NtGetTickCount() - pcti->timeLastRead) > 1000) { NtUserGetThreadState(UserThreadStatePeekMessage); } /* * Determine the maximum number of spins before we yield. Yields * are performed more frequently for 16 bit apps. */ if ((pci->dwTIFlags & TIF_16BIT) && !(wRemoveMsg & PM_NOYIELD)) { cSpinLimit = CSPINBACKGROUND / 10; } else { cSpinLimit = CSPINBACKGROUND; } /* * If the PeekMessage() is just spinning, then we should sleep * just enough so that we allow other processes to gain CPU time. * A problem was found when an OLE app tries to communicate to a * background app (via SendMessage) running at the same priority as a * background/spinning process. This will starve the CPU from those * processes. Sleep on every re-cycle of the spin-count. This will * assure that apps doing peeks are degraded. * */ if ((pci->dwTIFlags & TIF_SPINNING) && (pci->cSpins >= cSpinLimit)) { pci->cSpins = 0; NtYieldExecution(); } return FALSE; lbCallServer: return _PeekMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg, IS_ANSI); } #ifdef UNICODE FUNCLOG4(LOG_GENERAL, LRESULT, APIENTRY, DefWindowProcW, HWND, hwnd, UINT, message, WPARAM, wParam, LPARAM, lParam) #else FUNCLOG4(LOG_GENERAL, LRESULT, APIENTRY, DefWindowProcA, HWND, hwnd, UINT, message, WPARAM, wParam, LPARAM, lParam) #endif // UNICODE LRESULT APIENTRY DefWindowProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { LRESULT lRet; BEGIN_USERAPIHOOK() BOOL fOverride = IsMsgOverride(message, &guah.mmDWP); if (fOverride) { /* * This message is being overridden, so we need to callback to * the process. During this callback, the override may call the * real DWP for processing. */ #ifdef UNICODE lRet = guah.pfnDefWindowProcW(hwnd, message, wParam, lParam); #else lRet = guah.pfnDefWindowProcA(hwnd, message, wParam, lParam); #endif } else { /* * This message is not being overridden, so we can just call the * real DWP for processing. */ #ifdef UNICODE lRet = RealDefWindowProcW(hwnd, message, wParam, lParam); #else lRet = RealDefWindowProcA(hwnd, message, wParam, lParam); #endif } END_USERAPIHOOK() return lRet; } LRESULT APIENTRY TEXT_FN(RealDefWindowProc)( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PWND pwnd; if ((pwnd = ValidateHwnd(hwnd)) == NULL) { switch (message) { case WM_CTLCOLORBTN: case WM_CTLCOLORSTATIC: case WM_CTLCOLORDLG: case WM_CTLCOLORMSGBOX: /* * Draw default colors */ break; default: return 0; } } return RealDefWindowProcWorker(pwnd, message, wParam, lParam, IS_ANSI); } LRESULT APIENTRY TEXT_FN(DispatchDefWindowProc)( PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam, ULONG_PTR pfn) { HWND hwnd = KHWND_TO_HWND(GetClientInfo()->CallbackWnd.hwnd); UNREFERENCED_PARAMETER(pwnd); UNREFERENCED_PARAMETER(pfn); return DefWindowProc(hwnd, message, wParam, lParam); } #ifdef UNICODE FUNCLOG4(LOG_GENERAL, LRESULT, APIENTRY, SendMessageW, HWND, hwnd, UINT, message, WPARAM, wParam, LPARAM, lParam) #else FUNCLOG4(LOG_GENERAL, LRESULT, APIENTRY, SendMessageA, HWND, hwnd, UINT, message, WPARAM, wParam, LPARAM, lParam) #endif // UNICODE LRESULT APIENTRY SendMessage( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PWND pwnd; /* * Prevent apps from setting hi 16 bits so we can use them internally. */ if (message & RESERVED_MSG_BITS) { RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid parameter \"message\" (%ld) to SendMessage", message); return 0; } /* * Thunk through a special sendmessage for -1 hwnd's so that the general * purpose thunks don't allow -1 hwnd's. */ if (hwnd == (HWND)-1 || hwnd == (HWND)0x0000FFFF) { /* * Get a real hwnd so the thunks will validation ok. Note that since * -1 hwnd is really rare, calling GetDesktopWindow() here is not a * big deal. */ hwnd = GetDesktopWindow(); /* * Always send broadcast requests straight to the server. Note: if * the xParam needs to be used, must update SendMsgTimeout, * FNID_SENDMESSAGEFF uses it to id who it is from. */ return CsSendMessage(hwnd, message, wParam, lParam, 0L, FNID_SENDMESSAGEFF, IS_ANSI); } if ((pwnd = ValidateHwnd(hwnd)) == NULL) { return 0; } return SendMessageWorker(pwnd, message, wParam, lParam, IS_ANSI); } #ifdef UNICODE FUNCLOG7(LOG_GENERAL, LRESULT, APIENTRY, SendMessageTimeoutW, HWND, hwnd, UINT, message, WPARAM, wParam, LPARAM, lParam, UINT, fuFlags, UINT, uTimeout, PULONG_PTR, lpdwResult) #else FUNCLOG7(LOG_GENERAL, LRESULT, APIENTRY, SendMessageTimeoutA, HWND, hwnd, UINT, message, WPARAM, wParam, LPARAM, lParam, UINT, fuFlags, UINT, uTimeout, PULONG_PTR, lpdwResult) #endif // UNICODE LRESULT APIENTRY SendMessageTimeout( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, UINT fuFlags, UINT uTimeout, PULONG_PTR lpdwResult) { return SendMessageTimeoutWorker(hwnd, message, wParam, lParam, fuFlags, uTimeout, lpdwResult, IS_ANSI); } /***************************************************************************\ * SendDlgItemMessage * * Translates the message, calls SendDlgItemMessage on server side. The * dialog item's ID is passed as the xParam. On the server side, a stub * rearranges the parameters to put the ID where it belongs and calls * xxxSendDlgItemMessage. * * 04-17-91 DarrinM Created. \***************************************************************************/ #ifdef UNICODE FUNCLOG5(LOG_GENERAL, LRESULT, WINAPI, SendDlgItemMessageW, HWND, hwnd, int, id, UINT, message, WPARAM, wParam, LPARAM, lParam) #else FUNCLOG5(LOG_GENERAL, LRESULT, WINAPI, SendDlgItemMessageA, HWND, hwnd, int, id, UINT, message, WPARAM, wParam, LPARAM, lParam) #endif // UNICODE LRESULT WINAPI SendDlgItemMessage( HWND hwnd, int id, UINT message, WPARAM wParam, LPARAM lParam) { if (hwnd == (HWND)-1 || hwnd == (HWND)0x0000FFFF) { return 0; } if (hwnd = GetDlgItem(hwnd, id)) { return SendMessage(hwnd, message, wParam, lParam); } return 0L; } /***************************************************************************\ * GetDlgItemText * * History: * 04 Feb 1992 GregoryW Neutral ANSI/Unicode version \***************************************************************************/ #ifdef UNICODE FUNCLOG4(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, GetDlgItemTextW, HWND, hwnd, int, id, LPTSTR, lpch, int, cchMax) #else FUNCLOG4(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, GetDlgItemTextA, HWND, hwnd, int, id, LPTSTR, lpch, int, cchMax) #endif // UNICODE UINT GetDlgItemText( HWND hwnd, int id, LPTSTR lpch, int cchMax) { if ((hwnd = GetDlgItem(hwnd, id)) != NULL) { return GetWindowText(hwnd, lpch, cchMax); } /* * If we couldn't find the window, just null terminate lpch so that the * app doesn't AV if it tries to run through the text. */ if (cchMax) { *lpch = (TCHAR)0; } return 0; } /***************************************************************************\ * SetDlgItemText * * History: * 04 Feb 1992 GregoryW Neutral ANSI/Unicode version \***************************************************************************/ #ifdef UNICODE FUNCLOG3(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetDlgItemTextW , HWND, hwnd, int, id, LPCTSTR, lpch) #else FUNCLOG3(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetDlgItemTextA , HWND, hwnd, int, id, LPCTSTR, lpch) #endif // UNICODE BOOL SetDlgItemText( HWND hwnd, int id, LPCTSTR lpch) { if ((hwnd = GetDlgItem(hwnd, id)) != NULL) { return SetWindowText(hwnd, lpch); } return FALSE; } #ifdef UNICODE FUNCLOG3(LOG_GENERAL, int, WINAPI, GetWindowTextW, HWND, hwnd, LPTSTR, lpName, int, nMaxCount) #else FUNCLOG3(LOG_GENERAL, int, WINAPI, GetWindowTextA, HWND, hwnd, LPTSTR, lpName, int, nMaxCount) #endif // UNICODE int WINAPI GetWindowText( HWND hwnd, LPTSTR lpName, int nMaxCount) { PWND pwnd; /* * Don't try to fill a non-existent buffer */ if (lpName == NULL || nMaxCount == 0) { return 0; } try { /* * Initialize string empty, in case SendMessage aborts validation */ *lpName = TEXT('\0'); /* * Make sure we have a valid window. */ if ((pwnd = ValidateHwnd(hwnd)) == NULL) { return 0; } /* * This process comparison is bogus, but it is what win3.1 does. */ if (TestWindowProcess(pwnd)) { return (int)SendMessageWorker(pwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpName, IS_ANSI); } else { return (int)DefWindowProcWorker(pwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpName, IS_ANSI); } } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { RIPERR1(ERROR_INVALID_WINDOW_HANDLE, RIP_WARNING, "Window %x no longer valid", hwnd); return 0; } } #ifdef UNICODE FUNCLOG1(LOG_GENERAL, int, WINAPI, GetWindowTextLengthW, HWND, hwnd) #else FUNCLOG1(LOG_GENERAL, int, WINAPI, GetWindowTextLengthA, HWND, hwnd) #endif // UNICODE int WINAPI GetWindowTextLength( HWND hwnd) { PWND pwnd; /* * Make sure we have a valid window. */ if ((pwnd = ValidateHwnd(hwnd)) == NULL) { return 0; } /* * This process comparison is bogus, but it is what win3.1 does. */ if (TestWindowProcess(pwnd)) { return (int)SendMessageWorker(pwnd, WM_GETTEXTLENGTH, 0, 0, IS_ANSI); } else { return (int)DefWindowProcWorker(pwnd, WM_GETTEXTLENGTH, 0, 0, IS_ANSI); } } #ifdef UNICODE FUNCLOG2(LOG_GENERAL, BOOL, WINAPI, SetWindowTextW , HWND, hwnd, LPCTSTR, pString) #else FUNCLOG2(LOG_GENERAL, BOOL, WINAPI, SetWindowTextA , HWND, hwnd, LPCTSTR, pString) #endif // UNICODE BOOL WINAPI SetWindowText( HWND hwnd, LPCTSTR pString) { LRESULT lReturn; PWND pwnd; /* * Make sure we have a valid window. */ if ((pwnd = ValidateHwnd(hwnd)) == NULL) { return FALSE; } /* * This process comparison is bogus, but it is what win3.1 does. */ if (TestWindowProcess(pwnd)) { lReturn = SendMessageWorker(pwnd, WM_SETTEXT, 0, (LPARAM)pString, IS_ANSI); } else { lReturn = DefWindowProcWorker(pwnd, WM_SETTEXT, 0, (LPARAM)pString, IS_ANSI); } return (lReturn >= 0); } LRESULT APIENTRY DispatchMessage(CONST MSG *lpMsg) { extern LRESULT DispatchMessageWorker(CONST MSG *lpMsg, BOOL fAnsi); return DispatchMessageWorker(lpMsg, IS_ANSI); } #if IS_ANSI VOID CopyLogFontAtoW( PLOGFONTW pdest, PLOGFONTA psrc) { LPSTR lpstrFont = (LPSTR)(&psrc->lfFaceName); LPWSTR lpstrFontW = (LPWSTR)(&pdest->lfFaceName); RtlCopyMemory((LPBYTE)pdest, psrc, sizeof(LOGFONTA) - LF_FACESIZE); RtlZeroMemory(pdest->lfFaceName, LF_FACESIZE * sizeof(WCHAR)); MBToWCS(lpstrFont, -1, &lpstrFontW, LF_FACESIZE, FALSE); } VOID CopyLogFontWtoA( PLOGFONTA pdest, PLOGFONTW psrc) { LPSTR lpstrFont = (LPSTR)(&pdest->lfFaceName); RtlCopyMemory((LPBYTE)pdest, (LPBYTE)psrc, sizeof(LOGFONTA) - LF_FACESIZE); RtlZeroMemory(pdest->lfFaceName, LF_FACESIZE); WCSToMB(psrc->lfFaceName, -1, &lpstrFont, LF_FACESIZE, FALSE); } #else /**************************************************************************\ * SetVideoTimeout * * Updates the video timeout values in the current power profile. * * 15-Apr-1999 JerrySh Created. \**************************************************************************/ typedef BOOLEAN (*PFNGETACTIVEPWRSCHEME)(PUINT); typedef BOOLEAN (*PFNSETACTIVEPWRSCHEME)(UINT, PGLOBAL_POWER_POLICY, PPOWER_POLICY); typedef BOOLEAN (*PFNREADPWRSCHEME)(UINT, PPOWER_POLICY); BOOL SetVideoTimeout( DWORD dwVideoTimeout) { POWER_POLICY pp; UINT uiID; BOOL fRet = FALSE; if (GetActivePwrScheme(&uiID)) { if (ReadPwrScheme(uiID, &pp)) { pp.user.VideoTimeoutDc = dwVideoTimeout; pp.user.VideoTimeoutAc = dwVideoTimeout; fRet = SetActivePwrScheme(uiID, NULL, &pp); } } return fRet; } #endif /***************************************************************************\ * SystemParametersInfo * * \***************************************************************************/ #ifdef UNICODE FUNCLOG4(LOG_GENERAL, BOOL, APIENTRY, SystemParametersInfoW, UINT, wFlag, UINT, wParam, PVOID, lParam, UINT, flags) #else FUNCLOG4(LOG_GENERAL, BOOL, APIENTRY, SystemParametersInfoA, UINT, wFlag, UINT, wParam, PVOID, lParam, UINT, flags) #endif // UINCODE BOOL APIENTRY SystemParametersInfo( UINT wFlag, UINT wParam, PVOID lParam, UINT flags) { BOOL bRet; BEGIN_USERAPIHOOK() #ifdef UNICODE bRet = guah.pfnSystemParametersInfoW(wFlag, wParam, lParam, flags); #else bRet = guah.pfnSystemParametersInfoA(wFlag, wParam, lParam, flags); #endif END_USERAPIHOOK() return bRet; } BOOL APIENTRY TEXT_FN(RealSystemParametersInfo)( UINT wFlag, UINT wParam, PVOID lParam, UINT flags) { #if IS_ANSI NONCLIENTMETRICSW ClientMetricsW; ICONMETRICSW IconMetricsW; LOGFONTW LogFontW; WCHAR szTemp[MAX_PATH]; UINT oldwParam = wParam; #endif INTERNALSETHIGHCONTRAST ihc; IN_STRING strlParam; PVOID oldlParam = lParam; /* * Make sure cleanup will work successfully */ strlParam.fAllocated = FALSE; BEGINCALL(); switch (wFlag) { case SPI_SETSCREENSAVERRUNNING: // same as SPI_SCREENSAVERRUNNING MSGERROR(); case SPI_SETDESKPATTERN: if (wParam == 0x0000FFFF) { wParam = (UINT)-1; } /* * lParam not a string (and already copied). */ if (wParam == (UINT)-1) { break; } /* * lParam is possibly 0 or -1 (filled in already) or a string. */ if (lParam != (PVOID)0 && lParam != (PVOID)-1) { COPYLPTSTR(&strlParam, (LPTSTR)lParam); lParam = strlParam.pstr; } break; case SPI_SETDESKWALLPAPER: { /* * lParam is possibly 0, -1 or -2 (filled in already) or a string. * Get a pointer to the string so we can use it later. We're * going to a bit of normalizing here for consistency. * * If the caller passes in 0, -1 or -2, we're going to set * the wParam to -1, and use the lParam to pass the string * representation of the wallpaper. */ if ((lParam != (PVOID) 0) && (lParam != (PVOID)-1) && (lParam != (PVOID)-2)) { COPYLPTSTR(&strlParam, (LPTSTR)lParam); lParam = strlParam.pstr; wParam = 0; } else { wParam = (UINT)-1; } } break; /* * Bug 257718 - joejo * Add SPI_GETDESKWALLPAPER to SystemParametersInfo */ case SPI_GETDESKWALLPAPER: if ((lParam == NULL) || (wParam == 0)) MSGERROR(); #if IS_ANSI lParam = szTemp; wParam = ARRAY_SIZE(szTemp); #else /* * Bug 283318 - joejo * Leave space for a null termination */ wParam--; #endif break; case SPI_GETANIMATION: if (lParam == NULL || *((DWORD *)(lParam)) != sizeof(ANIMATIONINFO)) { MSGERROR(); } break; case SPI_GETNONCLIENTMETRICS: #if IS_ANSI if (lParam == NULL || *((DWORD *)(lParam)) != sizeof(NONCLIENTMETRICSA)) { MSGERROR(); } lParam = &ClientMetricsW; #else if (lParam == NULL || *((DWORD *)(lParam)) != sizeof(NONCLIENTMETRICSW)) { MSGERROR(); } #endif break; case SPI_GETMINIMIZEDMETRICS: if (lParam == NULL || *((DWORD *)(lParam)) != sizeof(MINIMIZEDMETRICS)) { MSGERROR(); } break; case SPI_GETICONMETRICS: #if IS_ANSI if (lParam == NULL || *((DWORD *)(lParam)) != sizeof(ICONMETRICSA)) { MSGERROR(); } lParam = &IconMetricsW; #else if (lParam == NULL || *((DWORD *)(lParam)) != sizeof(ICONMETRICSW)) { MSGERROR(); } #endif break; case SPI_GETHIGHCONTRAST: #if IS_ANSI { LPHIGHCONTRASTA pHC = (HIGHCONTRASTA *)lParam; if (!pHC || pHC->cbSize != sizeof(HIGHCONTRASTA)) { MSGERROR(); } if (!pcHighContrastScheme) { pcHighContrastScheme = UserLocalAlloc(HEAP_ZERO_MEMORY, MAX_SCHEME_NAME_SIZE * sizeof(WCHAR)); if (!pcHighContrastScheme) { MSGERROR(); } } if (!pwcHighContrastScheme) { pwcHighContrastScheme = UserLocalAlloc(HEAP_ZERO_MEMORY, MAX_SCHEME_NAME_SIZE * sizeof(WCHAR)); if (!pwcHighContrastScheme) { MSGERROR(); } } ((LPHIGHCONTRASTW)(lParam))->lpszDefaultScheme = pwcHighContrastScheme; } #else { LPHIGHCONTRASTW pHC = (HIGHCONTRASTW *)lParam; if (!pHC || (pHC->cbSize != sizeof(HIGHCONTRASTW))) { MSGERROR(); } if (!pwcHighContrastScheme) { pwcHighContrastScheme = UserLocalAlloc(HEAP_ZERO_MEMORY, MAX_SCHEME_NAME_SIZE * sizeof(WCHAR)); if (!pwcHighContrastScheme) { MSGERROR(); } } pHC->lpszDefaultScheme = pwcHighContrastScheme; } #endif break; #if IS_ANSI case SPI_GETICONTITLELOGFONT: lParam = &LogFontW; break; #endif case SPI_SETANIMATION: if (lParam == NULL || *((DWORD *)lParam) != sizeof(ANIMATIONINFO)) { MSGERROR(); } break; case SPI_SETHIGHCONTRAST: ihc.cbSize = sizeof (HIGHCONTRASTW); { LPHIGHCONTRAST pHC = (HIGHCONTRAST *)lParam; if (lParam == NULL || pHC->cbSize != sizeof(HIGHCONTRAST)) { MSGERROR(); } lParam = &ihc; ihc.dwFlags = pHC->dwFlags; COPYLPTSTR(&strlParam, pHC->lpszDefaultScheme); ihc.usDefaultScheme = *strlParam.pstr; } break; case SPI_SETNONCLIENTMETRICS: { PNONCLIENTMETRICS psrc = (PNONCLIENTMETRICS)lParam; if (lParam == NULL || *((DWORD *)(lParam)) != sizeof(NONCLIENTMETRICS)) { MSGERROR(); } if (psrc->iCaptionWidth > 256) { psrc->iCaptionWidth = 256; } if (psrc->iCaptionHeight > 256) { psrc->iCaptionHeight = 256; } #if IS_ANSI ClientMetricsW.cbSize = psrc->cbSize; ClientMetricsW.iBorderWidth = psrc->iBorderWidth; ClientMetricsW.iScrollWidth = psrc->iScrollWidth; ClientMetricsW.iScrollHeight = psrc->iScrollHeight; ClientMetricsW.iCaptionWidth = psrc->iCaptionWidth; ClientMetricsW.iCaptionHeight = psrc->iCaptionHeight; ClientMetricsW.iSmCaptionWidth = psrc->iSmCaptionWidth; ClientMetricsW.iSmCaptionHeight = psrc->iSmCaptionHeight; ClientMetricsW.iMenuWidth = psrc->iMenuWidth; ClientMetricsW.iMenuHeight = psrc->iMenuHeight; CopyLogFontAtoW(&(ClientMetricsW.lfCaptionFont), &(psrc->lfCaptionFont)); CopyLogFontAtoW(&(ClientMetricsW.lfSmCaptionFont), &(psrc->lfSmCaptionFont)); CopyLogFontAtoW(&(ClientMetricsW.lfMenuFont), &(psrc->lfMenuFont)); CopyLogFontAtoW(&(ClientMetricsW.lfStatusFont), &(psrc->lfStatusFont)); CopyLogFontAtoW(&(ClientMetricsW.lfMessageFont), &(psrc->lfMessageFont)); lParam = &ClientMetricsW; #endif wParam = sizeof(NONCLIENTMETRICSW); } break; case SPI_SETMINIMIZEDMETRICS: if ((lParam == NULL) || (*((DWORD *)(lParam)) != sizeof(MINIMIZEDMETRICS))) MSGERROR(); wParam = sizeof(MINIMIZEDMETRICS); break; case SPI_SETICONMETRICS: #if IS_ANSI { PICONMETRICSA psrc = (PICONMETRICSA)lParam; if (lParam == NULL || *((DWORD *)(lParam)) != sizeof(ICONMETRICSA)) { MSGERROR(); } RtlCopyMemory(&IconMetricsW, psrc, sizeof(ICONMETRICSA) - sizeof(LOGFONTA)); CopyLogFontAtoW(&(IconMetricsW.lfFont), &(psrc->lfFont)); lParam = &IconMetricsW; } #else if (lParam == NULL || *((DWORD *)(lParam)) != sizeof(ICONMETRICSW)) { MSGERROR(); } #endif wParam = sizeof(ICONMETRICSW); break; case SPI_SETICONTITLELOGFONT: #if IS_ANSI CopyLogFontAtoW(&LogFontW, lParam); lParam = &LogFontW; #endif wParam = sizeof(LOGFONTW); break; case SPI_GETFILTERKEYS: { if ((((LPFILTERKEYS)lParam)->cbSize == 0) || (((LPFILTERKEYS)lParam)->cbSize) > sizeof(FILTERKEYS)) { MSGERROR(); } } break; case SPI_GETSTICKYKEYS: { if ((((LPSTICKYKEYS)lParam)->cbSize == 0) || (((LPSTICKYKEYS)lParam)->cbSize) > sizeof(STICKYKEYS)) { MSGERROR(); } } break; case SPI_GETTOGGLEKEYS: { if ((((LPTOGGLEKEYS)lParam)->cbSize == 0) || (((LPTOGGLEKEYS)lParam)->cbSize) > sizeof(TOGGLEKEYS)) { MSGERROR(); } } break; case SPI_GETMOUSEKEYS: { if ((((LPMOUSEKEYS)lParam)->cbSize == 0) || (((LPMOUSEKEYS)lParam)->cbSize) > sizeof(MOUSEKEYS)) { MSGERROR(); } } break; case SPI_GETACCESSTIMEOUT: { if ((((LPACCESSTIMEOUT)lParam)->cbSize == 0) || (((LPACCESSTIMEOUT)lParam)->cbSize) > sizeof(ACCESSTIMEOUT)) { MSGERROR(); } } break; case SPI_GETSOUNDSENTRY: if ((((LPSOUNDSENTRY)lParam)->cbSize == 0) || (((LPSOUNDSENTRY)lParam)->cbSize) > sizeof(SOUNDSENTRY)) { MSGERROR(); } break; } retval = NtUserSystemParametersInfo(wFlag, wParam, lParam, flags); switch (wFlag) { #if IS_ANSI case SPI_GETNONCLIENTMETRICS: { PNONCLIENTMETRICSA pdst = (PNONCLIENTMETRICSA)oldlParam; pdst->cbSize = sizeof(NONCLIENTMETRICSA); pdst->iBorderWidth = ClientMetricsW.iBorderWidth; pdst->iScrollWidth = ClientMetricsW.iScrollWidth; pdst->iScrollHeight = ClientMetricsW.iScrollHeight; pdst->iCaptionWidth = ClientMetricsW.iCaptionWidth; pdst->iCaptionHeight = ClientMetricsW.iCaptionHeight; pdst->iSmCaptionWidth = ClientMetricsW.iSmCaptionWidth; pdst->iSmCaptionHeight = ClientMetricsW.iSmCaptionHeight; pdst->iMenuWidth = ClientMetricsW.iMenuWidth; pdst->iMenuHeight = ClientMetricsW.iMenuHeight; CopyLogFontWtoA(&(pdst->lfCaptionFont), &(ClientMetricsW.lfCaptionFont)); CopyLogFontWtoA(&(pdst->lfSmCaptionFont), &(ClientMetricsW.lfSmCaptionFont)); CopyLogFontWtoA(&(pdst->lfMenuFont), &(ClientMetricsW.lfMenuFont)); CopyLogFontWtoA(&(pdst->lfStatusFont), &(ClientMetricsW.lfStatusFont)); CopyLogFontWtoA(&(pdst->lfMessageFont), &(ClientMetricsW.lfMessageFont)); } break; case SPI_GETICONMETRICS: { PICONMETRICSA pdst = (PICONMETRICSA)oldlParam; RtlCopyMemory(pdst, &IconMetricsW, sizeof(ICONMETRICSA) - sizeof(LOGFONTA)); pdst->cbSize = sizeof(ICONMETRICSA); CopyLogFontWtoA(&(pdst->lfFont), &(IconMetricsW.lfFont)); } break; case SPI_GETICONTITLELOGFONT: CopyLogFontWtoA((PLOGFONTA)oldlParam, &LogFontW); break; case SPI_GETHIGHCONTRAST: WCSToMB(pwcHighContrastScheme, -1, &pcHighContrastScheme, MAX_SCHEME_NAME_SIZE, FALSE); ((LPHIGHCONTRASTA)(lParam))->lpszDefaultScheme = pcHighContrastScheme; break; #endif case SPI_GETDESKWALLPAPER: { #if IS_ANSI INT cchAnsiCopy = WCSToMB(lParam, -1, (LPSTR*)&oldlParam, oldwParam - 1, FALSE); cchAnsiCopy = min(cchAnsiCopy, (INT)(oldwParam - 1)); ((LPSTR)oldlParam)[cchAnsiCopy] = 0; #else ((LPWSTR)oldlParam)[wParam] = (WCHAR)0; #endif break; } case SPI_SETLOWPOWERTIMEOUT: case SPI_SETPOWEROFFTIMEOUT: if (retval && (flags & SPIF_UPDATEINIFILE)) { retval = SetVideoTimeout(wParam); } break; } ERRORTRAP(FALSE); CLEANUPLPTSTR(strlParam); ENDCALL(BOOL); } #ifdef UNICODE FUNCLOG2(LOG_GENERAL, HANDLE, APIENTRY, GetPropW, HWND, hwnd, LPCTSTR, pString) #else FUNCLOG2(LOG_GENERAL, HANDLE, APIENTRY, GetPropA, HWND, hwnd, LPCTSTR, pString) #endif // UNICODE HANDLE APIENTRY GetProp(HWND hwnd, LPCTSTR pString) { PWND pwnd; int iString; if (IS_PTR(pString)) { iString = (int)GlobalFindAtom(pString); if (iString == 0) return NULL; } else iString = PTR_TO_ID(pString); pwnd = ValidateHwnd(hwnd); if (pwnd == NULL) return NULL; return _GetProp(pwnd, (LPWSTR)UIntToPtr( iString ), FALSE); } /***************************************************************************\ * RegisterClassW(API) * * History: * 28-Jul-1992 ChandanC Created. \***************************************************************************/ ATOM WINAPI TEXT_FN(RegisterClass)( CONST WNDCLASS *lpWndClass ) { WNDCLASSEX wc; /* * On 64-bit plaforms we'll have 32-bits of padding between style and * lpfnWndProc in WNDCLASS, so start the copy from the first 64-bit * aligned field and hand copy the rest. */ RtlCopyMemory(&(wc.lpfnWndProc), &(lpWndClass->lpfnWndProc), sizeof(WNDCLASS) - FIELD_OFFSET(WNDCLASS, lpfnWndProc)); wc.style = lpWndClass->style; wc.hIconSm = NULL; wc.cbSize = sizeof(WNDCLASSEX); return TEXT_FN(RegisterClassExWOW)(&wc, NULL, 0, CSF_VERSIONCLASS); } /***************************************************************************\ * RegisterClassExW(API) * * History: * 28-Jul-1992 ChandanC Created. \***************************************************************************/ ATOM WINAPI TEXT_FN(RegisterClassEx)( CONST WNDCLASSEX *lpWndClass) { if (lpWndClass->cbSize != sizeof(WNDCLASSEX)) { RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "RegisterClassEx: cbsize is wrong %lX", lpWndClass->cbSize); return 0; } else { return TEXT_FN(RegisterClassExWOW)((LPWNDCLASSEX)lpWndClass, NULL, 0, CSF_VERSIONCLASS); } } /***************************************************************************\ * GetMenuItemInfoInternal * * History: * 07-22-96 GerardoB - Added header and Fixed up for 5.0 \***************************************************************************/ BOOL TEXT_FN(GetMenuItemInfoInternal) (HMENU hMenu, UINT uID, BOOL fByPosition, LPMENUITEMINFOW lpInfo) { PITEM pItem; PMENU pMenu; PMENU pMenuT; pMenu = VALIDATEHMENU(hMenu); if (pMenu == NULL) { VALIDATIONFAIL(hMenu); } pMenuT = pMenu; // need to check the ORIGINAL menu if popup pItem = MNLookUpItem(pMenu, uID, fByPosition, &pMenu); if (pItem == NULL) { /* * Don't display a warning. The explorer makes a lot of calls * that fail here. * VALIDATIONFAIL(uID); */ SetLastError(ERROR_MENU_ITEM_NOT_FOUND); return FALSE; } if (lpInfo->fMask & MIIM_STATE) { lpInfo->fState = pItem->fState & MFS_MASK; } if (lpInfo->fMask & MIIM_ID) { lpInfo->wID = pItem->wID; } if ((lpInfo->fMask & MIIM_SUBMENU) && (pItem->spSubMenu != NULL)) { lpInfo->hSubMenu = PtoH(REBASEPTR(pMenu, pItem->spSubMenu)); } else { lpInfo->hSubMenu = NULL; } if (lpInfo->fMask & MIIM_CHECKMARKS) { lpInfo->hbmpChecked = KHBITMAP_TO_HBITMAP(pItem->hbmpChecked); lpInfo->hbmpUnchecked= KHBITMAP_TO_HBITMAP(pItem->hbmpUnchecked); } if (lpInfo->fMask & MIIM_DATA) { lpInfo->dwItemData = KERNEL_ULONG_PTR_TO_ULONG_PTR(pItem->dwItemData); } if (lpInfo->fMask & MIIM_FTYPE) { lpInfo->fType = pItem->fType & MFT_MASK; if (TestMF(pMenuT,MFRTL)) lpInfo->fType |= MFT_RIGHTORDER; } if ( lpInfo->fMask & MIIM_BITMAP) { lpInfo->hbmpItem = KHBITMAP_TO_HBITMAP(pItem->hbmp); } if (lpInfo->fMask & MIIM_STRING) { if ((lpInfo->cch == 0) || (lpInfo->dwTypeData == NULL) /* * If this is an old caller (MIIM_TYPE set), and this item * has a bitmap or it's ownerdraw, then don't attempt to * copy a string since they probably didn't pass a pointer */ || ((lpInfo->fMask & MIIM_TYPE) && ((lpInfo->fType & MFT_OWNERDRAW) /* * Bug 278750 - jojoe * * Soemone forgot to check for separator in the list * of menuitems that do NOT return string data! */ || (lpInfo->fType & MFT_SEPARATOR) || ((pItem->hbmp != NULL) && ((pItem->hbmp < HBMMENU_POPUPFIRST) || (pItem->hbmp > HBMMENU_POPUPLAST)))))) { /* * When DBCS is enabled, one UNICODE character may occupy two bytes. * GetMenuItemInfoA should return the byte count, rather than the character count. * On NT5, pItem->lpstr is guaranteed to be a valid string, if it is not NULL. */ if (IS_ANSI && IS_DBCS_ENABLED() && pItem->lpstr != NULL) { NTSTATUS Status; ULONG cch; Status = RtlUnicodeToMultiByteSize(&cch, REBASEPTR(pMenu, pItem->lpstr), pItem->cch * sizeof(WCHAR)); UserAssert(NT_SUCCESS(Status)); // RtlUnicodeToMultiByteSize is not expected to fail lpInfo->cch = cch; } else { lpInfo->cch = pItem->cch; } lpInfo->dwTypeData = NULL; } else { int cch = 0; if (pItem->lpstr != NULL) { // originally: // cch = min(lpInfo->cch - 1, (pItem->cch * sizeof(WORD))); cch = pItem->cch; UserAssert(cch >= 0); if (IS_DBCS_ENABLED()) { /* pItem->cch contains Unicode character counts, * we guess max DBCS string size for the Unicode string. */ cch *= DBCS_CHARSIZE; } cch = min(lpInfo->cch - 1, (DWORD)cch); #if IS_ANSI cch = WCSToMB(REBASEPTR(pMenu, pItem->lpstr), pItem->cch, (LPSTR *)&(lpInfo->dwTypeData), cch, FALSE); #else wcsncpy(lpInfo->dwTypeData, (LPWSTR)REBASEPTR(pMenu, pItem->lpstr), cch); #endif } #if IS_ANSI *((LPSTR)lpInfo->dwTypeData + cch) = (CHAR)0; #else *(lpInfo->dwTypeData + cch) = (WCHAR)0; #endif lpInfo->cch = cch; } } return TRUE; VALIDATIONERROR(FALSE); } /***************************************************************************\ * GetMenuString() * * History: * 07-22-96 GerardoB - Added header and Fixed up for 5.0 \***************************************************************************/ #ifdef UNICODE FUNCLOG5(LOG_GENERAL, int, DUMMYCALLINGTYPE, GetMenuStringW, HMENU, hMenu, UINT, wID, LPTSTR, lpsz, int, cchMax, UINT, flags) #else FUNCLOG5(LOG_GENERAL, int, DUMMYCALLINGTYPE, GetMenuStringA, HMENU, hMenu, UINT, wID, LPTSTR, lpsz, int, cchMax, UINT, flags) #endif // UNICODE int GetMenuString(HMENU hMenu, UINT wID, LPTSTR lpsz, int cchMax, UINT flags) { MENUITEMINFOW miiLocal; miiLocal.fMask = MIIM_STRING; miiLocal.dwTypeData = (LPWSTR)lpsz; miiLocal.cch = cchMax; if (cchMax != 0) { *lpsz = (TCHAR)0; } if (TEXT_FN(GetMenuItemInfoInternal)(hMenu, wID, (BOOL)(flags & MF_BYPOSITION), &miiLocal)) { return miiLocal.cch; } else { return 0; } } /***************************************************************************\ * GetMenuItemInfo * * 1) converts a MENUITEMINFO95 or a new-MENUITEMINFO-with-old-flags to a new * MENUITEMINFO -- this way all internal code can assume one look for the * structure * 2) calls the internal GetMenuItemInfo which performs validation and work * 3) converts the new MENUITEMINFO back to the original MENUITEMINFO * * History: * 07-22-96 GerardoB - Fixed up for 5.0 \***************************************************************************/ #ifdef UNICODE FUNCLOG4(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, GetMenuItemInfoW, HMENU, hMenu, UINT, wID, BOOL, fByPos, LPMENUITEMINFO, lpmii) #else FUNCLOG4(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, GetMenuItemInfoA, HMENU, hMenu, UINT, wID, BOOL, fByPos, LPMENUITEMINFO, lpmii) #endif // UNICODE BOOL GetMenuItemInfo(HMENU hMenu, UINT wID, BOOL fByPos, LPMENUITEMINFO lpmii) { UINT cbCallercbSize = lpmii->cbSize; MENUITEMINFOW miiLocal; if (!ValidateMENUITEMINFO((LPMENUITEMINFOW)lpmii, &miiLocal, MENUAPI_GET)) { return FALSE; } if (!TEXT_FN(GetMenuItemInfoInternal)(hMenu, wID, fByPos, &miiLocal)) { return FALSE; } /* * Copy the structure and map old flags back. Only requested fields were * modified, so it's OK to copy all fields back. */ RtlCopyMemory(lpmii, &miiLocal, SIZEOFMENUITEMINFO95); lpmii->cbSize = cbCallercbSize; if (cbCallercbSize > SIZEOFMENUITEMINFO95) { lpmii->hbmpItem = miiLocal.hbmpItem; } if (lpmii->fMask & MIIM_TYPE) { if ((miiLocal.hbmpItem != NULL) && (miiLocal.dwTypeData == NULL)) { lpmii->fType |= MFT_BITMAP; lpmii->dwTypeData = (LPTSTR)miiLocal.hbmpItem; } else if (miiLocal.cch == 0) { lpmii->dwTypeData = NULL; } lpmii->fMask &= ~(MIIM_FTYPE | MIIM_BITMAP | MIIM_STRING); } return TRUE; } /***************************************************************************\ * SetMenuItemInfo * * History: * 07-22-96 GerardoB - Added header and Fixed up for 5.0 \***************************************************************************/ #ifdef UNICODE FUNCLOG4(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetMenuItemInfoW, HMENU, hMenu, UINT, uID, BOOL, fByPosition, LPCMENUITEMINFO, lpmii) #else FUNCLOG4(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetMenuItemInfoA, HMENU, hMenu, UINT, uID, BOOL, fByPosition, LPCMENUITEMINFO, lpmii) #endif // UNICODE BOOL SetMenuItemInfo(HMENU hMenu, UINT uID, BOOL fByPosition, LPCMENUITEMINFO lpmii) { MENUITEMINFOW miiLocal; if (!ValidateMENUITEMINFO((LPMENUITEMINFOW)lpmii, &miiLocal, MENUAPI_SET)) { return FALSE; } return (ThunkedMenuItemInfo(hMenu, uID, fByPosition, FALSE, &miiLocal, IS_ANSI)); } /***************************************************************************\ * InsertMenuItem * * History: * 07-22-96 GerardoB - Added header and Fixed up for 5.0 \***************************************************************************/ BOOL InsertMenuItem (HMENU hMenu, UINT uID, BOOL fByPosition, LPCMENUITEMINFO lpmii) { MENUITEMINFOW miiLocal; if (!ValidateMENUITEMINFO((LPMENUITEMINFOW)lpmii, &miiLocal, MENUAPI_SET)) { return FALSE; } return (ThunkedMenuItemInfo(hMenu, uID, fByPosition, TRUE, &miiLocal, IS_ANSI)); } /***************************************************************************\ * InsertMenu * * History: * 07-22-96 GerardoB - Added header and Fixed up for 5.0 \***************************************************************************/ #ifdef UNICODE FUNCLOG5(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, InsertMenuW, HMENU, hMenu, UINT, uPosition, UINT, uFlags, UINT_PTR, uIDNewItem, LPCTSTR, lpNewItem) #else FUNCLOG5(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, InsertMenuA, HMENU, hMenu, UINT, uPosition, UINT, uFlags, UINT_PTR, uIDNewItem, LPCTSTR, lpNewItem) #endif // UNICODE BOOL InsertMenu(HMENU hMenu, UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, LPCTSTR lpNewItem) { MENUITEMINFOW miiLocal; SetMenuItemInfoStruct(hMenu, uFlags, uIDNewItem, (LPWSTR)lpNewItem, &miiLocal); return ThunkedMenuItemInfo(hMenu, uPosition, (BOOL) (uFlags & MF_BYPOSITION), TRUE, (LPMENUITEMINFOW)&miiLocal, IS_ANSI); } /***************************************************************************\ * AppendMenu * * History: * 07-22-96 GerardoB - Added header and Fixed up for 5.0 \***************************************************************************/ #ifdef UNICODE FUNCLOG4(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, AppendMenuW, HMENU, hMenu, UINT, uFlags, UINT_PTR, uIDNewItem, LPCTSTR, lpNewItem) #else FUNCLOG4(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, AppendMenuA, HMENU, hMenu, UINT, uFlags, UINT_PTR, uIDNewItem, LPCTSTR, lpNewItem) #endif // UNICODE BOOL AppendMenu(HMENU hMenu, UINT uFlags, UINT_PTR uIDNewItem, LPCTSTR lpNewItem) { MENUITEMINFOW miiLocal; SetMenuItemInfoStruct(hMenu, uFlags, uIDNewItem, (LPWSTR)lpNewItem, &miiLocal); return ThunkedMenuItemInfo(hMenu, MFMWFP_NOITEM, MF_BYPOSITION, TRUE, (LPMENUITEMINFOW)&miiLocal, IS_ANSI); } /***************************************************************************\ * ModifyMenu * * History: * 07-22-96 GerardoB - Added header and Fixed up for 5.0 \***************************************************************************/ #ifdef UNICODE FUNCLOG5(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, ModifyMenuW, HMENU, hMenu, UINT, uPosition, UINT, uFlags, UINT_PTR, uIDNewItem, LPCTSTR, lpNewItem) #else FUNCLOG5(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, ModifyMenuA, HMENU, hMenu, UINT, uPosition, UINT, uFlags, UINT_PTR, uIDNewItem, LPCTSTR, lpNewItem) #endif // UNICODE BOOL ModifyMenu(HMENU hMenu, UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, LPCTSTR lpNewItem) { MENUITEMINFOW miiLocal; SetMenuItemInfoStruct(hMenu, uFlags, uIDNewItem, (LPWSTR)lpNewItem, &miiLocal); return ThunkedMenuItemInfo(hMenu, uPosition, (BOOL) (uFlags & MF_BYPOSITION), FALSE, (LPMENUITEMINFOW)&miiLocal, IS_ANSI); } #ifdef UNICODE FUNCLOG6(LOG_GENERAL, LONG, WINUSERAPI, BroadcastSystemMessageExW, DWORD, dwFlags, LPDWORD, lpdwRecipients, UINT, uiMessage, WPARAM, wParam, LPARAM, lParam, PBSMINFO, pBSMInfo) #else FUNCLOG6(LOG_GENERAL, LONG, WINUSERAPI, BroadcastSystemMessageExA, DWORD, dwFlags, LPDWORD, lpdwRecipients, UINT, uiMessage, WPARAM, wParam, LPARAM, lParam, PBSMINFO, pBSMInfo) #endif // UNICODE /***************************************************************************\ * BroadcastSystemMessageEx * * History: * \***************************************************************************/ WINUSERAPI LONG BroadcastSystemMessageEx( DWORD dwFlags, LPDWORD lpdwRecipients, UINT uiMessage, WPARAM wParam, LPARAM lParam, PBSMINFO pBSMInfo) { return BroadcastSystemMessageWorker(dwFlags, lpdwRecipients, uiMessage, wParam, lParam, pBSMInfo, IS_ANSI); } #ifdef UNICODE FUNCLOG5(LOG_GENERAL, LONG, WINUSERAPI, BroadcastSystemMessageW, DWORD, dwFlags, LPDWORD, lpdwRecipients, UINT, uiMessage, WPARAM, wParam, LPARAM, lParam) #else FUNCLOG5(LOG_GENERAL, LONG, WINUSERAPI, BroadcastSystemMessageA, DWORD, dwFlags, LPDWORD, lpdwRecipients, UINT, uiMessage, WPARAM, wParam, LPARAM, lParam) #endif // UNICODE /***************************************************************************\ * BroadcastSystemMessage * * History: * 07-22-96 GerardoB - Added header \***************************************************************************/ WINUSERAPI LONG BroadcastSystemMessage( DWORD dwFlags, LPDWORD lpdwRecipients, UINT uiMessage, WPARAM wParam, LPARAM lParam) { return BroadcastSystemMessageWorker(dwFlags, lpdwRecipients, uiMessage, wParam, lParam, NULL, IS_ANSI); } #ifdef UNICODE FUNCLOG3(LOG_GENERAL, UINT, WINUSERAPI, GetWindowModuleFileNameW, HWND, hwnd, LPTSTR, pszFileName, UINT, cchFileNameMax) #else FUNCLOG3(LOG_GENERAL, UINT, WINUSERAPI, GetWindowModuleFileNameA, HWND, hwnd, LPTSTR, pszFileName, UINT, cchFileNameMax) #endif // UNICODE WINUSERAPI UINT WINAPI GetWindowModuleFileName( HWND hwnd, LPTSTR pszFileName, UINT cchFileNameMax) { PWND pwnd; pwnd = ValidateHwnd(hwnd); if (pwnd == NULL) { return 0; } return GetModuleFileName(KHANDLE_TO_HANDLE(pwnd->hModule), pszFileName, cchFileNameMax); } /***************************************************************************\ * RegisterDeviceNotification * * History: * 01-23-97 PaulaT - Added header \***************************************************************************/ WINUSERAPI HDEVNOTIFY WINAPI RegisterDeviceNotification( IN HANDLE hRecipient, IN LPVOID NotificationFilter, IN DWORD Flags) { extern HDEVNOTIFY RegisterDeviceNotificationWorker(IN HANDLE hRecipient, IN LPVOID NotificationFilter, IN DWORD Flags); // translate strings in NotificationFilter (if any) return RegisterDeviceNotificationWorker(hRecipient, NotificationFilter, Flags); } /***************************************************************************\ * GetMonitorInfo * * History: * 31-Mar-1997 adams Doesn't call into kernel. * 06-Jul-1998 MCostea Has to call into kernel #190510 \***************************************************************************/ #ifdef UNICODE FUNCLOG2(LOG_GENERAL, BOOL, WINUSERAPI, GetMonitorInfoW, HMONITOR, hMonitor, LPMONITORINFO, lpmi) #else FUNCLOG2(LOG_GENERAL, BOOL, WINUSERAPI, GetMonitorInfoA, HMONITOR, hMonitor, LPMONITORINFO, lpmi) #endif // UNICODE BOOL WINUSERAPI GetMonitorInfo(HMONITOR hMonitor, LPMONITORINFO lpmi) { PMONITOR pMonitor; BOOL bRetVal; int cbSize; pMonitor = VALIDATEHMONITOR(hMonitor); if (!pMonitor) { return FALSE; } cbSize = lpmi->cbSize; if (cbSize == sizeof(MONITORINFO)) { /* * Check for this first, since it is the most * common size. All the work for filling in * MONITORINFO fields is done after the else-if * statements. */ } else if (cbSize == sizeof(MONITORINFOEX)) { /* * The ANSI version has to translate the szDevice field */ ULONG_PTR pName; #if IS_ANSI WCHAR szDevice[CCHDEVICENAME]; pName = (ULONG_PTR)szDevice; #else pName = (ULONG_PTR)(((LPMONITORINFOEX)lpmi)->szDevice); #endif bRetVal = (BOOL)NtUserCallTwoParam((ULONG_PTR)(hMonitor), pName, SFI_GETHDEVNAME); if (!bRetVal) { return FALSE; } #if IS_ANSI WideCharToMultiByte( CP_ACP, 0, // ANSI -> Unicode (LPWSTR)pName, -1, // source & length (LPSTR)((LPMONITORINFOEX)lpmi)->szDevice, // destination & length ARRAY_SIZE(((LPMONITORINFOEX)lpmi)->szDevice), NULL, NULL); #endif } else { RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid lpmi->cbSize, %d", lpmi->cbSize); return FALSE; } lpmi->dwFlags = (pMonitor == GetPrimaryMonitor()) ? MONITORINFOF_PRIMARY : 0; lpmi->rcMonitor = pMonitor->rcMonitor; lpmi->rcWork = pMonitor->rcWork; return TRUE; } #ifdef GENERIC_INPUT #ifdef UNICODE FUNCLOG4(LOG_GENERAL, UINT, WINUSERAPI, GetRawInputDeviceInfoW, HANDLE, hDevice, UINT, uiCommand, LPVOID, pData, PUINT, pcbSize) #else FUNCLOG4(LOG_GENERAL, UINT, WINUSERAPI, GetRawInputDeviceInfoA, HANDLE, hDevice, UINT, uiCommand, LPVOID, pData, PUINT, pcbSize) #endif // UNICODE UINT WINUSERAPI GetRawInputDeviceInfo( HANDLE hDevice, UINT uiCommand, LPVOID pData, PUINT pcbSize) { #if IS_ANSI UINT uiRet; LPVOID lpParam = pData; WCHAR wszPath[MAX_PATH]; UINT cbBufferSize = 0; if (uiCommand == RIDI_DEVICENAME) { if (pData) { lpParam = wszPath; cbBufferSize = *pcbSize; } } uiRet = NtUserGetRawInputDeviceInfo(hDevice, uiCommand, lpParam, pcbSize); if (uiCommand == RIDI_DEVICENAME) { if (uiRet == (UINT)-1 && pData != NULL) { /* Insufficient buffer */ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { *pcbSize *= DBCS_CHARSIZE; } } else if (uiRet == 0 && pData == NULL) { /* The app wants the buffer size for the device name */ *pcbSize *= DBCS_CHARSIZE; } else { uiRet = WCSToMB(lpParam, uiRet, (LPSTR*)&pData, cbBufferSize, FALSE); /* TODO: * Handle the case if cbBufferSize was not enough. */ } } return uiRet; #else return NtUserGetRawInputDeviceInfo(hDevice, uiCommand, pData, pcbSize); #endif } #endif