You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2182 lines
69 KiB
2182 lines
69 KiB
/**************************************************************************\
|
|
* 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
|