windows-nt/Source/XPSP1/NT/drivers/wdm/input/tabletpc/tabsrv/tsrpc.cpp
2020-09-26 16:20:57 +08:00

671 lines
18 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation. All rights reserved.
Module Name:
tsrpc.cpp
Abstract:
This module contains the TabSrv RPC services.
Author:
Michael Tsang (MikeTs) 05-Jun-2000
Environment:
User mode
Revision History:
--*/
#include "pch.h"
/*++
@doc INTERNAL
@func unsigned | RPCServerThread | RPC Server thread.
@parm IN PVOID | param | Not used.
@rvalue Always returns 0.
--*/
unsigned __stdcall
RPCServerThread(
IN PVOID param
)
{
TRACEPROC("RPCServerThread", 2)
RPC_STATUS status;
RPC_BINDING_VECTOR *BindingVector = NULL;
TRACEENTER(("(param=%p)\n", param));
if ((status = RpcServerUseProtseq((unsigned char *)"ncalrpc",
RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
NULL)) != RPC_S_OK)
{
TABSRVERR(("RpcServerUseProtSeqEp failed (status=%d)\n", status));
}
else if ((status = RpcServerRegisterIf(TabSrv_v1_0_s_ifspec,
NULL,
NULL)) != RPC_S_OK)
{
TABSRVERR(("RpcServerRegisterIf failed (status=%d)\n", status));
}
else if ((status = RpcServerInqBindings(&BindingVector)) != RPC_S_OK)
{
TABSRVERR(("RpcServerInqBindings failed (status=%d)\n", status));
}
else if ((status = RpcEpRegister(TabSrv_v1_0_s_ifspec,
BindingVector,
NULL,
NULL)) != RPC_S_OK)
{
RpcBindingVectorFree(&BindingVector);
TABSRVERR(("RpcEpRegister failed (status=%d)\n", status));
}
else if ((status = RpcServerRegisterAuthInfo(NULL,
RPC_C_AUTHN_WINNT,
NULL,
NULL)) != RPC_S_OK)
{
RpcEpUnregister(TabSrv_v1_0_s_ifspec, BindingVector, NULL);
RpcBindingVectorFree(&BindingVector);
TABSRVERR(("RpcServerRegisterAuthInfo failed (status=%d)\n", status));
}
else
{
status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, FALSE);
TRACEASSERT(status == RPC_S_OK);
RpcEpUnregister(TabSrv_v1_0_s_ifspec, BindingVector, NULL);
RpcBindingVectorFree(&BindingVector);
}
TRACEINFO(1, ("RPC thread exiting...\n"));
TRACEEXIT(("=0\n"));
return 0;
} //RPCServerThread
/*++
@doc EXTERNAL
@func HEVTNOTIFY | TabSrvRegisterEventNotify |
Register event notification.
@parm IN handle_t | hBinding | RPC binding handle.
@parm IN EVTNOTIFY | Notify event.
@parm IN HWIN | hwnd | Handle to window to be notified.
@parm IN UINT | uiMsg | Notification message used.
@rvalue SUCCESS | Returns notification handle.
@rvalue FAILURE | Returns NULL.
--*/
HEVTNOTIFY
TabSrvRegisterEventNotify(
IN handle_t hBinding,
IN EVTNOTIFY Event,
IN HWIN hwnd,
IN UINT uiMsg
)
{
TRACEPROC("TabSrvRegisterEventNotify", 2)
PNOTIFYCLIENT Client;
TRACEENTER(("(hBinding=%x,Event=%x,hwnd=%x,Msg=%d)\n",
hBinding, Event, hwnd, uiMsg));
Client = (PNOTIFYCLIENT)malloc(sizeof(NOTIFYCLIENT));
if (Client != NULL)
{
DWORD rcWait;
Client->dwSig = SIG_NOTIFYCLIENT;
Client->Event = Event;
Client->hwnd = (HWND)hwnd;
Client->uiMsg = uiMsg;
rcWait = WaitForSingleObject(ghmutNotifyList, INFINITE);
if (rcWait == WAIT_OBJECT_0)
{
InsertTailList(&glistNotifyClients, &Client->list);
ReleaseMutex(ghmutNotifyList);
}
else
{
TABSRVERR(("failed to wait for client list Mutex (rcWait=%x,err=%d).\n",
rcWait, GetLastError()));
}
}
else
{
TABSRVERR(("Failed to allocate notification client.\n"));
}
TRACEEXIT(("=%p\n", Client));
return (HEVTNOTIFY)Client;
} //TabSrvRegisterEventNotify
/*++
@doc EXTERNAL
@func VOID | TabSrvDeregisterEventNotify | Deregister event notification.
@parm IN handle_t | hBinding | RPC binding handle.
@parm IN HEVTNOTIFY | Notification handle.
@rvalue SUCCESS | Returns TRUE.
@rvalue FAILURE | Returns FALSE.
--*/
BOOL
TabSrvDeregisterEventNotify(
IN handle_t hBinding,
IN HEVTNOTIFY hEventNotify
)
{
TRACEPROC("TabSrvRegisterEventNotify", 2)
BOOL rc;
PNOTIFYCLIENT Client = (PNOTIFYCLIENT)hEventNotify;
DWORD rcWait;
TRACEENTER(("(hBinding=%x,NotifyClient=%p)\n", Client));
__try
{
rc = (Client->dwSig == SIG_NOTIFYCLIENT);
}
__except(1)
{
TABSRVERR(("Invalid Notify Client handle.\n"));
rc = FALSE;
}
if (rc == TRUE)
{
rcWait = WaitForSingleObject(ghmutNotifyList, INFINITE);
if (rcWait == WAIT_OBJECT_0)
{
RemoveEntryList(&Client->list);
ReleaseMutex(ghmutNotifyList);
free(Client);
}
else
{
TABSRVERR(("failed to wait for notify list Mutex (rcWait=%x,err=%d).\n",
rcWait, GetLastError()));
rc = FALSE;
}
}
TRACEEXIT(("=%x\n", rc));
return rc;
} //TabSrvDeregisterEventNotify
/*++
@doc EXTERNAL
@func VOID | TabSrvGetLastRawDigiReport | Get the last raw digitizer
report.
@parm IN handle_t | hBinding | RPC binding handle.
@parm OUT PWORD | pwButtonState | To hold the button state data.
@parm OUT PWORD | pwX | To hold the X data.
@parm OUT PWORD | pwY | To hold the Y data.
@rvalue None.
--*/
VOID
TabSrvGetLastRawDigiReport(
IN handle_t hBinding,
OUT PWORD pwButtonState,
OUT PWORD pwX,
OUT PWORD pwY
)
{
TRACEPROC("TabSrvGetLastRawDigiReport", 2)
TRACEENTER(("(hBinding=%x,pwButtonState=%p,pwX=%p,pwY=%p)\n",
hBinding, pwButtonState, pwX, pwY));
*pwButtonState = gLastRawDigiReport.wButtonState;
*pwX = gLastRawDigiReport.wX;
*pwY = gLastRawDigiReport.wY;
TRACEEXIT(("!\n"));
return;
} //TabSrvGetLastRawDigiReport
/*++
@doc EXTERNAL
@func VOID | TabSrvSetPenTilt | Set pen tilt compensation.
@parm IN handle_t | hBinding | RPC binding handle.
@parm IN LONG | dx | x compensation.
@parm IN LONG | dy | y compensation.
@rvalue None.
--*/
VOID
TabSrvSetPenTilt(
IN handle_t hBinding,
IN LONG dx,
IN LONG dy
)
{
TRACEPROC("TabSrvSetPenTilt", 2)
LPTSTR lptstrPenTilt;
TRACEENTER(("(hBinding=%x,dx=%d,dy=%d)\n", hBinding, dx, dy));
lptstrPenTilt = (gdwfTabSrv & TSF_PORTRAIT_MODE)? TEXT("PenTilt_Portrait"):
TEXT("PenTilt_Landscape");
gConfig.PenTilt.dx = dx;
gConfig.PenTilt.dy = dy;
WriteConfig(lptstrPenTilt,
REG_BINARY,
(LPBYTE)&gConfig.PenTilt,
sizeof(gConfig.PenTilt));
TRACEEXIT(("!\n"));
return;
} //TabSrvSetPenTilt
/*++
@doc EXTERNAL
@func BOOL | TabSrvGetLinearityMap | Get linearity map.
@parm IN handle_t | hBinding | RPC binding handle.
@parm OUT PLINEARITY_MAP | LinearityMap | Points to the linearity map.
@rvalue SUCCESS | Returns TRUE.
@rvalue FAILURE | Returns FALSE.
--*/
BOOL
TabSrvGetLinearityMap(
IN handle_t hBinding,
OUT PLINEAR_MAP LinearityMap
)
{
TRACEPROC("TabSrvGetLinearityMap", 2)
BOOL rc;
TRACEENTER(("(hBinding=%x,pLinearityMap=%p)\n", hBinding, LinearityMap));
if (gdwfTabSrv & TSF_HAS_LINEAR_MAP)
{
*LinearityMap = gConfig.LinearityMap;
rc = TRUE;
}
else
{
rc = FALSE;
}
TRACEEXIT(("=%x\n", rc));
return rc;
} //TabSrvGetLinearityMap
/*++
@doc EXTERNAL
@func VOID | TabSrvSetLinearityMap | Set linearity map.
@parm IN handle_t | hBinding | RPC binding handle.
@parm IN PLINEARITY_MAP | LinearityMap | Points to the linearity map.
@rvalue None.
--*/
VOID
TabSrvSetLinearityMap(
IN handle_t hBinding,
IN PLINEAR_MAP LinearityMap
)
{
TRACEPROC("TabSrvSetLinearityMap", 2)
TRACEENTER(("(hBinding=%x,pLinearityMap=%p)\n", hBinding, LinearityMap));
gConfig.LinearityMap = *LinearityMap;
WriteConfig(gtszLinearityMap,
REG_BINARY,
(LPBYTE)&gConfig.LinearityMap,
sizeof(gConfig.LinearityMap));
gdwfTabSrv |= TSF_HAS_LINEAR_MAP;
TRACEEXIT(("!\n"));
return;
} //TabSrvSetLinearityMap
/*++
@doc EXTERNAL
@func BOOL | TabSrvGetPenFeatures | Get digitizer feature report.
@parm IN handle_t | hBinding | RPC binding handle.
@parm IN WORD | wReportID | Report ID of the feature report.
@parm IN WORD | wUsagePage | Usage page of the digitizer.
@parm IN WORD | wUsage | Usage of the digitizer page.
@parm OUT DWORD * | pdwFeature | To hold the feature value.
@rvalue SUCCESS | Returns TRUE.
@rvalue FAILURE | Returns FALSE.
--*/
BOOL
TabSrvGetPenFeatures(
IN handle_t hBinding,
IN WORD wReportID,
IN WORD wUsagePage,
IN WORD wUsage,
OUT DWORD *pdwFeature
)
{
TRACEPROC("TabSrvGetPenFeatures", 2)
BOOL rc = FALSE;
PCHAR buff;
TRACEENTER(("(hBinding=%x,ReportID=%d,UsagePage=%d,Usage=%d,pdwFeature=%p)\n",
hBinding, wReportID, wUsagePage, wUsage, pdwFeature));
if (gdevDigitizer.hDevice != INVALID_HANDLE_VALUE)
{
buff = (PCHAR)calloc(gdevDigitizer.hidCaps.FeatureReportByteLength,
sizeof(CHAR));
TRACEASSERT(buff != NULL);
*buff = (CHAR)wReportID;
rc = HidD_GetFeature(gdevDigitizer.hDevice,
buff,
gdevDigitizer.hidCaps.FeatureReportByteLength);
if (rc == TRUE)
{
NTSTATUS status;
status = HidP_GetUsageValue(
HidP_Feature,
wUsagePage,
0,
wUsage,
pdwFeature,
gdevDigitizer.pPreParsedData,
buff,
gdevDigitizer.hidCaps.FeatureReportByteLength);
if (status != HIDP_STATUS_SUCCESS)
{
rc = FALSE;
TABSRVERR(("Failed to get feature value (status=%x).\n",
status));
}
}
else
{
TABSRVERR(("Failed to get device feature.\n"));
}
if (buff != NULL)
{
free(buff);
}
}
TRACEEXIT(("=%x (Feature=%x)\n", *pdwFeature));
return rc;
} //TabSrvGetPenFeatures
/*++
@doc EXTERNAL
@func BOOL | TabSrvSetPenFeatures | Set digitizer feature report.
@parm IN handle_t | hBinding | RPC binding handle.
@parm IN WORD | wReportID | Report ID of the feature report.
@parm IN WORD | wUsagePage | Usage page of the digitizer.
@parm IN WORD | wUsage | Usage of the digitizer page.
@parm IN DWORD | dwFeature | Feature value.
@rvalue SUCCESS | Returns TRUE.
@rvalue FAILURE | Returns FALSE.
--*/
BOOL
TabSrvSetPenFeatures(
IN handle_t hBinding,
IN WORD wReportID,
IN WORD wUsagePage,
IN WORD wUsage,
IN DWORD dwFeature
)
{
TRACEPROC("TabSrvSetPenFeatures", 2)
BOOL rc = FALSE;
PCHAR buff;
NTSTATUS status;
TRACEENTER(("(hBinding=%x,ReportID=%d,UsagePage=%d,Usage=%d,Feature=%x)\n",
hBinding, wReportID, wUsagePage, wUsage, dwFeature));
if (gdevDigitizer.hDevice != INVALID_HANDLE_VALUE)
{
buff = (PCHAR)calloc(gdevDigitizer.hidCaps.FeatureReportByteLength,
sizeof(CHAR));
TRACEASSERT(buff != NULL);
*buff = (CHAR)wReportID;
status = HidP_SetUsageValue(
HidP_Feature,
wUsagePage,
0,
wUsage,
dwFeature,
gdevDigitizer.pPreParsedData,
buff,
gdevDigitizer.hidCaps.FeatureReportByteLength);
if (status == HIDP_STATUS_SUCCESS)
{
rc = HidD_SetFeature(gdevDigitizer.hDevice,
buff,
gdevDigitizer.hidCaps.FeatureReportByteLength);
if (rc == FALSE)
{
TABSRVERR(("Failed to set device feature.\n"));
}
}
else
{
TABSRVERR(("Failed to set feature value (status=%x).\n", status));
}
if (buff != NULL)
{
free(buff);
}
}
TRACEEXIT(("=%x\n", rc));
return rc;
} //TabSrvSetPenFeatures
/*++
@doc EXTERNAL
@func BOOL | TabSrvGetGestureSettings | Get gesture settings.
@parm IN handle_t | hBinding | RPC binding handle.
@parm OUT PGESTURE_SETTINGS | GestureSettings | To hold the gesture
settings.
@rvalue SUCCESS | Returns TRUE.
@rvalue FAILURE | Returns FALSE.
--*/
BOOL
TabSrvGetGestureSettings(
IN handle_t hBinding,
OUT PGESTURE_SETTINGS GestureSettings
)
{
TRACEPROC("TabSrvGetGestureSettings", 2)
TRACEENTER(("(hBinding=%x,pSettings=%p)\n", hBinding, GestureSettings));
*GestureSettings = gConfig.GestureSettings;
TRACEEXIT(("=1 (Features=%x,Radius=%d,StopDist=%d,StopTime=%d)\n",
GestureSettings->dwfFeatures, GestureSettings->iRadius,
GestureSettings->iStopDist, GestureSettings->iStopTime));
return TRUE;
} //TabSrvGetGestureSettings
/*++
@doc EXTERNAL
@func BOOL | TabSrvSetGestureSettings | Set gesture settings.
@parm IN handle_t | hBinding | RPC binding handle.
@parm IN PGESTURE_SETTINGS | GestureSettings | Point to the gesture
settings to set.
@rvalue SUCCESS | Returns TRUE.
@rvalue FAILURE | Returns FALSE.
--*/
BOOL
TabSrvSetGestureSettings(
IN handle_t hBinding,
IN PGESTURE_SETTINGS GestureSettings
)
{
TRACEPROC("TabSrvSetGestureSettings", 2)
BOOL rc = FALSE;
PTSTHREAD MouseThread;
TRACEENTER(("(hBinding=%x,pSettings=%p,Features=%x,Radius=%d,StopDist=%d,StopTime=%d)\n",
hBinding, GestureSettings, GestureSettings->dwfFeatures,
GestureSettings->iRadius, GestureSettings->iStopDist,
GestureSettings->iStopTime));
gConfig.GestureSettings = *GestureSettings;
WriteConfig(gtszGestureSettings,
REG_BINARY,
(LPBYTE)&gConfig.GestureSettings,
sizeof(gConfig.GestureSettings));
MouseThread = FindThread(TSF_MOUSETHREAD);
if (MouseThread != NULL)
{
if (gConfig.GestureSettings.dwfFeatures & GESTURE_FEATURE_MOUSE_ENABLED)
{
MouseThread->dwfThread |= THREADF_ENABLED;
}
else
{
MouseThread->dwfThread &= ~THREADF_ENABLED;
}
if ((MouseThread->dwfThread & THREADF_ENABLED) &&
(MouseThread->hThread == NULL))
{
//
// Mouse thread is enabled but not running, so start it.
//
if (!InitThreads(MouseThread, 1))
{
TABSRVERR(("failed to start mouse thread.\n"));
}
}
else if (!(MouseThread->dwfThread & THREADF_ENABLED) &&
(MouseThread->hThread != NULL))
{
//
// Mouse thread is disabled but it is currently running, so kill it.
//
if (ghwndMouse != NULL)
{
DWORD rcWait;
gdwfTabSrv |= TSF_TERMINATE;
PostMessage(ghwndMouse, WM_CLOSE, 0, 0);
rcWait = WaitForSingleObject(MouseThread->hThread, 1000);
if (rcWait != WAIT_OBJECT_0)
{
TABSRVERR(("failed to kill mouse thread (rcWait=%x,err=%d)\n",
rcWait, GetLastError()));
}
gdwfTabSrv &= ~TSF_TERMINATE;
}
}
}
TRACEEXIT(("=1\n"));
return TRUE;
} //TabSrvSetGestureSettings
/*++
@doc EXTERNAL
@func BOOL | TabSrvGetButtonSettings | Get button settings.
@parm IN handle_t | hBinding | RPC binding handle.
@parm OUT PBUTTON_SETTINGS | ButtonSettings | To hold the button
settings.
@rvalue SUCCESS | Returns TRUE.
@rvalue FAILURE | Returns FALSE.
--*/
BOOL
TabSrvGetButtonSettings(
IN handle_t hBinding,
OUT PBUTTON_SETTINGS ButtonSettings
)
{
TRACEPROC("TabSrvGetButtonSettings", 2)
TRACEENTER(("(hBinding=%x,pSettings=%p)\n", hBinding, ButtonSettings));
*ButtonSettings = gConfig.ButtonSettings;
TRACEEXIT(("=1\n"));
return TRUE;
} //TabSrvGetButtonSettings
/*++
@doc EXTERNAL
@func BOOL | TabSrvSetButtonSettings | Set button settings.
@parm IN handle_t | hBinding | RPC binding handle.
@parm IN PBUTTON_SETTINGS | ButtonSettings | Point to the button
settings to set.
@rvalue SUCCESS | Returns TRUE.
@rvalue FAILURE | Returns FALSE.
--*/
BOOL
TabSrvSetButtonSettings(
IN handle_t hBinding,
IN PBUTTON_SETTINGS ButtonSettings
)
{
TRACEPROC("TabSrvSetButtonSettings", 2)
BOOL rc = FALSE;
PTSTHREAD MouseThread;
TRACEENTER(("(hBinding=%x,pSettings=%p)\n", hBinding, ButtonSettings));
gConfig.ButtonSettings = *ButtonSettings;
WriteConfig(gtszButtonSettings,
REG_BINARY,
(LPBYTE)&gConfig.ButtonSettings,
sizeof(gConfig.ButtonSettings));
TRACEEXIT(("=1\n"));
return TRUE;
} //TabSrvSetGestureSettings