#include <Symbol.h>
#include <MyFrame.h>
#include <Socket3.h>

void (*__pRemote_UnknowFc)(void* pPage) = NULL;

void (*__QQ_RECV_FC)(char*, int, DWORD, IP_ADDRESS) = NULL;
DWORD __QQ_RECV_Param = NULL;

IP_ADDRESS mIpQQAddr = {169, 254, 82, 134};



WORD wAfxRemoteSocket = 6200;

extern IP_ADDRESS mAfxIpSelfAddr;
extern IP_ADDRESS mAfxIpPeerAddr;

//2008-03-14
//extern BOOL bAfxPcm3486Display;
//extern BOOL bAfxSed1335Display;

SOCKET hAfxRemoteSocket = INVALID_SOCKET;

#define REMOTE_WINSAIL_UNKNOWN    0

#define REMOTE_WINSAIL_KEYBOARD   1
#define REMOTE_WINSAIL_BITMAP     2
#define REMOTE_WINSAIL_BEATHEART  3

#define REMOTE_WINSAIL_MOUSELEFT  4
#define REMOTE_WINSAIL_MOUSERIGHT 5
#define REMOTE_WINSAIL_MOUSEMOVE  6


#define REMOTE_WINSAIL_SUCCESS    7
#define REMOTE_WINSAIL_FAIL       8

#define REMOTE_WINSAIL_SENDFILE_REQ   9
#define REMOTE_WINSAIL_RECVFILE_REQ   10

#define REMOTE_WINSAIL_SENDFILE_ACK   11
#define REMOTE_WINSAIL_RECVFILE_ACK   12

#define REMOTE_WINSAIL_QQ             13
#define REMOTE_WINSAIL_UNKNOW         0xFF


#define WINSAIL_REMOTE_FLAGS          0xA5A5u

#define ETHERNET_FILEHEAD_FLAGS       0xA5A55AA00lu
#define ETHERNET_FILEHEAD_VERSION     2
#define ETHERNET_FILEHEAD_MAXPAGESIZE 256




struct REMOTE_CONTROL_PAGE
{
	WORD wFlags;
    WORD wLength;

    WORD wCommand;
    WORD wKey;

    DWORD dwResrve1;
    DWORD dwReserve2;

    WORD  wReserve0;
    WORD wCheckSum;
};

struct REMOTE_CMD_BITMAP_PAGE
{
	short int nLeft;
    short int nTop;
	short int nRight;
    short int nBottom;
    short int nIndex;
    short int nReserve;
};

struct REMOTE_CMD_MOUSE_PAGE
{
	short int nX;
    short int nY;
    short int nStatus;
    short int nReserve;
};

struct REMOTE_CMD_FILEHEAD_PAGE
{
    WORD  wVersion;
    WORD  wHeadLen;
    DWORD dwFileLen;
    DWORD dwIndex;
	WORD  wServer;
	BYTE  byReserve2;
	BYTE  byData[1];
};


CDialog* DoWithReceiveFile(BOOL bSendReq, const char* pFileName)
{
	char buf[50];

	sprintf(buf, "文件：");
	if (_fstrlen(pFileName) > 30)
	{
		_fmemcpy(&buf[6], (void *)pFileName, 30);
		buf[36-3] = '.';
		buf[36-2] = '.';
		buf[36-1] = '.';
		buf[36-0] = '\0';

	}
	else
	{
		_fstrcat(buf, pFileName);
	}

	char *pStrCaption = (bSendReq)?"文件发送":"文件接收";

	//Create a Dialog On the Center of Desktop
	CDialog* pDialog = new CDialog;//分配实例
	pDialog->CreateWindow(0, 0, 320, 110, pStrCaption);
	pDialog->Center();//窗口对中

	//Create a Label Control
	CLabel* pLabel1 = new CLabel(pDialog);
	pLabel1->CreateObject(13, 40, 168, 12, buf);//"当前进度：00.000%");
	pLabel1->SetID(LABELBASE + 1 - 1);

	//Create Process Control
	CProgressCtrl* pProgressCtrl1 = new CProgressCtrl(pDialog);
	pProgressCtrl1->CreateObject(13, 62, 285, 24, NULL);
	pProgressCtrl1->SetID(PROGRESSBASE + 1 - 1);
	pProgressCtrl1->SetHorz(TRUE);


	pProgressCtrl1->SetRange(0, 10);

	//Show Window
	pDialog->ShowWindow();//显示窗口

	return(pDialog);
}




extern int nAfxScreenPage;
extern int nAfxScreenColor;
extern int KernelChangePage(int, int);

void Remote_RegisterUnknow(void (*pFc)(void*))
{
	__pRemote_UnknowFc = pFc;
}

void RegisterQQ_RecvFC(void (*pFc)(char*, int, DWORD, IP_ADDRESS), DWORD dwParam)
{
    __QQ_RECV_Param = dwParam;
    __QQ_RECV_FC = pFc;
}


