Leaked source code of windows server 2003
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

/**************************************************************************\
* 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