gpecer.cpp
来自「老外的一个开源项目」· C++ 代码 · 共 1,328 行 · 第 1/3 页
CPP
1,328 行
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name:
Abstract:
Functions:
Notes:
--*/
#include "precomp.h"
#include "winsock.h"
#include "cerdisp.h"
#include "halether.h"
#include "syspal.h" // for 8Bpp we use the natural palette
#include "gpecer.h"
INSTANTIATE_GPE_ZONES(0x3,"MGDI Driver","unused1","unused2") // Start with errors and warnings
BOOL v_fPalChanged;
BOOL v_CursorDrawnByCE;
#ifdef DD_ENABLE
DDGPE *gGPE = (DDGPE *)NULL;
#else // DD_ENABLE
static GPE *gGPE = (GPE *)NULL;
#endif // DD_ENABLE
// This prototype avoids problems exporting from .lib
BOOL APIENTRY GPEEnableDriver(ULONG engineVersion, ULONG cj, DRVENABLEDATA *data,
PENGCALLBACKS engineCallbacks);
BOOL APIENTRY DrvEnableDriver(ULONG engineVersion, ULONG cj, DRVENABLEDATA *data,
PENGCALLBACKS engineCallbacks)
{
return GPEEnableDriver(engineVersion, cj, data, engineCallbacks);
}
//
// Main entry point for a GPE-compliant driver
//
GPE *GetGPE(void)
{
if (!gGPE)
{
if (!CeSetThreadPriority(GetCurrentThread(), 200))
{
DEBUGMSG (1, (TEXT("GPECERem::DoInput warning, failed to set CEThreadPriority!\r\n")));
}
RETAILMSG (1, (TEXT("Entry thread priority=%d\r\n"), CeGetThreadPriority(GetCurrentThread())));
gGPE = new GPECERem();
}
return gGPE;
}
void GPECERem::InitCerDispInfo(PCERDISPINFO pInfo)
{
OSVERSIONINFO OSVersionInfo;
TCHAR szParamInfo[256];
DWORD dwGetBootMeName = SPI_GETBOOTMENAME;
memset (pInfo, 0, sizeof(*pInfo));
pInfo->dwSize = sizeof(*pInfo);
pInfo->dwMagic = MAGIC_VERSION;
pInfo->cXScreen = m_nScreenWidth;
pInfo->cYScreen = m_nScreenHeight;
pInfo->cScreenDepth = m_colorDepth;
OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVersionInfo);
GetVersionEx (&OSVersionInfo);
pInfo->dwMajorVersion = OSVersionInfo.dwMajorVersion;
pInfo->dwMinorVersion = OSVersionInfo.dwMinorVersion;
SystemParametersInfo (SPI_GETPLATFORMNAME, sizeof(szParamInfo)/sizeof(TCHAR), szParamInfo, 0);
WideCharToMultiByte (CP_ACP, 0, szParamInfo, -1, pInfo->szPlatformType, sizeof(pInfo->szPlatformType), NULL, NULL);
SystemParametersInfo (SPI_GETOEMINFO, sizeof(szParamInfo)/sizeof(TCHAR), szParamInfo, 0);
WideCharToMultiByte (CP_ACP, 0, szParamInfo, -1, pInfo->szOEMInfo, sizeof(pInfo->szOEMInfo), NULL, NULL);
KernelIoControl (IOCTL_HAL_GET_DEVICE_INFO, &dwGetBootMeName, sizeof(dwGetBootMeName), szParamInfo, sizeof(szParamInfo)/sizeof(TCHAR), NULL);
WideCharToMultiByte (CP_ACP, 0, szParamInfo, -1, pInfo->szDeviceName, sizeof(pInfo->szDeviceName), NULL, NULL);
}
int
TCPSend (SOCKET Sock, char *data, int len)
{
int offset = 0;
int cSent;
while (offset < len) {
cSent = send (Sock, data+offset, len-offset, 0);
if (SOCKET_ERROR == cSent) {
return SOCKET_ERROR;
}
offset += cSent;
}
return offset;
}
int
TCPRecv (SOCKET Sock, char *data, int Len)
{
int offset = 0;
int RecvLen;
while (offset < Len) {
RecvLen = recv(Sock, data+offset, Len-offset, 0);
if (RecvLen == SOCKET_ERROR) {
return SOCKET_ERROR;
}
offset += RecvLen;
}
return offset;
}
void
CloseSocket (DWORD* Sock)
{
SOCKET tmp = InterlockedExchange((LPLONG)Sock, INVALID_SOCKET);
if (tmp != INVALID_SOCKET) {
closesocket (tmp);
}
}
DWORD GPECERem::DoInput (LPVOID lParam)
{
GPECERem *pThis = (GPECERem *)lParam;
USHORT Cmd;
USHORT MouseData[2];
DWORD dwFlags;
SOCKET Sock = (SOCKET)pThis->m_Sock;
DEBUGMSG (1, (TEXT("DoInput thread entering\r\n")));
if (!CeSetThreadPriority(GetCurrentThread(), 200))
{
DEBUGMSG (1, (TEXT("GPECERem::DoInput warning, failed to set CEThreadPriority!\r\n")));
return -1;
}
RETAILMSG (1, (TEXT("GPECERem::DoInput thread priority=%d\r\n"), CeGetThreadPriority(GetCurrentThread())));
while (INVALID_SOCKET != Sock) {
if (TCPRecv (Sock, (char *)&Cmd, sizeof(Cmd)) != sizeof(Cmd)) {
DEBUGMSG (1, (TEXT("DoInput: Error %d reading cmd\r\n"), WSAGetLastError()));
break;
}
switch (Cmd) {
case 0 :
case MOUSEEVENTF_LEFTDOWN :
case MOUSEEVENTF_LEFTUP :
case MOUSEEVENTF_RIGHTDOWN :
case MOUSEEVENTF_RIGHTUP :
case MOUSEEVENTF_MIDDLEDOWN :
case MOUSEEVENTF_MIDDLEUP :
if (TCPRecv (Sock, (char*)&MouseData, sizeof(MouseData)) == sizeof(MouseData)) {
// mouse_event() expects the coordinates in "touch coordinates"
// so we multiply by 4
mouse_event (MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE | Cmd, MouseData[0] * 0xFFFF/ pThis->m_nScreenWidth,
MouseData[1] * 0xFFFF/pThis->m_nScreenHeight, 0, 0);
}
else {
DEBUGMSG (1, (TEXT("DoInput: Error %d reading mouse event\r\n"), WSAGetLastError()));
goto Exit;
}
break;
case MOUSEEVENTF_WHEEL :
if (TCPRecv (Sock, (char*)&MouseData, sizeof(USHORT)) == sizeof(USHORT)) {
mouse_event (Cmd, 0, 0, (SHORT)MouseData[0], 0);
}
else {
DEBUGMSG (1, (TEXT("DoInput: Error %d reading mouse data\r\n"), WSAGetLastError()));
goto Exit;
}
break;
case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
case WM_SYSKEYDOWN:
if (TCPRecv (Sock, (char *)&MouseData, sizeof(USHORT)) == sizeof(USHORT)) {
dwFlags = ((WM_KEYUP == Cmd) || (WM_SYSKEYUP == Cmd)) ? KEYEVENTF_KEYUP : 0;
// No scancode data.
keybd_event ((BYTE)MouseData[0], 0, dwFlags, 0);
}
else {
DEBUGMSG (1, (TEXT("DoInput: Error %d reading keyboard data\r\n"), WSAGetLastError()));
goto Exit;
}
break;
case WM_DRAW_CURSOR:
if (TCPRecv (Sock, (char *)&MouseData, sizeof(USHORT)) == sizeof(USHORT)) {
v_CursorDrawnByCE = (BOOL)MouseData[0];
}
else {
DEBUGMSG (1, (TEXT("DoInput: Error %d reading mouse draw cursor data\r\n"), WSAGetLastError()));
goto Exit;
}
break;
case CEROBJ_CONFIG:
if (TCPRecv (Sock, (char *)&(pThis->m_Config), sizeof(pThis->m_Config)) == sizeof(pThis->m_Config)) {
if (pThis->m_Config.dwRefreshInterval > 10*1000) {
pThis->m_Config.dwRefreshInterval = 10*1000; // max interval is 10s
}
}
else {
DEBUGMSG (1, (TEXT("DoInput: Error %d reading config data\r\n"), WSAGetLastError()));
goto Exit;
}
break;
default :
DEBUGMSG (1, (TEXT("DoInput: Unknown command\r\n")));
break;
}
}
Exit:
CloseSocket (&pThis->m_Sock);
DEBUGMSG (1, (TEXT("DoInput thread exiting\r\n")));
return -1;
}
DWORD GPECERem::DoBroadcast (LPVOID lParam)
{
GPECERem *pThis = (GPECERem *)lParam;
CERDISPINFO Info;
SOCKADDR_IN SockAddr;
SOCKET Sock;
DEBUGMSG (1, (TEXT("DoBroadcast thread entering\r\n")));
// Init identifier
pThis->InitCerDispInfo(&Info);
// Init address
memset (&SockAddr, 0, sizeof(SockAddr));
SockAddr.sin_family = AF_INET;
SockAddr.sin_port = htons(987);
SockAddr.sin_addr.S_un.S_addr = INADDR_BROADCAST;
while(pThis->m_Sock == INVALID_SOCKET) {
// Create UDP sock
Sock = socket (AF_INET, SOCK_DGRAM, 0);
// Enable broadcast option.
BOOL fBroadcast = TRUE;
setsockopt (Sock, SOL_SOCKET, SO_BROADCAST, (char *)&fBroadcast, sizeof(fBroadcast));
// Broadcast identifier
while(pThis->m_Sock == INVALID_SOCKET) {
if (sendto (Sock, (char*)&Info, sizeof(Info), 0, (sockaddr*)&SockAddr, sizeof(SockAddr)) == SOCKET_ERROR) {
DEBUGMSG (1, (TEXT("GPECERem::DoBroadcast Unable to broadcast\r\n")));
break;
}
Sleep (5*1000);
}
closesocket (Sock);
}
DEBUGMSG (1, (TEXT("DoBroadcast thread exiting\r\n")));
return 0;
}
DWORD
ComputeSum (WORD *pwSrc, int cWords)
{
DWORD dwCheckSum = 0;
for (int i = 0; i < cWords; i++) {
dwCheckSum += pwSrc[i];
}
return dwCheckSum;
}
DWORD
ComputeCRC (WORD *pwSrc, int cWords)
{
PUCHAR Buffer = (PUCHAR)pwSrc;
UINT Length = 2*cWords;
DWORD Crc, Carry;
UINT i, j;
UCHAR CurByte;
Crc = 0xffffffff;
for (i = 0; i < Length; i++) {
CurByte = Buffer[i];
for (j = 0; j < 8; j++) {
Carry = ((Crc & 0x80000000) ? 1 : 0) ^ (CurByte & 0x01);
Crc <<= 1;
CurByte >>= 1;
if (Carry) {
Crc = (Crc ^ 0x04c11db6) | Carry;
}
}
}
return Crc;
}
DWORD
ComputeCheck (DWORD dwCheckPolicy, WORD *pwSrc, int cWords)
{
if (dwCheckPolicy) {
return ComputeCRC (pwSrc, cWords);
}
else {
return ComputeSum (pwSrc, cWords);
}
}
int
CompressRect (WORD *pwSrc, WORD *pwDst, int cWords)
{
int i, offset;
WORD Color, RepeatCount;
offset = 0;
for (i=0; i < cWords; ) {
RepeatCount = 1;
Color = pwSrc[i];
i++;
while ((i < cWords) && (RepeatCount < 0xF000)) {
if (Color != pwSrc[i]) {
break;
}
i++;
RepeatCount++;
}
pwDst[offset++] = RepeatCount;
pwDst[offset++] = Color;
}
return offset;
}
DWORD
CompressRow (PWORD pwSrc, PWORD pwDst, int RowWords)
{
int i, offset;
WORD Color, RepeatCount;
offset = 2;
for (i=0; i < RowWords; ) {
RepeatCount = 1;
Color = pwSrc[i];
i++;
while (i < RowWords) {
if (Color != pwSrc[i]) {
break;
}
i++;
RepeatCount++;
}
pwDst[offset++] = RepeatCount;
pwDst[offset++] = Color;
}
pwDst[1] = offset - 2;
return offset;
}
DWORD WINAPI GPECERem::Refresh (LPVOID lParam)
{
GPECERem *pThis = (GPECERem *)lParam;
WSADATA wsaData;
WORD wVersionRequested;
int Status, cRemoteAddr;
SOCKADDR_IN SockAddr, RemoteAddr;
SOCKET ListenSock;
CERDISPINFO Info;
CERPALUPDATE PalObj;
RGBQUAD rgq[256];
CERRECTUPDATE RectObj;
WORD *pwSrc, *pwDst = NULL;
int i, cWords, offset;
HANDLE hBroadcastThread, hInputThread;
DWORD dwThreadID;
DWORD dwCheck, dwOldCheck;
DWORD *pdwRowCheck;
DWORD dwLastTick;
DEBUGMSG (1, (TEXT("GPECERem::Refresh FrameBuffer=0x%X\r\n"), pThis->m_VirtualFrameBuffer));
if (!CeSetThreadPriority(GetCurrentThread(), 200))
{
DEBUGMSG (1, (TEXT("GPECERem::Refresh warning, failed to set CEThreadPriority!\r\n")));
return -1;
}
RETAILMSG (1, (TEXT("GPECERem::Refresh thread priority=%d\r\n"), CeGetThreadPriority(GetCurrentThread())));
wVersionRequested = MAKEWORD(1,1);
Status = WSAStartup (wVersionRequested, &wsaData);
if (Status != 0) {
DEBUGMSG (1, (TEXT("GPECERem::Refresh WSAStartup call failed!!, Error %d\r\n"), WSAGetLastError()));
return -1;
}
// Initialize default values
memset ((char *)&SockAddr, 0, sizeof(SockAddr));
SockAddr.sin_family = AF_INET;
SockAddr.sin_port = htons(987);
SockAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
// Create listen sock
ListenSock = socket (AF_INET, SOCK_STREAM, 0);
bind (ListenSock, (SOCKADDR *)&SockAddr, sizeof(SockAddr));
listen (ListenSock, 1);
while (1) {
// Start the broadcast thread.
hBroadcastThread = CreateThread (NULL, 0, DoBroadcast, (LPVOID)pThis, 0, &dwThreadID);
// Accept client connect
cRemoteAddr = sizeof(RemoteAddr);
pThis->m_Sock = accept (ListenSock, (SOCKADDR *)&RemoteAddr, &cRemoteAddr);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?