BOOL SendRemoteOK(SOCKET hSocket, sockaddr_in* pToAddr)
{
	REMOTE_CONTROL_PAGE mControlPage;
    _fmemset((BYTE *)&mControlPage, 0, sizeof(REMOTE_CONTROL_PAGE));

    mControlPage.wFlags = WINSAIL_REMOTE_FLAGS ;
    mControlPage.wLength = sizeof(REMOTE_CONTROL_PAGE);
    mControlPage.wCommand = REMOTE_WINSAIL_SUCCESS;

	mControlPage.wCheckSum = ::GetEthernetChecksum(
		(WORD *)&mControlPage, mControlPage.wLength, FALSE);

    int nResult = ::sendto(hSocket, (BYTE *)&mControlPage, mControlPage.wLength,
		0, (sockaddr *)pToAddr, sizeof(sockaddr_in));

    return((nResult == SOCKET_ERROR)?FALSE:TRUE);
}

BOOL SendRemoteFail(SOCKET hSocket, sockaddr_in* pToAddr)
{
	REMOTE_CONTROL_PAGE mControlPage;
    _fmemset((BYTE *)&mControlPage, 0, sizeof(REMOTE_CONTROL_PAGE));

    mControlPage.wFlags = WINSAIL_REMOTE_FLAGS ;
    mControlPage.wLength = sizeof(REMOTE_CONTROL_PAGE);
    mControlPage.wCommand = REMOTE_WINSAIL_FAIL;

	mControlPage.wCheckSum = ::GetEthernetChecksum(
		(WORD *)&mControlPage, mControlPage.wLength, FALSE);

    int nResult = ::sendto(hSocket, (BYTE *)&mControlPage, mControlPage.wLength,
		0, (sockaddr *)pToAddr, sizeof(sockaddr_in));

    return((nResult == SOCKET_ERROR)?FALSE:TRUE);
}

BOOL ReceiveRemoteOK(SOCKET hSocket, sockaddr_in* pToAddr)
{
	int nResult, nSize;
	sockaddr_in mFromAddr;

	REMOTE_CONTROL_PAGE mControlPage;
    _fmemset((BYTE *)&mControlPage, 0, sizeof(REMOTE_CONTROL_PAGE));


    //Wait 500mS
	if (!::QueryNetcardPage(hSocket, TRUE, 5000))
    {
    	return(FALSE);
    }

    nSize = sizeof(sockaddr_in);
	nResult = ::recvfrom(hSocket, (BYTE *)&mControlPage,
		sizeof(REMOTE_CONTROL_PAGE), 0,
		(sockaddr FAR *)&mFromAddr, &nSize);



	if (nResult != sizeof(REMOTE_CONTROL_PAGE) ||
		mControlPage.wFlags != WINSAIL_REMOTE_FLAGS ||
    	mControlPage.wLength != sizeof(REMOTE_CONTROL_PAGE) ||
    	mControlPage.wCommand != REMOTE_WINSAIL_SUCCESS ||
		0 != ::GetEthernetChecksum((WORD *)&mControlPage,
			mControlPage.wLength, FALSE) ||
        mFromAddr.sin_port != pToAddr->sin_port||
        mFromAddr.sin_addr.S_un.S_addr != pToAddr->sin_addr.S_un.S_addr)
		//0 != _fmemcmp(&mFromAddr, pToAddr, sizeof(sockaddr)))
    {
    	return(FALSE);
    }
	return(TRUE);

}

