RCPServer.cpp
上传用户:hyz2004817
上传日期:2022-03-30
资源大小:226k
文件大小:25k
- // RCPServer.cpp : Defines the entry point for the application.
- //
- #include "stdafx.h"
- #include "resource.h"
- //#include "WSAErrorString.h"
- //#include "id_handler.h"
- // 时间的限制,以分钟为单位
- #define TIME_LIMIT 10
- // 服务器端主窗口的类名
- #define SERVER_WINDOW_CLASSNAME "drm_rca_server_window_class"
- // 服务器端主窗口的标题名
- #define SERVER_WINDOW_CAPTIONNAME "RCA 服务器"
- // 客户端主窗口的类名
- #define CLIENT_WINDOW_CLASSNAME "drm_rca_client_window_class"
- // 用于创建命名信标对象,控制服务器同一时刻最多只能运行两个实例
- #define RCA_RUNNING_CONTROL_SEMAPHORE_NAME "rca_running_semphore_control"
- // 当前软件的版本号, 语法 MAKEWORD( 次版本号, 主版本号)
- #define CURRENT_VERSION MAKEWORD( 0, 2 )
- // 自定义版本更新消息, WPARAM 为版本验证值,LPARAM 为传送消息的线程的 ID
- // WM_VERSIONUPDATE 消息有两个类型, 一种为
- #define WM_VERSIONUPDATE (WM_USER +3)
- #define VERSION_HIGH 1
- #define VERSION_LOW 2
- #define VERSION_EQUAL 3
- // 自定义消息 假如正在工作的 RCA 版本较低, 一个更高版本的 RCA 将会通知低版本的退出
- // 然后高版本的将等待低版本的传递 WM_OLDVERSIONEXIT 消息,以表示低版本的已经退出
- // 这时高版本的将可以继续运行
- #define WM_OLDVERSIONEXIT (WM_USER +4)
- #define WM_RCASHELLICON (WM_USER +5)
- WORD winsock_version = MAKEWORD(2, 2);
- WSADATA wsadata;
- ///////////////////////////
- //RCAInit 函数初始化的变量
- CHAR g_pszOS[6]; // OS version info
- CHAR g_pszComputerName[MAX_COMPUTERNAME_LENGTH+1]; // computer Name
- CHAR g_pszUserName[UNLEN +1]; // current thread's user name
- CHAR* g_pszSystemDir; // system directory
- CHAR* g_pszWindowsDir; // windows setup directory
- HINSTANCE g_hInstance;
- OSVERSIONINFO g_SysVer; // OS version struct
- MEMORYSTATUS g_MemoryStatus; // memory status struct
- BOOL g_bCanAcceptEx; // 初始化时确定的布尔变量, 说明操作系统是否支持
- // AcceptEx函数
- HWND g_hWnd; // main window handle;
- NOTIFYICONDATA g_nid;
- HICON g_hBig;
- HICON g_hSmall;
- HMENU g_hShellIconMenu;
- HANDLE g_hRunningControlSemaphore;
- DWORD g_dwAnotherRCAVertionUpdateThreadId;
- BOOL g_bMustExit = FALSE;
- HANDLE g_hExitEvent;
- //////////////////////////////////////////////
- //
- // 服务开始使用的全局变量
- //
- HANDLE g_hServiceMainThreadHandle = NULL;
- DWORD g_dwServiceMainThreadID = NULL;
- BOOL g_bServiceMainThreadMustExit = FALSE;
- SOCKET g_sockService = NULL;
- SOCKADDR_IN g_addrServer; // 服务器地址描述
- WORD g_wServerPort; // 服务器端口号, 网络字节顺序
- ///////////////////////////////////////////////
- //
- // 有关安全方面的全局变量
- //
- BOOL g_bAllAccess = TRUE;
- ///////////////////////////////////////////////////
- //
- // 函数原型声明
- //
- BOOL WINAPI RCAInit();
- BOOL WINAPI RCAUninit();
- BOOL WINAPI CanGoon( DWORD * result );
- void WINAPI OutputAddr( unsigned int uIP );
- LRESULT CALLBACK MainWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
- DWORD WINAPI RCAService( PVOID pVoid );
- BOOL WINAPI ServiceMainThreadStartup();
- BOOL WINAPI ServiceInit();
- BOOL WINAPI ServiceUninit();
- BOOL WINAPI AccessControl( RCAREQUESTHEADER * pRequestHead, DWORD dwRemoteAddress, WORD wPort );
- DWORD WINAPI RequestHandle( SOCKET accept, DWORD dwRemoteAddress );
- BOOL WINAPI GetRCARequestIDHandler( DWORD dwRequestID, RCAREQUESTIDHANDLER * pHandler);
- /////////////////////////////////////////////////
- //
- // 通过客户端请求的操作 ID , 查找相应的 ID 处理函数
- //
- //
- BOOL WINAPI GetRCARequestIDHandler( DWORD dwRequestID, RCAREQUESTIDHANDLER * pHandler)
- {
- switch ( dwRequestID )
- {
- case 0x10: // 16 进制 10 号, 10 进制 16 号, 创建进程执行
- *pHandler = RCAID_0X10_HANDLER;
- break;
- case 0x20:
- *pHandler = RCAID_0X20_HANDLER;
- break;
- case 0x40:
- *pHandler = RCAID_0X40_HANDLER;
- break;
- case 0x41:
- *pHandler = RCAID_0X41_HANDLER;
- break;
- case 0x110:
- *pHandler = RCAID_0X110_HANDLER;
- break;
- default:
- return FALSE;
- }
- return TRUE;
- }
- //////////////////////////////////////////////////////
- //
- // 说明:
- // 一个客户端的请求已经到来, 先分析请求是否为 RCA 请求
- // 请求 如果是一个 RCA 请求, 分两步处理:
- // 1. 对请求的访问控制, 这将涉及到发出请求的客户端 IP 地址,
- // 请求的操作 ID. 这些由 AccessControl 函数完成, 如果 AccessControl
- // 返回 TRUE , 则允许执行这个请求, 返回 FALSE, 将拒绝请求.
- //
- // 2. 如果允许执行请求, 将调用 ID 分流模块,
- // 以将请求正确的传递到相应的处理程序
- //
- DWORD WINAPI RequestHandle( PVOID p )
- {
- RCAREQUESTHANDLEDATA * pData = (RCAREQUESTHANDLEDATA *)p;
- SOCKET sockRemote = pData->sockRemote;
- HANDLE hEventArray[2];
- char headBuffer[40];
- PRCAREQUESTHEADER pRCAHead = NULL;
- int ret;
- int nBytes = sizeof(RCAREQUESTHEADER);
- int nLeft = nBytes;
- int i = 0;
- BOOL bExit = FALSE;
-
- hEventArray[0] = CreateEvent( NULL , FALSE, FALSE, NULL );
- hEventArray[1] = g_hExitEvent;
- if( hEventArray[0] == NULL )
- goto end_request_handle;
- ret = WSAEventSelect( sockRemote, hEventArray[0], FD_READ | FD_WRITE | FD_CLOSE );
- if( ret != 0 )
- {
- DEBUGOUTPUT1( WSAERRORSTRING );
- exit(0);
- }
- BOOL bRecv = TRUE;
-
- while( 1 )
- {
-
- ret = RCARecv_EventSelectIO( sockRemote, hEventArray, headBuffer, sizeof(RCAREQUESTHEADER));
- if( ret != sizeof(RCAREQUESTHEADER) )
- break;
- pRCAHead = (RCAREQUESTHEADER*)headBuffer;
- // 确定前四个字节为一个 ANSI C 字符串 "RCA "
- if( 0 != lstrcmp( pRCAHead ->rcaID, "RCA" ) )
- break;
- // 确保版本支持, 当前只支持 1.0 的版本
- // 保证协议版本在 1.0 或 1.0 以下
- if( pRCAHead->wMajorVersion > 1 )
- break;
- if( (pRCAHead->wMajorVersion == 1) && (pRCAHead->wMinorVersion!=0) )
- break;
-
-
- /////////////////////////////////////
- //
- // 至此验证完毕. 大致上符合一个 RCA 的请求
- // 现在将调用 AccessControl 函数, 确定此请求是否接受
- if( !AccessControl( pRCAHead, pData->dwRemoteAddress, (WORD)pData->dwRemotePort ) )
- break;
- RCAREQUESTIDHANDLER pFunc; // ID 处理函数的指针
- //nBytes = pRCAHead->requestBytes - 40; // 需要接收的字节数, 为请求头中 requestBytes 字段 减去 40
- if( GetRCARequestIDHandler( pRCAHead->dwRequestID, &pFunc) )
- {
-
- if( TRUE == (*pFunc)( sockRemote , pData, pRCAHead, hEventArray) )
- {
- nLeft = sizeof(RCAREQUESTHEADER); // 重置接收参数
- i = 0; // 重置接收参数
- continue; // 继续接收下一个请求
- }
- else
- break; // 结束请求处理
- // 省略了一些..... 以后加入
- }
- }
- // 结束请求并释放资源
- end_request_handle:
- if( hEventArray[0] != NULL )
- CloseHandle( hEventArray[0] );
- // shutdown( pData->sockRemote, SD_BOTH );
- closesocket( pData->sockRemote );
- free( p ); // 释放
-
- return 0;
- }
- //////////////////////////////////////////////////////
- //
- // 访问控制的实现函数
- //
- BOOL WINAPI AccessControl( RCAREQUESTHEADER * pRequestHead, DWORD dwRemoteAddress, WORD wPort )
- {
-
- // 现在不实现. 当前版本将接受所有的请求
- return TRUE;
- }
- ////////////////////////////////////////////////////
- //
- // 当监听服务线程结束时必须调用的清除资源的操作
- BOOL WINAPI ServiceUninit()
- {
- int ret;
- closesocket( g_sockService );
- ret = WSACleanup();
- if ( ret != 0 )
- {
- DEBUGOUTPUT1( WSAERRORSTRING );
- return FALSE;
- }
- return TRUE;
- }
- ////////////////////////////////////////////////////////////
- //
- // 监听服务线程需要的初始化操作
- //
- BOOL WINAPI ServiceInit()
- {
- char str[256];
- str[0] = '0';
- int ret;
- ret = WSAStartup( winsock_version, &wsadata );
- if( ret != 0 )
- {
- DEBUGOUTPUT1( WSAERRORSTRING );
- return FALSE;
- }
- g_sockService = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
- if( g_sockService == INVALID_SOCKET )
- {
- DEBUGOUTPUT1( WSAERRORSTRING );
- return FALSE;
- }
- g_wServerPort = htons( 4813);
- g_addrServer.sin_family = AF_INET;
- g_addrServer.sin_port = g_wServerPort; // 4813
- g_addrServer.sin_addr.S_un.S_addr = htonl( INADDR_ANY ); // 监听任何地址
- ret = bind( g_sockService, (SOCKADDR*)&g_addrServer, sizeof( g_addrServer ) );
- if( ret != 0 )
- {
- DEBUGOUTPUT2( WSAERRORSTRING, "无法将套接字绑定到本地地址" );
- closesocket( g_sockService );
- return FALSE;
- }
- return TRUE;
- }
- ////////////////////////////
- //
- // 启动主服务线程
- //
- // 参数: 无
- //
- // 返回值: TRUE --- 服务线程已启动
- // FALSE --- 服务线程无法启动
- //
- BOOL WINAPI ServiceMainThreadStartup()
- {
- g_hServiceMainThreadHandle =
- CreateThread(
- NULL, // 默认的安全属性
- 0, // 默认的堆栈大小
- RCAService, // 线程函数是 RCAService
- NULL, // 无参数
- CREATE_SUSPENDED, // 线程创建后将其挂起
- &g_dwServiceMainThreadID // 将线程 ID 保存在全局变量 g_dwServiceMainThreadID 中
- );
- if( g_hServiceMainThreadHandle == 0 )
- return FALSE;
- else
- return TRUE;
-
- }
- DWORD WINAPI RCAService( PVOID pVoid )
- {
- int ret;
- static DWORD first = GetTickCount();
- static DWORD last;
- first = GetTickCount();
- if( listen( ::g_sockService, 64 ) != 0 )
- {
- PostMessage( g_hWnd, WM_DESTROY, 0, 0 );
- return 0;
- }
-
- SOCKET sockAccept;
- HANDLE hEventArray[2];
- SOCKADDR_IN clientAddr;
- int addrLen;
-
- DWORD dwTempThreadID;
- DWORD dwWaitResult;
- HANDLE hTemp;
- WSANETWORKEVENTS networkEvents;
- addrLen = sizeof( clientAddr );
- // 创建事件对象, 并将监听插座置为异步模式, 此异步模型为异步事件模型
- hEventArray[0] = CreateEvent( NULL, FALSE, FALSE, NULL );
- ret = WSAEventSelect( g_sockService, hEventArray[0], FD_ACCEPT );
- if( ret != 0 )
- {
- DEBUGOUTPUT1( WSAERRORSTRING );
- exit(0); // 危险代码 !
- }
- hEventArray[1] = g_hExitEvent;
- while( 1 )
- {
- //服务主线程开始对指定端口号进行监听,最大连接缓冲 64 个
- sockAccept = accept( g_sockService , (SOCKADDR*)&clientAddr, &addrLen );
- if( sockAccept == INVALID_SOCKET )
- {
- if( WSAEWOULDBLOCK != WSAGetLastError() )
- {
- DEBUGOUTPUT1( WSAERRORSTRING );
- exit(0);
- }
- } else
- {
- // 注: 这里必须在堆上分配内存.
- // 一个很常见的编程错误就是给一个刚创建的线程传递在栈上分配的数据
- RCAREQUESTHANDLEDATA * pData =
- (RCAREQUESTHANDLEDATA*) new BYTE[sizeof(RCAREQUESTHANDLEDATA)];
- if( pData == NULL ) // 内存不足, 很少见的情况
- {
- closesocket( sockAccept );
- continue;
- }
- pData->sockRemote = sockAccept;
- pData->dwRemoteAddress = clientAddr.sin_addr.S_un.S_addr;
- pData->dwRemotePort = clientAddr.sin_port;
- hTemp = CreateThread (
- NULL,
- 0,
- RequestHandle,
- pData,
- 0,
- &dwTempThreadID);
-
- if( hTemp != 0 )
- CloseHandle( hTemp );
- continue;
- }
- if ( (GetTickCount() - first) > TIME_LIMIT * 60 * 1000 )
- {
- PostMessage(g_hWnd, WM_DESTROY, 0, 0 );
- return 0;
- }
- dwWaitResult = WaitForMultipleObjects( 2, hEventArray, FALSE, INFINITE );
-
- // 一个网络事件发生后, 用 WSAEnumNetworkEvents 列举网络事件
- if( dwWaitResult == (WAIT_OBJECT_0 + 1) )
- {
- CloseHandle( hEventArray[0] );
- return 0;
- }
- if( dwWaitResult == WAIT_OBJECT_0 )
- {
- ret = WSAEnumNetworkEvents( g_sockService, hEventArray[0], &networkEvents );
-
- if( networkEvents.lNetworkEvents & FD_ACCEPT )
- {
- // FD_ACCEPT 事件没产生错误,将再次 accept( ... ) 以接受连接
- if( networkEvents.iErrorCode[ FD_ACCEPT_BIT ] == 0 )
- {
- // 接受连接
- continue;
- }
- else
- {
- DEBUGOUTPUT1( WSAERRORSTRING );
- }
- }
-
- }
- }// service while
- CloseHandle( hEventArray[0] );
- return 0;
- }
- VOID WINAPI OnShellIconMessage( HWND hwnd, WPARAM w, LPARAM l )
- {
- static int x;
- static int y;
- POINT p;
- // 筛选图标 ID
- switch( w )
- {
- case 1: // RCA SERVER ICON
- // 筛选消息
- switch( l )
- {
- case WM_RBUTTONUP:
- GetCursorPos( &p );
-
- // 假如选中了"退出"命令
- if( 2 == TrackPopupMenuEx( g_hShellIconMenu,
- TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD |
- TPM_BOTTOMALIGN | TPM_RIGHTALIGN, p.x, p.y ,hwnd, NULL ) )
- DestroyWindow( hwnd );
- break;
-
- }
- break;
- }
- }
- LRESULT CALLBACK MainWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
- {
-
- switch( msg )
- {
- case WM_RCASHELLICON:
- OnShellIconMessage( hwnd, wParam, lParam );
- return 0;
- case WM_CREATE:
- g_nid.cbSize = sizeof(NOTIFYICONDATA );
- g_nid.hIcon = g_hSmall;
- g_nid.hWnd = hwnd;
- lstrcpy( g_nid.szTip, "RCA SERVER v0.8 beta n使用限时:10分 n端口: 4813" );
- g_nid.uCallbackMessage = (WM_RCASHELLICON);
- g_nid.uID = 1;
- g_nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
- return Shell_NotifyIcon( NIM_ADD, &g_nid );
-
- case WM_VERSIONUPDATE:
- DWORD iCmp;
- if( CURRENT_VERSION > wParam )
- iCmp = (DWORD)VERSION_LOW;
- else if( CURRENT_VERSION == wParam )
- iCmp = (DWORD)VERSION_EQUAL;
- else
- iCmp = (DWORD)VERSION_HIGH;
-
- PostThreadMessage( lParam, WM_VERSIONUPDATE, iCmp, CURRENT_VERSION );
- if( iCmp == VERSION_HIGH ) // 正在运行的 RCA 版本较低,应该退出,现在尝试退出
- {
- DestroyWindow( hwnd );
- PostThreadMessage( lParam, WM_OLDVERSIONEXIT, 0, 0 );
- }
- return 0;
- case WM_DESTROY:
- g_bMustExit = TRUE;
- DWORD ret;
- SetEvent( g_hExitEvent );
- ret = WaitForSingleObject ( ::g_hServiceMainThreadHandle, 10000 );
- if ( ret != WAIT_OBJECT_0 )
- {
-
- MessageBox( hwnd, "严重错误", "报告", MB_ICONINFORMATION );
- exit(0);
- }
- PostQuitMessage(0);
- CloseHandle( g_hExitEvent );
- Shell_NotifyIcon( NIM_DELETE, &g_nid );
- break;
- case WM_CLOSE:
- DestroyWindow( hwnd );
- break;
- case WM_TIMER:
- if( wParam == 3 )
- DestroyWindow( hwnd );
- break;
- default:
- return DefWindowProc(hwnd, msg, wParam, lParam );
- }
- return DefWindowProc(hwnd, msg, wParam, lParam );
- }
- INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, INT )
- //int _cdecl main()
- {
- //ShellExecute( NULL, NULL, "notepad", "", NULL, SW_SHOWNORMAL );
- g_hInstance = GetModuleHandle(NULL);
-
- // 执行必须的初始化
- if( RCAInit() )
- {
- DWORD dwResult;
- //////////////////////////////////////
- //
- // CanGoon 函数进行必要的版本控制. 如果函数返回 TRUE,
- // 将表示当前这个 RCAServer 可以运行,具体说明参考 CanGoon 函数
- //
- //
- if( CanGoon( &dwResult ) )
- {
-
- g_hExitEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
- // 创建服务主线程, 线程将监听客户的请求
- if( ServiceInit() == TRUE )
- {
- if( ServiceMainThreadStartup() == TRUE )
- {
- ResumeThread( ::g_hServiceMainThreadHandle );
- } else
- goto init_failed;
- } else
- goto init_failed;
-
- SetTimer( g_hWnd, 3, TIME_LIMIT * 60 * 1000, NULL );
- MSG msg;
- while( GetMessage( &msg, NULL, 0, 0 ) )
- {
-
- TranslateMessage( &msg );
- DispatchMessage( &msg );
- }
- init_failed:
- if( g_hRunningControlSemaphore != NULL )
- ReleaseSemaphore( g_hRunningControlSemaphore, 1, NULL );
- SAFE_CLOSE_HANDLE( g_hRunningControlSemaphore );
- ServiceUninit();
- }
-
- RCAUninit();
- }
- else
- {
- //RCAUninit();
- return -1;
- }
- return 0;
- }
- ///////////////////////////////////////////////
- //
- // 函数原型: BOOL RCAInit();
- //
- // 功能: 执行时必须进行的初始化部分
- //
- // 返回值 TRUE -- 初始化成功, RCA将继续运行
- // FALSE-- 失败, RCA 必须退出
- //
- BOOL WINAPI RCAInit()
- {
-
-
-
- // 获取版本信息 ---- g_SysVer;
-
- g_SysVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx( &g_SysVer);
- switch( g_SysVer.dwPlatformId )
- {
- case VER_PLATFORM_WIN32s:// Windows 3.x , return FALSE, 不支持
- return FALSE;
-
- case VER_PLATFORM_WIN32_WINDOWS: // Win9x/ME
- if( g_SysVer.dwMinorVersion == 0 )
- lstrcpy( g_pszOS, "WIN95" );
- else
- lstrcpy( g_pszOS, "WIN98" );
- g_bCanAcceptEx = FALSE; // Win9x/ME 不支持 AcceptEx 函数
- break;
- case VER_PLATFORM_WIN32_NT: // Windows NT/2000;
- switch( g_SysVer.dwMajorVersion )
- {
- case 4:
- lstrcpy( g_pszOS, "WINNT" ); break;
- case 5:
- if( g_SysVer.dwMinorVersion > 0 )
- {
- lstrcpy( g_pszOS, "WINXP" ); break;
- }
- else
- {
- lstrcpy( g_pszOS, "WIN2K" ); break;
- }
- default:
- return FALSE;
- }
- g_bCanAcceptEx = TRUE; // Windows NT/2000 支持 套接字函数 AcceptEx
- break;
- default: // 无法识别
- return FALSE;
- }
-
- // 获取计算机名 g_pszComputerName
- DWORD dwSize = MAX_COMPUTERNAME_LENGTH +1;
- if( !GetComputerName( g_pszComputerName, &dwSize ) )
- {
- DEBUGOUTPUT1( "Call GetComputerName failed" );
- return FALSE;
- }
- DEBUGOUTPUT2( "计算机名: ", g_pszComputerName );
-
- //////////////////////////////////////////////////
- // 获系统目录路径 g_pszSystemDir;
- //
- // example:
- // for win9x c:Windowssystem
- // for winnt/2000 c:winntsystem32
- dwSize = 0;
- dwSize = GetSystemDirectory( NULL, 0 );
- if( dwSize == NULL )
- return FALSE;
- dwSize ++;
- g_pszSystemDir = NULL;
- g_pszSystemDir = new CHAR[ dwSize ];
- if( g_pszSystemDir == NULL )
- {
- DEBUGOUTPUT1( "ERROR - not enough memory" );
- return FALSE;
- }
- dwSize = GetSystemDirectory( g_pszSystemDir, dwSize );
- DEBUGOUTPUT2( "当前系统目录是: ", g_pszSystemDir );
-
-
- ////////////////////////////////////////////////////
- // 获取当前用户名
- dwSize = UNLEN +1;
- if( ! GetUserName( g_pszUserName, &dwSize ) )
- {
- DEBUGOUTPUT1( "Call GetUserName failed" );
- return FALSE;
- }
- DEBUGOUTPUT2( "当前用户名:", g_pszUserName );
-
- /////////////////////////////////////////////////////
- // 获取 Windows 目录
- //
- // example:
- // for Win9x C:Windows
- // for WinNT/2000 C:winnt
-
- dwSize = 0;
- dwSize = GetWindowsDirectory( NULL, 0 );
- if( dwSize == NULL )
- return FALSE;
- dwSize ++;
- g_pszWindowsDir = NULL;
- g_pszWindowsDir = new CHAR[ dwSize ];
- if( g_pszWindowsDir == NULL )
- {
- DEBUGOUTPUT1( "ERROR - not enough memory" );
- delete[] g_pszSystemDir;
- return FALSE;
- }
- dwSize = GetWindowsDirectory( g_pszWindowsDir, dwSize );
- DEBUGOUTPUT2( "Windows 目录是: ", g_pszWindowsDir );
- ////////////////////////////////////////////////////////
- // 获取内存信息
- //
- GlobalMemoryStatus( &g_MemoryStatus );
- g_hBig = LoadIcon( g_hInstance, MAKEINTRESOURCE(IDI_BIG) );
- g_hSmall = LoadIcon( g_hInstance, MAKEINTRESOURCE(IDI_SMALL) );
- g_hShellIconMenu = CreatePopupMenu();
- AppendMenu( g_hShellIconMenu,
- MF_STRING, 1, "打开 RCA 服务管理器(&O) (beta版未实现)" );
- AppendMenu( g_hShellIconMenu,
- MF_SEPARATOR, 0, NULL );
- AppendMenu( g_hShellIconMenu,
- MF_STRING, 2, "退出(&E)" );
-
- return TRUE;
- }
- /////////////////////////////////////////////////////////////
- //
- // 原型: BOOL RCAUninit();
- //
- // 功能: 程序退出时,进行清除操作
- //
- // 返回值: 返回 TRUE 表示成功清除, FALSE 表示失败
- //
- BOOL WINAPI RCAUninit()
- {
- DestroyMenu( g_hShellIconMenu );
-
- SAFE_DELETE_ARRAY( g_pszSystemDir );
- SAFE_DELETE_ARRAY( g_pszWindowsDir );
- return TRUE;
- }
- //////////////////////////////////////////////////////////////
- //
- // 原型: void OutputAddr( unsigned int u );
- //
- // 功能: 在控制台输出一个描述 IP 地址的无符号整数
- //
- // 注: 这个无符号整数已经被字节反序编码过的,
- // 输出时最低字节将被先输出,最高字节最后输出
- //
- // 返回值: 无
- //
- void WINAPI OutputAddr( unsigned int u )
- {
- cout<< ((u & 0xFF000000) >> 24) << "."
- << ((u & 0x00ff0000) >> 16) << "."
- << ((u & 0x0000ff00) >> 8) << "."
- << ((u & 0x000000ff) >> 0) ;
- }
- ////////////////////////////////////////////////////////////
- //
- // CanGoon 函数进行必要的版本控制. 如果函数返回 TRUE,
- // 将表示当前这个 RCAServer 可以运行,这将发生在以下两种情况:
- //
- // 1. 当前系统没有任何 RCAServer 在运行,这时本 RCAServer 将顺利运行。
- // 这是通过一个 Semaphore 对象对正在运行的任何版本的 RCAServer 进行控制实现的
- // 2. 首先说明一点,Semaphore 对象将保证当前系统绝不会有三个或三个以上的无论什么版本的RCAServer 同时运行
- // 若当前系统有一个 RCAServer 在运行, CanGoon 将试图查找正运行的 RCAServer 的主窗口, 找不到将退出
- // 找到后会给窗口 Post 一个 WM_VERSIONUPDATE 消息, 以校验两个 RCAServer 的版本到底谁年轻谁 TMD 老该死
- //
- // 几种情况:
- // 更早运行的 RCAServer 版本低, 并且没有活动的连接,更早运行的 RCAServer 版本将退出
- // 新版本的将继续初始化并替代老版本的执行 RCP 服务
- //
- // 更早运行的 RCAServer 版本低,但有活动的连接,新版本的将等待一段时间(不长,几秒钟),若这
- // 若这段时间内老版本的所有连接已关闭, 老的将退出,由新的替代运行,若这段时间连接仍未关闭,
- // 新的高版本的 RCAServer 将退出
- //
- // 更早运行的 RCAServer 版本高, 简单, 新的低版本 RCAServer 直接退出.
- //
- // 返回值: TRUE --- 此 RCAServer 实例将可以继续运行
- // FALSE --- 此 RCAServer 实例必须退出
- //
- BOOL WINAPI CanGoon( DWORD * result )
- {
- //
- BOOL bAlreadyRun = FALSE;
- DWORD dwWaitResult;
- g_hRunningControlSemaphore =
- CreateSemaphore( NULL, 2, 2, RCA_RUNNING_CONTROL_SEMAPHORE_NAME );
- if( !g_hRunningControlSemaphore )
- return FALSE;
- if( GetLastError() == ERROR_ALREADY_EXISTS ) // 信标对象已经存在, 将试图找
- { // RCA SERVER 主窗口, 并进行版本更新
- dwWaitResult = WaitForSingleObject( g_hRunningControlSemaphore, 500 );
- if( dwWaitResult == WAIT_TIMEOUT )
- {
-
- SAFE_CLOSE_HANDLE( g_hRunningControlSemaphore );
- return FALSE;
- }
- bAlreadyRun = TRUE;
- HWND oldRCAMainWnd = FindWindow( SERVER_WINDOW_CLASSNAME,
- SERVER_WINDOW_CAPTIONNAME);
- if( !oldRCAMainWnd ) // 如果找不到,先休眠 2 秒, 再次试图查找窗口
- Sleep(2000);
- oldRCAMainWnd = FindWindow( SERVER_WINDOW_CLASSNAME,
- SERVER_WINDOW_CAPTIONNAME );
- if( !oldRCAMainWnd ) // 如果还找不到,返回 FALSE,必须退出,信标对象无法准确定位
- return FALSE;
- PostMessage( oldRCAMainWnd, WM_VERSIONUPDATE,
- CURRENT_VERSION, GetCurrentThreadId() );
- MSG msg;
- int count = 4; // 循环 4 次
- while( count ) // 等待正在工作的 RCA 回递版本更新的消息
- {
- Sleep( 500 ); //
- if( PeekMessage( &msg, NULL, WM_VERSIONUPDATE, WM_VERSIONUPDATE, PM_REMOVE ) )
- {
- DWORD iCmp = msg.wParam; // wParam 为版本比较结果信息
- WORD oldVersion = LOWORD(msg.lParam); // lParam 的低字为正在工作的 RCA 版本
- // 正在工作的RCA 是否可以退出, 假如正在工作的 RCA 版本低,
- // 但有连接在工作中,则为 FALSE,即无法退出
- BOOL bOldRCARunning = (BOOL)HIWORD(msg.lParam);
-
- if( iCmp == VERSION_LOW ) // 本版本低, 必须退出
- {
- ReleaseSemaphore( g_hRunningControlSemaphore , 1, NULL );
- SAFE_CLOSE_HANDLE( g_hRunningControlSemaphore );
- return FALSE;
- } else if( iCmp == VERSION_EQUAL ) // 正在工作的版本与本版本相同,也退出
- {
- ReleaseSemaphore( g_hRunningControlSemaphore, 1, NULL );
- SAFE_CLOSE_HANDLE( g_hRunningControlSemaphore );
- return FALSE;
- } else if( iCmp == VERSION_HIGH ) // 本版本高,可以开始更新
- {
- BOOL bOldRCAExit = FALSE;
- count = 4;
- while( count )
- {
- Sleep( 500 );
- if( PeekMessage( &msg, NULL, WM_OLDVERSIONEXIT, WM_OLDVERSIONEXIT, PM_REMOVE ) )
- {
- bOldRCAExit = TRUE;
- break;
- } else
- count-- ;
- }
- if( bOldRCAExit == FALSE ) // 虽然正在工作的版本低,但无法退出(有连接等)
- {
- ReleaseSemaphore( g_hRunningControlSemaphore, 1, NULL );
- SAFE_CLOSE_HANDLE( g_hRunningControlSemaphore );
- return FALSE;
- }
- break; // 跳出版本更新的消息通信循环
- }
-
- } else
- count --;
- }
- }
- WNDCLASSEX wcex;
- wcex.cbClsExtra = 0;
- wcex.cbSize = sizeof( wcex );
- wcex.cbWndExtra = 0;
- wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW );
- wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
- wcex.hIcon = g_hBig;
- wcex.hIconSm = g_hSmall;
- wcex.hInstance = g_hInstance;
- wcex.lpfnWndProc = MainWndProc;
- wcex.lpszClassName = SERVER_WINDOW_CLASSNAME;
- wcex.lpszMenuName = NULL;
- wcex.style = CS_HREDRAW | CS_VREDRAW;
- if( !RegisterClassEx( &wcex ) )
- {
- RCAUninit();
- return -1;
- }
- g_hWnd = CreateWindow( SERVER_WINDOW_CLASSNAME, SERVER_WINDOW_CAPTIONNAME,
- WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
- CW_USEDEFAULT, 400, 300,
- NULL, NULL, g_hInstance, NULL );
- if( g_hWnd == NULL )
- {
- RCAUninit();
- return -1;
- }
- ShowWindow( g_hWnd, SW_HIDE);
- UpdateWindow( g_hWnd );
-
- return TRUE;
- }
- /* // 接收请求头
- while ( nLeft > 0 )
- {
- ret = recv( sockRemote, &(headBuffer[i]), nLeft, 0 );
- if( ret == SOCKET_ERROR )
- {
- if( WSAGetLastError() != WSAEWOULDBLOCK )
- {
- bRecv = FALSE;
- break;
- }
- }
- else
- {
- nLeft -= ret;
- i += ret;
- continue;
- }
- DWORD dw = WaitForSingleObject( hEvent, INFINITE );
- WSANETWORKEVENTS netEvents;
- ret = WSAEnumNetworkEvents( sockRemote, hEvent, &netEvents );
- if( ret != 0 )
- {
- DEBUGOUTPUT1( WSAERRORSTRING );
- bRecv = FALSE;
- break;
- }
- if( netEvents.lNetworkEvents & FD_READ )
- {
- if( netEvents.iErrorCode[FD_READ_BIT] != 0 )
- {
- DEBUGOUTPUT1( WSAERRORSTRING );
- bRecv = FALSE;
- break;
-
- } else
- continue;
- }
- if( netEvents.lNetworkEvents & FD_CLOSE )
- {
- bRecv = FALSE;
- break;
- }
- } // recv while
- */