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.
422 lines
16 KiB
422 lines
16 KiB
/****************************************************************************/
|
|
// cm.h
|
|
//
|
|
// Cursor manager header.
|
|
//
|
|
// Copyright (C) 1997-2000 Microsoft Corp.
|
|
/****************************************************************************/
|
|
|
|
#ifndef _H_CM
|
|
#define _H_CM
|
|
|
|
extern "C" {
|
|
#include <adcgdata.h>
|
|
}
|
|
#include "autil.h"
|
|
#include "wui.h"
|
|
#include "uh.h"
|
|
|
|
#include "objs.h"
|
|
#include "cd.h"
|
|
|
|
#define TRC_GROUP TRC_GROUP_CORE
|
|
#define TRC_FILE "cm"
|
|
#define TSC_HR_FILEID TSC_HR_CM_H
|
|
|
|
|
|
/****************************************************************************/
|
|
/* Cursor size constants. These are t.128 specifications. */
|
|
/****************************************************************************/
|
|
#define CM_CURSOR_WIDTH 32
|
|
#define CM_CURSOR_HEIGHT 32
|
|
#define CM_NUM_CURSOR_BITMAP_BYTES ((CM_CURSOR_WIDTH * CM_CURSOR_HEIGHT) / 8)
|
|
|
|
|
|
/****************************************************************************/
|
|
/* Pointer cache sizes. */
|
|
/* */
|
|
/* Note: For 'old' style support, the cache includes one entry (never */
|
|
/* used!) for the last mono cursor */
|
|
/****************************************************************************/
|
|
#define CM_COLOR_CACHE_SIZE 20
|
|
#define CM_MONO_CACHE_SIZE 1
|
|
|
|
#define CM_MONO_CACHE_INDEX CM_COLOR_CACHE_SIZE
|
|
|
|
#define CM_CURSOR_CACHE_SIZE (CM_COLOR_CACHE_SIZE + CM_MONO_CACHE_SIZE)
|
|
|
|
|
|
/**STRUCT+*******************************************************************/
|
|
/* Structure: CM_GLOBAL_DATA */
|
|
/* */
|
|
/* Description: */
|
|
/****************************************************************************/
|
|
typedef struct tagCM_GLOBAL_DATA
|
|
{
|
|
HCURSOR cursorCache[CM_CURSOR_CACHE_SIZE];
|
|
} CM_GLOBAL_DATA, DCPTR PCM_GLOBAL_DATA;
|
|
/**STRUCT-*******************************************************************/
|
|
|
|
|
|
#define CM_DEFAULT_ARROW_CURSOR_HANDLE LoadCursor(NULL, IDC_ARROW)
|
|
|
|
|
|
class CCM
|
|
{
|
|
public:
|
|
|
|
CCM(CObjs* objs);
|
|
~CCM();
|
|
|
|
//
|
|
// API
|
|
//
|
|
|
|
/****************************************************************************/
|
|
// Functions
|
|
/****************************************************************************/
|
|
DCVOID DCAPI CM_Init(DCVOID);
|
|
DCVOID DCAPI CM_Enable(ULONG_PTR unused);
|
|
EXPOSE_CD_SIMPLE_NOTIFICATION_FN(CCM, CM_Enable);
|
|
DCVOID DCAPI CM_Disable(ULONG_PTR unused);
|
|
EXPOSE_CD_SIMPLE_NOTIFICATION_FN(CCM, CM_Disable);
|
|
void DCAPI CM_NullSystemPointerPDU(void);
|
|
void DCAPI CM_DefaultSystemPointerPDU(void);
|
|
HRESULT DCAPI CM_MonoPointerPDU(TS_MONOPOINTERATTRIBUTE UNALIGNED FAR *, DCUINT);
|
|
void DCAPI CM_PositionPDU(TS_POINT16 UNALIGNED FAR *);
|
|
HRESULT DCAPI CM_ColorPointerPDU(TS_COLORPOINTERATTRIBUTE UNALIGNED FAR *, DCUINT);
|
|
void DCAPI CM_CachedPointerPDU(unsigned);
|
|
HRESULT DCAPI CM_PointerPDU(TS_POINTERATTRIBUTE UNALIGNED FAR *, DCUINT);
|
|
|
|
/****************************************************************************/
|
|
/* Name: CM_Term */
|
|
/* */
|
|
/* Purpose: Cursor Manager termination */
|
|
/****************************************************************************/
|
|
inline void DCAPI CM_Term(void)
|
|
{
|
|
} /* CM_Term */
|
|
|
|
|
|
/****************************************************************************/
|
|
// CM_SlowPathPDU
|
|
//
|
|
// Handles non-fast-path translation to handler function calls.
|
|
/****************************************************************************/
|
|
// SECURITY - the size of the packet has been checked only to be sure there is
|
|
// enough data to read the TS_POINTER_PDU_DATA.messageType field
|
|
inline HRESULT DCAPI CM_SlowPathPDU(
|
|
TS_POINTER_PDU_DATA UNALIGNED FAR *pPointerPDU,
|
|
DCUINT dataLen )
|
|
{
|
|
DC_BEGIN_FN("CM_SlowPathPDU");
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
switch (pPointerPDU->messageType) {
|
|
case TS_PTRMSGTYPE_POSITION:
|
|
CHECK_READ_N_BYTES(pPointerPDU, (PBYTE)pPointerPDU + dataLen,
|
|
FIELDOFFSET(TS_POINTER_PDU_DATA,pointerData) +
|
|
sizeof(TS_POINT16), hr, (TB, _T("Bad TS_PTRMSGTYPE_POSITION")));
|
|
CM_PositionPDU(&pPointerPDU->pointerData.pointerPosition);
|
|
break;
|
|
|
|
case TS_PTRMSGTYPE_SYSTEM:
|
|
CHECK_READ_N_BYTES(pPointerPDU, (PBYTE)pPointerPDU + dataLen,
|
|
FIELDOFFSET(TS_POINTER_PDU_DATA,pointerData) +
|
|
sizeof(TSUINT32), hr, (TB, _T("Bad TS_PTRMSGTYPE_SYSTEM")));
|
|
|
|
switch (pPointerPDU->pointerData.systemPointerType) {
|
|
case TS_SYSPTR_NULL:
|
|
CM_NullSystemPointerPDU();
|
|
break;
|
|
|
|
case TS_SYSPTR_DEFAULT:
|
|
CM_DefaultSystemPointerPDU();
|
|
break;
|
|
|
|
default:
|
|
TRC_ERR((TB, _T("Invalid system pointer type")));
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case TS_PTRMSGTYPE_MONO:
|
|
CHECK_READ_N_BYTES(pPointerPDU, (PBYTE)pPointerPDU + dataLen,
|
|
FIELDOFFSET(TS_POINTER_PDU_DATA,pointerData) +
|
|
sizeof(TS_MONOPOINTERATTRIBUTE), hr, (TB, _T("Bad TS_PTRMSGTYPE_MONO")));
|
|
|
|
hr = CM_MonoPointerPDU(&pPointerPDU->pointerData.
|
|
monoPointerAttribute, dataLen - FIELDOFFSET(TS_POINTER_PDU_DATA,pointerData));
|
|
break;
|
|
|
|
case TS_PTRMSGTYPE_COLOR:
|
|
CHECK_READ_N_BYTES(pPointerPDU, (PBYTE)pPointerPDU + dataLen,
|
|
FIELDOFFSET(TS_POINTER_PDU_DATA,pointerData) +
|
|
sizeof(TS_COLORPOINTERATTRIBUTE), hr, (TB, _T("Bad TS_PTRMSGTYPE_COLOR")));
|
|
|
|
hr = CM_ColorPointerPDU(&pPointerPDU->pointerData.
|
|
colorPointerAttribute, dataLen - FIELDOFFSET(TS_POINTER_PDU_DATA,pointerData));
|
|
break;
|
|
|
|
case TS_PTRMSGTYPE_POINTER:
|
|
CHECK_READ_N_BYTES(pPointerPDU, (PBYTE)pPointerPDU + dataLen,
|
|
FIELDOFFSET(TS_POINTER_PDU_DATA,pointerData) +
|
|
sizeof(TS_POINTERATTRIBUTE), hr, (TB, _T("Bad TS_PTRMSGTYPE_POINTER")));
|
|
|
|
hr = CM_PointerPDU(&pPointerPDU->pointerData.pointerAttribute,
|
|
dataLen - FIELDOFFSET(TS_POINTER_PDU_DATA,pointerData));
|
|
break;
|
|
|
|
case TS_PTRMSGTYPE_CACHED:
|
|
CHECK_READ_N_BYTES(pPointerPDU, (PBYTE)pPointerPDU + dataLen,
|
|
FIELDOFFSET(TS_POINTER_PDU_DATA,pointerData) +
|
|
sizeof(TSUINT16), hr, (TB, _T("Bad TS_PTRMSGTYPE_CACHED")));
|
|
|
|
CM_CachedPointerPDU(pPointerPDU->pointerData.cachedPointerIndex);
|
|
break;
|
|
|
|
default:
|
|
TRC_ERR((TB, _T("Unknown PointerPDU type %#x"),
|
|
pPointerPDU->messageType));
|
|
hr = E_UNEXPECTED;
|
|
break;
|
|
}
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
return hr;
|
|
}
|
|
|
|
public:
|
|
//
|
|
// Public data members
|
|
//
|
|
CM_GLOBAL_DATA _CM;
|
|
|
|
private:
|
|
//
|
|
// Internal functions
|
|
//
|
|
|
|
/****************************************************************************/
|
|
/* Functions */
|
|
/****************************************************************************/
|
|
HRESULT DCINTERNAL CMCreateColorCursor(unsigned,
|
|
TS_COLORPOINTERATTRIBUTE UNALIGNED FAR *, DCUINT, HCURSOR *);
|
|
|
|
HRESULT DCINTERNAL CMCreateMonoCursor(
|
|
TS_MONOPOINTERATTRIBUTE UNALIGNED FAR *, DCUINT, HCURSOR *);
|
|
|
|
inline HRESULT DCINTERNAL CMCreateNewCursor(
|
|
TS_POINTERATTRIBUTE UNALIGNED FAR *pAttr,
|
|
DCUINT dataLen,
|
|
HCURSOR FAR *pNewHandle,
|
|
HCURSOR * pOldHandle)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HCURSOR oldHandle = NULL;
|
|
HCURSOR newHandle;
|
|
unsigned cacheIndex;
|
|
unsigned xorLen;
|
|
|
|
DC_BEGIN_FN("CMCreateNewCursor");
|
|
|
|
TRC_DATA_DBG("Rx cursor data", pAttr, sizeof(TS_POINTERATTRIBUTE) );
|
|
|
|
cacheIndex = pAttr->colorPtrAttr.cacheIndex;
|
|
|
|
// SECURITY: 555587 cursor values must be validated
|
|
if (cacheIndex >= CM_CURSOR_CACHE_SIZE) {
|
|
TRC_ERR(( TB, _T("Invalid cache index %d"), cacheIndex));
|
|
hr = E_TSC_CORE_CACHEVALUE;
|
|
DC_QUIT;
|
|
}
|
|
TRC_DBG((TB, _T("Cached index %d"), cacheIndex));
|
|
|
|
oldHandle = _CM.cursorCache[cacheIndex];
|
|
|
|
// SECURITY 555587: CMCreate<XXX>Cursor must validate input
|
|
if (FIELDOFFSET(TS_COLORPOINTERATTRIBUTE, colorPointerData) +
|
|
pAttr->colorPtrAttr.lengthXORMask + pAttr->colorPtrAttr.lengthANDMask > dataLen) {
|
|
TRC_ERR(( TB, _T("Bad CreateNewCursor; dataLen %u"), dataLen));
|
|
hr = E_TSC_CORE_LENGTH;
|
|
DC_QUIT;
|
|
}
|
|
|
|
// Create the new cursor according to the color depth
|
|
if (pAttr->XORBpp == 1) {
|
|
TRC_NRM((TB, _T("Create mono cursor")));
|
|
|
|
// Data contains XOR followed by AND mask.
|
|
xorLen = pAttr->colorPtrAttr.lengthXORMask;
|
|
TRC_DATA_DBG("AND mask",
|
|
pAttr->colorPtrAttr.colorPointerData + xorLen,
|
|
xorLen);
|
|
TRC_DATA_DBG("XOR bitmap",
|
|
pAttr->colorPtrAttr.colorPointerData,
|
|
xorLen);
|
|
#ifndef OS_WINCE
|
|
newHandle = CreateCursor(_pUi->UI_GetInstanceHandle(),
|
|
pAttr->colorPtrAttr.hotSpot.x,
|
|
pAttr->colorPtrAttr.hotSpot.y,
|
|
pAttr->colorPtrAttr.width,
|
|
pAttr->colorPtrAttr.height,
|
|
pAttr->colorPtrAttr.colorPointerData + xorLen,
|
|
pAttr->colorPtrAttr.colorPointerData);
|
|
#else
|
|
/******************************************************************/
|
|
/* In Windows CE environments, we're not guaranteed that */
|
|
/* CreateCursor is part of the OS, so we do a GetProcAddress on */
|
|
/* it so we can be sure. If it's not there, this usually means */
|
|
/* we're on a touch screen device where these cursor doesn't */
|
|
/* matter anyway. */
|
|
/******************************************************************/
|
|
if (g_pCreateCursor)
|
|
{
|
|
newHandle = g_pCreateCursor(_pUi->UI_GetInstanceHandle(),
|
|
pAttr->colorPtrAttr.hotSpot.x,
|
|
pAttr->colorPtrAttr.hotSpot.y,
|
|
pAttr->colorPtrAttr.width,
|
|
pAttr->colorPtrAttr.height,
|
|
pAttr->colorPtrAttr.colorPointerData + xorLen,
|
|
pAttr->colorPtrAttr.colorPointerData);
|
|
|
|
}
|
|
else
|
|
{
|
|
newHandle = NULL;
|
|
}
|
|
#endif // OS_WINCE
|
|
}
|
|
else {
|
|
TRC_NRM((TB, _T("Create %d bpp cursor"), pAttr->XORBpp));
|
|
hr = CMCreateColorCursor(pAttr->XORBpp, &(pAttr->colorPtrAttr),
|
|
dataLen - FIELDSIZE(TS_POINTERATTRIBUTE, XORBpp), &newHandle);
|
|
DC_QUIT_ON_FAIL(hr);
|
|
}
|
|
|
|
_CM.cursorCache[cacheIndex] = newHandle;
|
|
if (newHandle != NULL) {
|
|
// New cursor created OK.
|
|
*pNewHandle = newHandle;
|
|
}
|
|
else {
|
|
// Failed to create the new color cursor - use default
|
|
TRC_ALT((TB, _T("Failed to create cursor")));
|
|
*pNewHandle = CM_DEFAULT_ARROW_CURSOR_HANDLE;
|
|
}
|
|
|
|
*pOldHandle = oldHandle;
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
return hr;
|
|
}
|
|
|
|
inline HRESULT DCINTERNAL CMCreateNewColorCursor(
|
|
unsigned cacheIndex,
|
|
TS_COLORPOINTERATTRIBUTE UNALIGNED FAR *pAttr,
|
|
DCUINT dataLen,
|
|
HCURSOR FAR *pNewHandle,
|
|
HCURSOR * pOldHandle)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HCURSOR oldHandle = NULL;
|
|
HCURSOR newHandle;
|
|
|
|
DC_BEGIN_FN("CMCreateNewColorCursor");
|
|
|
|
// SECURITY: 555587 cursor values must be validated
|
|
if (cacheIndex >= CM_CURSOR_CACHE_SIZE) {
|
|
TRC_ERR(( TB, _T("Invalid cache index %d"), cacheIndex));
|
|
hr = E_TSC_CORE_CACHEVALUE;
|
|
DC_QUIT;
|
|
}
|
|
|
|
TRC_DBG((TB, _T("Cached index %d"), cacheIndex));
|
|
|
|
oldHandle = _CM.cursorCache[cacheIndex];
|
|
|
|
// Create the new color cursor. Save in the cache.
|
|
// This is for the 'old' cursor protocol so we hard coded the color
|
|
// depth as 24 bpp.
|
|
|
|
// SECURITY 559307: CMCreate<XXX>Cursor need size of PDU passed in
|
|
hr = CMCreateColorCursor(24, pAttr, dataLen, &newHandle);
|
|
DC_QUIT_ON_FAIL(hr);
|
|
|
|
_CM.cursorCache[cacheIndex] = newHandle;
|
|
if (newHandle != NULL) {
|
|
// New cursor created OK.
|
|
*pNewHandle = newHandle;
|
|
}
|
|
else {
|
|
// Failed to create the new color cursor - use default
|
|
TRC_ALT((TB, _T("Failed to create color cursor")));
|
|
*pNewHandle = CM_DEFAULT_ARROW_CURSOR_HANDLE;
|
|
}
|
|
|
|
*pOldHandle = oldHandle;
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
return hr;
|
|
}
|
|
|
|
inline HCURSOR DCINTERNAL CMGetCachedCursor(unsigned cacheIndex)
|
|
{
|
|
DC_BEGIN_FN("CMGetCachedCursor");
|
|
|
|
TRC_NRM((TB, _T("Cached color pointer - index %d"), cacheIndex));
|
|
|
|
TRC_ASSERT((cacheIndex < CM_CURSOR_CACHE_SIZE),
|
|
(TB, _T("Invalid cache index %d"), cacheIndex));
|
|
|
|
/************************************************************************/
|
|
/* Assume NULL means we failed to create the cursor, so use the */
|
|
/* default. If the server has not sent this definition, that is not our */
|
|
/* fault. */
|
|
/************************************************************************/
|
|
|
|
// SECURITY 550811: Cache index must be verified
|
|
if (cacheIndex < CM_CURSOR_CACHE_SIZE &&
|
|
_CM.cursorCache[cacheIndex] != NULL) {
|
|
DC_END_FN();
|
|
return _CM.cursorCache[cacheIndex];
|
|
}
|
|
else {
|
|
TRC_ALT((TB, _T("No cached cursor - use default")));
|
|
DC_END_FN();
|
|
return CM_DEFAULT_ARROW_CURSOR_HANDLE;
|
|
}
|
|
}
|
|
|
|
|
|
// Platform specific prototypes.
|
|
HBITMAP CMCreateXORBitmap(LPBITMAPINFO,
|
|
TS_COLORPOINTERATTRIBUTE UNALIGNED FAR *);
|
|
HCURSOR CMCreatePlatformCursor(TS_COLORPOINTERATTRIBUTE UNALIGNED FAR *,
|
|
HBITMAP, HBITMAP);
|
|
#ifdef OS_WINCE
|
|
DCVOID DCINTERNAL CMMakeMonoDIB(HDC, LPBITMAPINFO, PDCUINT8, PDCUINT8);
|
|
#endif // OS_WINCE
|
|
|
|
|
|
private:
|
|
CUT* _pUt;
|
|
CUH* _pUh;
|
|
CCD* _pCd;
|
|
CIH* _pIh;
|
|
CUI* _pUi;
|
|
|
|
private:
|
|
CObjs* _pClientObjects;
|
|
|
|
};
|
|
|
|
#undef TRC_FILE
|
|
#undef TRC_GROUP
|
|
#undef TSC_HR_FILEID
|
|
|
|
#endif // _H_CM
|