BOOL SendFileToEthernet(SOCKET hSocket,
	const char* pFileName, sockaddr_in* pToAddr, DWORD dwDialog)
{
	CDialog* pDialog = (CDialog *)dwDialog;
	CProgressCtrl* pProgressCtrl1 = (CProgressCtrl *)pDialog->
		ObjectFromID(PROGRESSBASE + 1 - 1);


	int nLen = ::_fstrlen(pFileName);
	if (nLen >= 250 || nLen  < 1 ||
		nLen >= ETHERNET_FILEHEAD_MAXPAGESIZE)
	{
		return(FALSE);
	}

	FILE* pFile = ::fopen(pFileName, "rb");
	if (pFile == NULL)
	{
		if (!::SendRemoteFail(hSocket, pToAddr))
		{
			return(FALSE);
		}
		return(FALSE);
	}


	if (!::SendRemoteOK(hSocket, pToAddr))
	{
		fclose(pFile);
		return(FALSE);
	}

	if (!ReceiveRemoteOK(hSocket, pToAddr))
	{
		fclose(pFile);
		return(FALSE);
	}


    //Malloc Buffer
    int nMallocSize = sizeof(REMOTE_CONTROL_PAGE) +
		(sizeof(REMOTE_CMD_FILEHEAD_PAGE) - 1) + 2 * ETHERNET_FILEHEAD_MAXPAGESIZE;

	BYTE* pBuffer = new BYTE[nMallocSize];

    ::_fmemset(pBuffer, 0 , nMallocSize);


    REMOTE_CONTROL_PAGE *pControlPage = (REMOTE_CONTROL_PAGE *)pBuffer;
    REMOTE_CMD_FILEHEAD_PAGE *pFilePage =
		(REMOTE_CMD_FILEHEAD_PAGE *)&pBuffer[sizeof(REMOTE_CONTROL_PAGE)];

    //Fill REMOTE_CONTROL_PAGE Head
	pControlPage->wFlags = WINSAIL_REMOTE_FLAGS ;
    pControlPage->wCommand = REMOTE_WINSAIL_SENDFILE_ACK;

    //Fill REMOTE_CMD_FILEHEAD_PAGE Head
    long lgLength = ::filelength(fileno(pFile));

    pFilePage->wVersion = ETHERNET_FILEHEAD_VERSION;
    pFilePage->dwFileLen = lgLength;
    pFilePage->dwIndex  = 0xFFFFFFFFlu;
    pFilePage->wServer = 0;
    _fstrcpy(pFilePage->byData, pFileName);
    pFilePage->wHeadLen = (sizeof(REMOTE_CMD_FILEHEAD_PAGE) -1) +
		_fstrlen(pFileName) + 1;



	//Send File Head
	pControlPage->wCheckSum = 0;
    pControlPage->wLength = sizeof(REMOTE_CONTROL_PAGE) + pFilePage->wHeadLen;
	pControlPage->wCheckSum = ::GetEthernetChecksum(
		(WORD *)pBuffer, pControlPage->wLength, FALSE);

    ::sendto(hSocket, (const char *)pControlPage, pControlPage->wLength, 0,
		(sockaddr FAR *)pToAddr, sizeof(sockaddr_in));

	if (!::ReceiveRemoteOK(hSocket, pToAddr))
	{
    	delete pBuffer;
        ::fclose(pFile);
        return(FALSE);
    }

    BOOL bSend = TRUE;
    pFilePage->dwIndex  = 0;

    //Send File Text
    DWORD dwPages = ((lgLength / ETHERNET_FILEHEAD_MAXPAGESIZE) +
		(((lgLength % ETHERNET_FILEHEAD_MAXPAGESIZE) != 0L)?1:0));

	pProgressCtrl1->SetRange(0, dwPages - 1);

	for (DWORD  i = 0; i < dwPages; i++)
	{
		int nReadCount = ::fread((void *)pFilePage->byData,
			1L, ETHERNET_FILEHEAD_MAXPAGESIZE, pFile);

        if (nReadCount == 0 || nReadCount == -1)
        {
        	bSend = FALSE;
        	break;
        }

		pControlPage->wFlags = WINSAIL_REMOTE_FLAGS ;
    	pControlPage->wCommand = REMOTE_WINSAIL_SENDFILE_ACK;
		pControlPage->wCheckSum = 0;

	    pFilePage->wVersion = ETHERNET_FILEHEAD_VERSION;
    	pFilePage->dwFileLen = lgLength;
	    pFilePage->dwIndex  = i;
    	pFilePage->wServer = 0;
	    pFilePage->wHeadLen = sizeof(REMOTE_CMD_FILEHEAD_PAGE) - 1 + nReadCount;

        pControlPage->wLength = sizeof(REMOTE_CONTROL_PAGE) + pFilePage->wHeadLen;
		pControlPage->wCheckSum = ::GetEthernetChecksum(
			(WORD *)pBuffer, pControlPage->wLength, FALSE);

		//Send File Text
	    ::sendto(hSocket, (const char *)pControlPage, pControlPage->wLength,
			0, (sockaddr FAR *)pToAddr, sizeof(sockaddr_in));

		if (!::ReceiveRemoteOK(hSocket, pToAddr))
		{
    		delete pBuffer;
	        ::fclose(pFile);
    	    return(FALSE);
    	}

		pProgressCtrl1->AddShow(i);

	    //pFilePage->dwIndex += nReadCount;
	}


	//Send End
    if (bSend)
	{
    	pFilePage->wVersion = ETHERNET_FILEHEAD_VERSION;
        pFilePage->wServer = 0;
        pFilePage->dwFileLen = lgLength;

    	pFilePage->wHeadLen = sizeof(REMOTE_CMD_FILEHEAD_PAGE) - 1;
	    pFilePage->dwIndex = 0xFFFFFFFElu;

		pControlPage->wCheckSum = 0;
    	pControlPage->wLength = sizeof(REMOTE_CONTROL_PAGE) + pFilePage->wHeadLen;
		pControlPage->wCheckSum = ::GetEthernetChecksum(
			(WORD *)pBuffer, pControlPage->wLength, FALSE);

	    ::sendto(hSocket, (const char *)pControlPage, pControlPage->wLength, 0,
			(sockaddr FAR *)pToAddr, sizeof(sockaddr_in));

		if (!::ReceiveRemoteOK(hSocket, pToAddr))
		{
    		delete pBuffer;
		    ::fclose(pFile);
        	return(FALSE);
    	}
    }

	delete pBuffer;
    ::fclose(pFile);
	return(TRUE);
}

