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 + -
显示快捷键?