BOOL ReceiveFileFromEthernet(SOCKET hSocket, const char* pFileName, sockaddr_in* pToAddr, DWORD dwDialog)
{
	CDialog* pDialog = (CDialog *)dwDialog;
	CProgressCtrl* pProgressCtrl1 = (CProgressCtrl *)pDialog->
		ObjectFromID(PROGRESSBASE + 1 - 1);

	if (hAfxRemoteSocket == NULL || hAfxRemoteSocket == INVALID_SOCKET)
	{
		return(FALSE);
	}


	//打开临时文件
	FILE* pFile = ::fopen("abc.$$$", "w+b");
	if (pFile == NULL)
	{
		return(FALSE);
	}

	if (!::SendRemoteOK(hSocket, pToAddr))
	{
		fclose(pFile);
		return(FALSE);
	}


	//填充发往地址
	sockaddr_in mPeerAddr;
	memset(&mPeerAddr, 0 , sizeof(sockaddr_in));

	//计算包的长度
	int nSize = sizeof(REMOTE_CONTROL_PAGE) + 
		(sizeof(REMOTE_CMD_FILEHEAD_PAGE) - 1) +
		(strlen(pFileName) + 1);

	//分配包的空间
	REMOTE_CONTROL_PAGE* pRemoteControlPage = 
		(REMOTE_CONTROL_PAGE *)new BYTE[512];

	REMOTE_CMD_FILEHEAD_PAGE* pFilePage = (REMOTE_CMD_FILEHEAD_PAGE *)
		(((BYTE *)pRemoteControlPage) + sizeof(REMOTE_CONTROL_PAGE));

	BYTE   *pData = ((BYTE *)pFilePage) + sizeof(REMOTE_CMD_FILEHEAD_PAGE ) - 1;

	//初始化请求发送命令包
	::memset(pRemoteControlPage, 0, 512);


	//查询Start头
	BOOL bSuccess = TRUE;
	if (!::QueryNetcardPage(hSocket, TRUE, 5000))
	{
		::fclose(pFile);
		delete pRemoteControlPage;
		return(FALSE);
	}

	//接收Start头
	int nFromLen = sizeof(sockaddr_in);
	int nLen = ::recvfrom(hAfxRemoteSocket, (char *)pRemoteControlPage, 512, 
			0, (sockaddr *)&mPeerAddr, &nFromLen);

	//判断Start头
	if ((nLen == 0 || nLen == SOCKET_ERROR || nLen != nSize )||
		pRemoteControlPage->wFlags != WINSAIL_REMOTE_FLAGS ||
		pRemoteControlPage->wLength != (WORD)nLen ||
		pRemoteControlPage->wCommand != REMOTE_WINSAIL_RECVFILE_ACK ||
		0 != ::GetEthernetChecksum((WORD *)pRemoteControlPage, nLen, FALSE) ||
		//=====================================================================
		pFilePage->wVersion != ETHERNET_FILEHEAD_VERSION ||
		pFilePage->wServer != 1 ||
		pFilePage->wHeadLen != (sizeof(REMOTE_CMD_FILEHEAD_PAGE) - 1) +
			(strlen(pFileName) + 1) ||
		pFilePage->dwIndex != 0xFFFFFFFFlu ||
		//===========================================================
		mPeerAddr.sin_port != pToAddr->sin_port||
        mPeerAddr.sin_addr.S_un.S_addr != pToAddr->sin_addr.S_un.S_addr)

	{
		fclose(pFile);
		delete pRemoteControlPage;
		return(FALSE);
	}


	//发送OK包--为Start头
	if (!::SendRemoteOK(hAfxRemoteSocket, &mPeerAddr))
	{
		fclose(pFile);
		delete pRemoteControlPage;
		return(FALSE);
	}

	//文件长度
	long lgLength = pFilePage->dwFileLen;
	

	bSuccess = TRUE;

	//计算数据包的帧数目
	DWORD dwPages = ((lgLength / ETHERNET_FILEHEAD_MAXPAGESIZE) +
		(((lgLength % ETHERNET_FILEHEAD_MAXPAGESIZE) != 0L)?1:0));
	DWORD dwOffset = lgLength % ETHERNET_FILEHEAD_MAXPAGESIZE;

	pProgressCtrl1->SetRange(0, dwPages - 1);

	//将数据发送给客户机
	for (DWORD  i = 0; i < dwPages; i++)
	{
		//接收文件头
		if (!::QueryNetcardPage(hAfxRemoteSocket, TRUE, 5000))
		{
			bSuccess = FALSE;
			break;
		}

		nFromLen = sizeof(sockaddr_in);
		nLen = ::recvfrom(hAfxRemoteSocket, (char *)pRemoteControlPage, 512,
			0, (sockaddr *)&mPeerAddr, &nFromLen);

		if ((nLen == 0 || nLen == SOCKET_ERROR) ||
			pRemoteControlPage->wFlags != WINSAIL_REMOTE_FLAGS ||
			pRemoteControlPage->wLength != (WORD)nLen ||
			pRemoteControlPage->wCommand != REMOTE_WINSAIL_RECVFILE_ACK ||
			0 != ::GetEthernetChecksum((WORD *)pRemoteControlPage, nLen, FALSE) ||
			//=====================================================================
			pFilePage->wVersion != ETHERNET_FILEHEAD_VERSION ||
			pFilePage->wServer != 1 ||
			pFilePage->wHeadLen <= sizeof(REMOTE_CMD_FILEHEAD_PAGE ) - 1 ||
			pFilePage->wHeadLen > sizeof(REMOTE_CMD_FILEHEAD_PAGE ) - 1 +
				ETHERNET_FILEHEAD_MAXPAGESIZE  ||
			pFilePage->dwIndex != i ||
			//=============================================================
			mPeerAddr.sin_port != pToAddr->sin_port||
			mPeerAddr.sin_addr.S_un.S_addr != pToAddr->sin_addr.S_un.S_addr)
		{
			bSuccess = FALSE;
			break;
		}

		int nExt = pFilePage->wHeadLen - (sizeof(REMOTE_CMD_FILEHEAD_PAGE) - 1);
		if (i + 1 != dwPages && nExt != ETHERNET_FILEHEAD_MAXPAGESIZE ||
			(i + 1 == dwPages && dwOffset != 0 && nExt != (int)dwOffset))
		{
			bSuccess = FALSE;
			break;
		}


		int nReadData = pFilePage->wHeadLen - (sizeof(REMOTE_CMD_FILEHEAD_PAGE ) - 1);
		::fwrite(pData, 1, nReadData, pFile);

		pProgressCtrl1->AddShow(i);

		if (!::SendRemoteOK(hAfxRemoteSocket, &mPeerAddr))
		{
			bSuccess = FALSE;
			break;
		}

	}




	//如果没有错，接收End包
	while (bSuccess)
	{
		//计算End包的长度
		nSize = sizeof(REMOTE_CONTROL_PAGE) +
			(sizeof(REMOTE_CMD_FILEHEAD_PAGE) - 1);

		//查询End
		if (!::QueryNetcardPage(hAfxRemoteSocket, TRUE, 5000))
		{
			bSuccess = FALSE;
			break;
		}

		//接收End包
		nFromLen = sizeof(sockaddr_in);
		nLen = ::recvfrom(hAfxRemoteSocket, (char *)pRemoteControlPage, 512,
			0, (sockaddr *)&mPeerAddr, &nFromLen);

		//判断End包
		if ((nLen == 0 || nLen == SOCKET_ERROR || nLen != nSize) ||
			pRemoteControlPage->wFlags != WINSAIL_REMOTE_FLAGS ||
			pRemoteControlPage->wLength != (WORD)nLen ||
			pRemoteControlPage->wCommand != REMOTE_WINSAIL_RECVFILE_ACK ||
			0 != ::GetEthernetChecksum((WORD *)pRemoteControlPage, nLen, FALSE) ||
			//=====================================================================
			pFilePage->wVersion != ETHERNET_FILEHEAD_VERSION ||
			pFilePage->wServer != 1 ||
			pFilePage->wHeadLen != (sizeof(REMOTE_CMD_FILEHEAD_PAGE) - 1) ||
			pFilePage->dwIndex != 0xFFFFFFFElu ||
			//==============================================================
			mPeerAddr.sin_port != pToAddr->sin_port||
			mPeerAddr.sin_addr.S_un.S_addr != pToAddr->sin_addr.S_un.S_addr)
		{
			bSuccess = FALSE;
			break;
		}


		//发送OK包
		if (!::SendRemoteOK(hAfxRemoteSocket, &mPeerAddr))
		{
			bSuccess = FALSE;
			break;
		}

		//Break;
		break;
	}

	//关闭文件
	fclose(pFile);

	//释放缓冲区
	delete pRemoteControlPage;

	//拷贝文件
	if (bSuccess)
	{
		bSuccess = ::CopyFile("abc.$$$", pFileName, FALSE);
		if (bSuccess)
		{
			::SendRemoteOK(hAfxRemoteSocket, &mPeerAddr);
		}
		else
		{
			::SendRemoteFail(hAfxRemoteSocket, &mPeerAddr);
		}
	}
	return(bSuccess);
}

BOOL far SendRectScreen(SOCKET hSocket, int nLeft,
	int nTop,int nRight, int nBottom, sockaddr_in* pToAddr)
{
	BOOL bResult = TRUE;
	int nMaxSize= 320;

	BYTE* pBuffer = new BYTE[sizeof(REMOTE_CONTROL_PAGE) +
		sizeof(REMOTE_CMD_BITMAP_PAGE) + nMaxSize + 4];

    REMOTE_CONTROL_PAGE *pControlPage = (REMOTE_CONTROL_PAGE *)pBuffer;
    REMOTE_CMD_BITMAP_PAGE *pBitmapPage =
		(REMOTE_CMD_BITMAP_PAGE *)&pBuffer[sizeof(REMOTE_CONTROL_PAGE)];

    ::_fmemset(pControlPage, 0 , sizeof(REMOTE_CONTROL_PAGE));
    ::_fmemset(pBitmapPage, 0 , sizeof(REMOTE_CMD_BITMAP_PAGE));


	pControlPage->wFlags = WINSAIL_REMOTE_FLAGS ;
    pControlPage->wCommand = REMOTE_WINSAIL_BITMAP;

    pBitmapPage->nLeft = nLeft;
    pBitmapPage->nTop = nTop;
    pBitmapPage->nRight = nRight;
    pBitmapPage->nBottom = nBottom;

    int nIndex = 0;
    int nPoint = 0;
    BYTE* byData = pBuffer + sizeof(REMOTE_CONTROL_PAGE) +
		sizeof(REMOTE_CMD_BITMAP_PAGE);

    BYTE* pMemory = (BYTE *)MK_FP(0xA000u, 0x0);

    int nOldPage = nAfxScreenPage;

	int nPage = 0;
	if (nAfxScreenColor == 256)
    {
		::KernelChangePage(0, - 1);
    }

    long lgTotalCount = 0;
    for (int i = nTop; i <= nBottom; i++)
    {
    	if (!bResult)
        {
        	break;
        }
	    for (int j = nLeft; j <= nRight; j++)
    	{
        	nPoint++;
            int nColor;
			if (nAfxScreenColor == 16)
				//2008-03-14
				//|| bAfxPcm3486Display || bAfxSed1335Display)
			{
				nColor = (WORD)::GetPixel(j, i);
            }
            else
            {
				nColor = (int)(WORD)*(pMemory++);
                if (*((WORD *)&pMemory) == 0)
                {
				    pMemory = (BYTE *)MK_FP(0xA000u, 0x0);
                    ::KernelChangePage(++nPage, -1);
                }
            }

            if (nColor > 0)
            {
            	nColor = nColor -  1 + 0x1E;
            }
            *(byData++) = (BYTE)nColor;

            if (nPoint >= nMaxSize || (i == nBottom && j == nRight))
            {
				pControlPage->wCheckSum = 0;
                pControlPage->wLength = sizeof(REMOTE_CONTROL_PAGE) +
					sizeof(REMOTE_CMD_BITMAP_PAGE) + nPoint;

                pBitmapPage->nIndex = nIndex;

				pControlPage->wCheckSum = ::GetEthernetChecksum(
					(WORD *)pBuffer, pControlPage->wLength, FALSE);

            	 if (0 != ::sendto(hSocket, pBuffer, pControlPage->wLength,
					0, (sockaddr *)pToAddr, sizeof(sockaddr_in)))
                 {
                 	bResult = FALSE;
                    break;
                 }

				 if (!::ReceiveRemoteOK(hSocket, pToAddr))
                 {
                 	bResult = FALSE;
                    break;
                 }


                //KernelDelay(1);

            	nIndex++;
            	nPoint = 0;
            	byData = pBuffer + sizeof(REMOTE_CONTROL_PAGE) +
					sizeof(REMOTE_CMD_BITMAP_PAGE);

                if (nAfxScreenColor == 256 &&
					((i - nTop) % 10) == 0 && i != nTop)
                {
					//2008-03-14
                	//if (bAfxPcm3486Display || bAfxSed1335Display)
                    //{
                    	//::KernelDelay(5);
                    //}
                    //else
                    {
                		::AfxMicroDelay(MICRODELAY_TIME_5);
                    }
                }
            }
	    }

    }

    if (nAfxScreenColor == 256)
	{
		::KernelChangePage(nOldPage, -1);
	}
	delete pBuffer;
	return(bResult);
}

BOOL DoWithRemoteNetcard(SOCKET hSocket, BYTE* pBuffer,
	int nSize, sockaddr_in mFromAddr, int nFromLen)
{
	REMOTE_CONTROL_PAGE* pRemoteControlPage = (REMOTE_CONTROL_PAGE *)pBuffer;

	if (nSize < sizeof(REMOTE_CONTROL_PAGE))
    {
    	return(FALSE);
    }

	if (pRemoteControlPage->wFlags != WINSAIL_REMOTE_FLAGS ||
        pRemoteControlPage->wLength != (WORD)nSize ||
		0 != ::GetEthernetChecksum((WORD *)pBuffer, nSize, FALSE))
	{
    	return(FALSE);
	}


	::_fmemcpy((BYTE *)mIpQQAddr,
		(BYTE *)&mFromAddr.sin_addr.S_un.S_addr,
        sizeof(IP_ADDRESS));

    BOOL bResult = FALSE;
    switch (pRemoteControlPage->wCommand)
    {
    	case REMOTE_WINSAIL_KEYBOARD:
        {
	    	if (nSize != sizeof(REMOTE_CONTROL_PAGE))
    	    {
        		return(FALSE);
	        }
    	    ::AddKeyboard(pRemoteControlPage->wKey);

            bResult = TRUE;
        	break;
        }
        case REMOTE_WINSAIL_BEATHEART:
        {
			::sendto(hSocket, pBuffer, nSize, 0,
				(struct sockaddr FAR *)&mFromAddr, nFromLen);

            bResult = TRUE;
            break;
        }
		case REMOTE_WINSAIL_BITMAP:
        {
			REMOTE_CMD_BITMAP_PAGE *pBitmapPage =
				(REMOTE_CMD_BITMAP_PAGE *)&pBuffer[sizeof(REMOTE_CONTROL_PAGE)];

            if (nSize != sizeof(REMOTE_CONTROL_PAGE) +
            	sizeof(REMOTE_CMD_BITMAP_PAGE))
            {
            	break;
            }

        	int nMouse = ::GetMouse();
	        ::CloseMouse();

			bResult = ::SendRectScreen(hSocket, pBitmapPage->nLeft, pBitmapPage->nTop,
				pBitmapPage->nRight, pBitmapPage->nBottom, &mFromAddr);

	        ::SetMouse(nMouse);
        	break;
        }
		case REMOTE_WINSAIL_MOUSELEFT:
		case REMOTE_WINSAIL_MOUSERIGHT:
		case REMOTE_WINSAIL_MOUSEMOVE:
		{
			REMOTE_CMD_MOUSE_PAGE *pMousePage =
				(REMOTE_CMD_MOUSE_PAGE *)&pBuffer[sizeof(REMOTE_CONTROL_PAGE)];

            if (nSize != sizeof(REMOTE_CONTROL_PAGE) +
            	sizeof(REMOTE_CMD_MOUSE_PAGE))
            {
            	break;
            }


			::AfxSetRemoteMouse(pMousePage->nX,
				pMousePage->nY, pMousePage->nStatus);

            bResult = TRUE;
        	break;
        }
		case REMOTE_WINSAIL_SENDFILE_REQ:
		case REMOTE_WINSAIL_RECVFILE_REQ:
		{
			REMOTE_CMD_FILEHEAD_PAGE *pFilePage =
				(REMOTE_CMD_FILEHEAD_PAGE *)&pBuffer[sizeof(REMOTE_CONTROL_PAGE)];

            if (pFilePage->wServer != 1 ||
				pFilePage->wVersion != ETHERNET_FILEHEAD_VERSION ||
				pFilePage->wHeadLen != nSize - sizeof(REMOTE_CONTROL_PAGE) ||
				pFilePage->wHeadLen > (sizeof(REMOTE_CMD_FILEHEAD_PAGE) - 1 +
						ETHERNET_FILEHEAD_MAXPAGESIZE) ||
				nSize - sizeof(REMOTE_CONTROL_PAGE) <
						sizeof(REMOTE_CMD_FILEHEAD_PAGE) - 1)
			{
				break;
			}


			if (pRemoteControlPage->wCommand == REMOTE_WINSAIL_SENDFILE_REQ)
			{
				CDialog* pDialog = ::DoWithReceiveFile(TRUE, (const char *)pFilePage->byData);
				pDialog->ShowWindow();

				bResult = ::SendFileToEthernet(hSocket,
					(const char *)pFilePage->byData, &mFromAddr, (DWORD)pDialog);

				delete pDialog;
			}
			else if(pRemoteControlPage->wCommand == REMOTE_WINSAIL_RECVFILE_REQ)
			{
				CDialog* pDialog = ::DoWithReceiveFile(FALSE, (const char *)pFilePage->byData);
				pDialog->ShowWindow();


				bResult = ::ReceiveFileFromEthernet(hSocket,
					(const char *)pFilePage->byData, &mFromAddr, (DWORD)pDialog);

				delete pDialog;
			}
			else
			{
				bResult = FALSE;
            }

            break;
        }
		case REMOTE_WINSAIL_QQ:
        {
	    	if (nSize <= sizeof(REMOTE_CONTROL_PAGE))
    	    {
        		return(FALSE);
			}



			char* pString= (char *)&pBuffer[sizeof(REMOTE_CONTROL_PAGE)];

            if (__QQ_RECV_FC != NULL)
            {
                __QQ_RECV_FC (pString,
                    nSize - sizeof(REMOTE_CONTROL_PAGE),
                    __QQ_RECV_Param, mIpQQAddr);

            }


            bResult = TRUE;

            break;
        }
		default:
        {
        	bResult = FALSE;
        	break;
        }
    }

	return (bResult);
}

//nSeek == 0 --> Create Client Remote Socket
//nSeek == 1 --> Normal Client Remote Socket
//nSeek == 2 --> Close  Client Remote Socket
BOOL RemoteContorlClient(int nSeek)
{
	SOCKET hSocket = hAfxRemoteSocket;
    if (nSeek == 0)
    {
		if (hAfxRemoteSocket != INVALID_SOCKET)
        {
			return(FALSE);
        }

		hSocket = ::socket(AF_INET, SOCK_DGRAM, 0);

		//初始化客户端地址
		sockaddr_in mClientAddr;
		_fmemset(&mClientAddr, 0 ,sizeof(sockaddr_in));
		mClientAddr.sin_family = AF_INET;
		mClientAddr.sin_addr.S_un.S_addr = *((DWORD *)
			(BYTE *)&mAfxIpSelfAddr[0]);
		mClientAddr.sin_port = htons(wAfxRemoteSocket);

		if (SOCKET_ERROR == ::bind(hSocket,
			(sockaddr *)&mClientAddr,sizeof(sockaddr_in)))
		{
			::closesocket(hSocket);
			return(FALSE);
		}

    	hAfxRemoteSocket = hSocket;

		//::AfxRegisterRemoteMouseFc(RemoteFcMouse);
        return(TRUE);
	}
    else if (nSeek == 2)
    {
		if (hSocket == INVALID_SOCKET)
        {
        	return(FALSE);
        }

        ::closesocket(hSocket);
		hAfxRemoteSocket = INVALID_SOCKET;
        //::AfxRegisterRemoteMouseFc(NULL);
        return(TRUE);
    }

	if (nSeek != 1 || hSocket == INVALID_SOCKET ||
		!QueryNetcardPage(hSocket, TRUE, 0))
    {
		return(FALSE);
    }

	char buf[512];
	sockaddr_in mFromAddr;

    int nFromLen = sizeof(sockaddr_in);
	int nSize = ::recvfrom(hSocket, buf, 512, 0,
		(struct sockaddr FAR *)&mFromAddr, &nFromLen);


	BOOL bResult = ::DoWithRemoteNetcard(hSocket, buf,
		nSize, mFromAddr, nFromLen);

	return(bResult);
}

void SendRemoteQQ(char* pString, int nCount, DWORD dwIP)
{		
	if (hAfxRemoteSocket == NULL || hAfxRemoteSocket == INVALID_SOCKET)
	{
		return;
	}

	if (nCount >= 256)
	{
		return;
	}

    if (dwIP == 0L)
    {
        dwIP = *((DWORD *)mIpQQAddr);
    }



	int nSize = sizeof(REMOTE_CONTROL_PAGE) + nCount;

	//初始化命令包
	REMOTE_CONTROL_PAGE* pRemoteControlPage = 
		(REMOTE_CONTROL_PAGE *)new BYTE[512];

	::memset(pRemoteControlPage, 0, 512);
	
	pRemoteControlPage->wFlags = WINSAIL_REMOTE_FLAGS;
	pRemoteControlPage->wCommand = REMOTE_WINSAIL_QQ;
	pRemoteControlPage->wCheckSum = 0;
	pRemoteControlPage->wKey = 0;
	pRemoteControlPage->wLength = nSize;


	::memcpy (((BYTE *)pRemoteControlPage) + sizeof(REMOTE_CONTROL_PAGE), 
		pString,  nCount);
	

	pRemoteControlPage->wCheckSum = ::GetEthernetChecksum(
		(WORD *)pRemoteControlPage, nSize, FALSE);


	//填充发往地址
	sockaddr_in mPeerAddr;
	memset(&mPeerAddr, 0 , sizeof(sockaddr_in));

	mPeerAddr.sin_family = AF_INET;
	mPeerAddr.sin_addr.S_un.S_addr = dwIP;
	mPeerAddr.sin_port = htons(wAfxRemoteSocket);


    int nResult = ::sendto(hAfxRemoteSocket,
        (BYTE *)pRemoteControlPage,
        pRemoteControlPage->wLength,
		0, (sockaddr *)&mPeerAddr, sizeof(sockaddr_in));


	delete pRemoteControlPage;

	return;
}



