www.pudn.com > gamedata.rar > serverlogin.c


// serverlogin.cpp : Defines the entry point for the application. 
// 
//#define WIN32_LEAN_AND_MEAN 
#include "stdafx.h" 
#include "resource.h" 
 
#define MAX_CHAR      1024 
 
struct logindata 
{ 
    SOCKET      sock;                     
    char        InBuffer[4];         // 输入 
    OVERLAPPED  ovIn;          
    int         nOutBufIndex;        
    char        OutBuffer[MAXCHAR];  // 输出 
    OVERLAPPED  ovOut; 
    DWORD       dwWritten; 
 
	char        id[32]; 
	char        password[32]; 
	int         vip; 
	char        idcard[32]; 
}; 
 
struct GAMESERVERINFO 
{ 
	int  index; 
	char name[50]; 
	char ip[50]; 
	int  port; 
}; 
 
#define MAX_LOADSTRING 100 
 
TBBUTTON tbButtons[] =  
{ 
	{ 0, IDM_STARTSERVICE,	TBSTATE_ENABLED,	TBSTYLE_BUTTON, 0L, 0}, 
	{ 1, IDM_STOPSERVICE,	TBSTATE_ENABLED,	TBSTYLE_BUTTON, 0L, 0},	 
	{ 2, IDM_FONTCOLOR,		TBSTATE_ENABLED,	TBSTYLE_BUTTON, 0L, 0}, 
	{ 3, IDM_BACKCOLOR,		TBSTATE_ENABLED,	TBSTYLE_BUTTON, 0L, 0}, 
}; 
 
TCHAR szTitle[MAX_LOADSTRING];								// The title bar text 
TCHAR szWindowClass[MAX_LOADSTRING];								// The title bar text 
HANDLE ghCompletionPort; 
 
char szLoginInfo[2048]; 
struct GAMESERVERINFO pServerInfo[64]; 
struct optiondata option; 
 
// Foward declarations of functions included in this code module: 
ATOM				MyRegisterClass(HINSTANCE hInstance); 
BOOL				InitInstance(HINSTANCE, int); 
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM); 
LRESULT CALLBACK	About(HWND, UINT, WPARAM, LPARAM); 
DWORD WINAPI        ServerThread(LPVOID pVoid); 
 
void Encode2(BYTE buf[2], int data) 
{ 
	buf[0] = (data / 256) % 256; 
	buf[1] = data % 256; 
} 
 
void GetExeDir(char* szExeDir) 
{ 
	char buf[MAX_PATH]; 
	char *cptr; 
 
	GetModuleFileNameA(NULL, buf, MAX_PATH); 
 
	//move pointer to end of string 
	cptr = buf + lstrlenA(buf); 
 
	//find the end of the path 
	do 
	{ 
		cptr--; 
	} while (*cptr != '\\'); 
	cptr++; 
	*cptr='\0'; 
	strcpy(szExeDir,buf); 
} 
 
BOOL loaddata(char *szBuf) 
{ 
	FILE *fp; 
	char szfilepath[256], buf1[256]; 
	char szfilename[256]; 
	szBuf[0]=0; 
 
	GetExeDir(szfilepath); 
 
	sprintf(szfilename, "%slogindata\\logininfo.inf", szfilepath); 
 
	if((fp=fopen(szfilename, "r")) != NULL )		 
	{ 
		while( fgets( buf1, sizeof( buf1), fp) != NULL )	 
		{ 
			strcat( szBuf, buf1); 
		} 
		fclose( fp); 
	}else	 
		return FALSE; 
 
	return TRUE; 
} 
 
BOOL loadserverdata() 
{ 
	FILE *fp; 
 
	int number, i; 
 
	char szfilepath[256]; 
	char szfilename[256]; 
	char n1[20], n2[20], n3[20], n4[20]; 
 
	GetExeDir(szfilepath); 
 
	sprintf(szfilename, "%slogindata\\server.inf", szfilepath); 
 
	fp = fopen(szfilename, "r"); 
 
	if(fp != NULL)  
	{ 
		fscanf(fp, "数量 = %s\n", n1); 
		number = atol(n1); 
 
		for (i=0;ivip,       0,  &Indexind);      //  
			//	SQLGetData(hstmt, 17, SQL_C_TINYINT, &loginglobals->time,      0,  &Indexind); 
				SQLGetData(hstmt, 12, SQL_C_CHAR,    login->idcard,     50,  &Indexind);     // 身份证 
 
			//	sprintf(tmp1, "%d", loginglobals->vip); 
			//	MessageBoxA(NULL, tmp1, "", 0); 
				strcpy(login->id, id); 
				strcpy(login->password, psd); 
 
				retval = TRUE; 
			} 
		} 
		else  
		{ 
	/*		if( DisplayErrorMsg(filename, hstmt) == -1 )  
			{ 
				m_AccountDB.Close(); 
				if( !m_AccountDB.IsOpen() )  
				{ 
					ReConnectODBC(&m_AccountDB, m_strDSN, m_strUID, m_strPWD); 
					return FALSE; 
				} 
			} 
			*/ 
			retval = FALSE; 
		} 
	 
		SQLFreeHandle((SQLSMALLINT)SQL_HANDLE_STMT,hstmt); 
	} 
	else   
		return FALSE; 
 
	return retval; 
} 
 
int userconnect(struct logindata *login, char *buf, int len) 
{ 
	char *tmp; 
	int t1, t2, i, ret; 
	BYTE b[2];	 
    // 00 01 02 03 04 05 06 07 08 
	// 0C 80 05 00 10 00 00 00 01  
 
	if (((int)(BYTE)buf[4] > 64) || ((int)(BYTE)buf[4] <= 0)) { return -1; } 
	 
   
//	MessageBox(NULL, loginglobals->m_id,pServerInfo[(int)(BYTE)buf[4]-1].ip,0); 
	t1 = strlen(login->id); 
	t2 = strlen(pServerInfo[(int)(BYTE)buf[4]-1].ip); 
	// 64 80 22 00 0B 00 7A 68 65 6E 67 64 61 6E 69 61 6E 01 0E 00 32 31 39 2E 31 35 33 2E 32 38 2E 31 33 36 C8 32 00 00 
	// 64 80 1B 00 09 00 67 6F 75 7A 61 69 64 75 69       01 09 00 31 32 37 2E 30 2E 30 2E 31                FA 32 00 00  
 
	tmp = (char*)malloc(t1 + t2 + 13); 
 
	tmp[0] = (char)0x64; 
	tmp[1] = (char)0x80; 
	tmp[2] = (char)(BYTE)(t1 + t2 + 13 - 4); 
	tmp[3] = (char)0x00; 
	tmp[4] = (char)(BYTE)t1; 
	tmp[5] = (char)0x00; 
 
	for (i=0; iid[i]; 
	} 
 
	tmp[6+t1] = (char)0x01; 
	tmp[7+t1] = (char)(BYTE)t2; 
	tmp[8+t1] = (char)(BYTE)0x00; 
 
	for (i=0; isock, tmp, t1 + t2 + 13, 0); 
 
//	free(tmp); 
 
	return ret; 
} 
 
int sendwelcomeinfo(struct logindata  *login) 
{ 
	char *tmp, TIME[64]; 
	int t1, t2, i, ret; 
	BYTE n[2]; 
 
/*	if (time == 0) { closesocket(s); return; } 
 
	if (time <= 10)  
	{ 
		sprintf(TIME, "您还有%d小时 游戏时间 请即时冲卡", time); 
	} 
	else 
	{ 
		sprintf(TIME, "您还有%d小时 游戏时间", time); 
	} 
*/ 
	if (login->vip == 0) 
	//	sprintf(TIME, "您剩余的游戏时间为%d小时%d分钟.", (loginglobals->time / (loginglobals->time % 360)), (loginglobals->time % 6)); 
	    sprintf(TIME, "测试用户."); 
	else if (login->vip == 1) 
		sprintf(TIME, "您剩余的游戏时间为天.");	 
	else if (login->vip == 2)	 
		sprintf(TIME, "免费时间."); 
	else if (login->vip == 3)	 
		sprintf(TIME, "您是永久免费会员."); 
	else if (login->vip == 4) 
		sprintf(TIME, "GM 登陆."); 
	else 
		sprintf(TIME, ""); 
 
 
	t1 = strlen(TIME); 
	t2 = strlen(szLoginInfo); 
 
	if (strcmp(TIME, "") == 0) t1 = 0; 
 
	tmp = (char*)malloc(t1 + t2 + 6 + 5); 
 
	tmp[0] = (char)0x01; 
	tmp[1] = (char)0x80; 
	Encode2(n, t1 + t2 + 6); 
	tmp[2] = (char)n[1]; 
	tmp[3] = (char)n[0]; 
	tmp[4] = (char)0x00; 
 
	tmp[5] = (char)0x01; 
 
	tmp[6] = (char)(BYTE)(t1); 
	tmp[7] = (char)0x00; 
 
	for (i=0; isock, tmp, t1 + t2 + 6 + 5, 0); 
 
//	free(tmp); 
 
	return ret; 
} 
 
int userstatus(struct logindata *login, char *buf, int len) 
{ 
	int i, ret; 
	char *id; 
	char tmp[2]; 
	char error_tmp[5]; 
 
	id = (char*)malloc((int)(BYTE)buf[4]); 
 
	strcpy(id, ""); 
 
	for (i=0; i<(int)(BYTE)buf[4]; i++) 
	{ 
		sprintf(tmp, "%c", buf[6 + i]);	 
		strcat(id, tmp); 
	} 
 
//	try 
//	{ 
		// 帐号认证 
		if (checkaccount(login, id, "")) 
		{ 
			strcpy(login->id, id); 
			sendwelcomeinfo(login); 
		} 
		else		 
		{ 
			// 01 80 01 00 01 
			error_tmp[0] = (char)0x01; 
			error_tmp[1] = (char)0x80; 
			error_tmp[2] = (char)0x01; 
			error_tmp[3] = (char)0x00; 
			error_tmp[4] = (char)0x01; 
 
			ret = send(login->sock, error_tmp, 5, 0); 
		} 
		 
//	} 
//	catch(...)///捕捉异常 
//	{ 
//		return -1; 
//	} 
 
 //   free(id); 
 
	return 0; 
} 
 
void ReadPack(struct logindata *login) 
{ 
    int     i = 0; 
    BOOL    bResult; 
    int     err; 
    DWORD     numRead; 
 
    while (++i) 
    { 
        // 读取一个单字符 
        bResult = ReadFile( 
                    (HANDLE)login->sock, 
                    login->InBuffer, 
                    1, 
                    &numRead, 
                    &login->ovIn); 
 
        // 这里,等待一个信息包. 
        if (bResult) 
		{ 
            return; 
		} 
 
        err = GetLastError(); 
 
        // 获取状态,这里并不代表错误 
        if (err == ERROR_IO_PENDING) 
            return; 
 
        if ( err == ERROR_INVALID_USER_BUFFER || 
             err == ERROR_NOT_ENOUGH_QUOTA || 
             err == ERROR_NOT_ENOUGH_MEMORY ) 
        { 
            if (i == 5)  
            { 
                Sleep(50);  // 等待并重试 
                continue; 
            } 
 
      //      printf("IssueRead -系统溢出连接池"); 
        } 
		 
 
        break; 
    } 
	 
 
  //  fprintf(stderr, "IssueRead - 读信息失败.\n"); 
	 
} 
 
// 
// 确保我们运行在正确的版本下 Windows NT (3.51, 4.0, or later) 
// 
BOOL CheckOsVersion() 
{ 
    OSVERSIONINFO   ver; 
    BOOL            bResult; 
 
    ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 
 
    bResult = GetVersionEx((LPOSVERSIONINFO) &ver); 
 
    if ((!bResult) || 
         (ver.dwPlatformId != VER_PLATFORM_WIN32_NT)) 
    { 
        MessageBox(NULL, "you must have windows NT 3.51 or later\n", "信息", 0); 
 
		return FALSE; 
    } 
	return TRUE; 
} 
 
DWORD WINAPI ThreadFunc(LPVOID pVoid) 
{ 
 
    BOOL    bResult; 
    DWORD   dwNumRead; 
    struct logindata *pCntx; 
    LPOVERLAPPED lpOverlapped; 
 
    UNREFERENCED_PARAMETER(pVoid); 
 
    // 无限循环从 I/O completion port 获取信息. 
    for (;;) 
    { 
        bResult = GetQueuedCompletionStatus( 
               ghCompletionPort, 
               &dwNumRead, 
               &(DWORD)pCntx, 
               &lpOverlapped, 
               INFINITE 
            ); 
 
        if (bResult == FALSE 
            && lpOverlapped == NULL) 
        { 
//            FatalError( 
  //              "ThreadFunc - GetQueuedCompletionStatus()错误.\n"); 
        } 
        else if (bResult == FALSE 
            && lpOverlapped != NULL) 
        { 
			CloseHandle(pCntx->ovOut.hEvent); 
            closesocket(pCntx->sock); 
        } 
 
        else if (dwNumRead == 0) 
        { 
			CloseHandle(pCntx->ovOut.hEvent); 
            closesocket(pCntx->sock); 
        } 
 
        else 
        { 
            char *pch = &pCntx->OutBuffer[pCntx->nOutBufIndex++]; 
            *pch++ = pCntx->InBuffer[0]; 
//            *pch = '\0';   
 
		//	strcpy(tmp,""); 
		//	sprintf(tmp, "%2.2X\n", (BYTE)pCntx->InBuffer[0]); 
		//	MessageBox(NULL, tmp, "",0); 
 
			// 00 80 3A 00 09 00 31 31 31 31 31 31 31 31 31 19 46 00 00 B4 5E 00 00 9E 61 11 47 EC FE B4 F6 14 13 1E 43 74 40 CB 03 06 D0 34 57 11 00 31 33 2E 39 64 2E 63 39 2E 38 38 2E 66 34 2E 62 61  
			if(((BYTE)pCntx->OutBuffer[0] == 0x00) && ((BYTE)pCntx->OutBuffer[1] == 0x80) &&  
				((BYTE)pCntx->OutBuffer[2] + (BYTE)pCntx->OutBuffer[3] * 256 + 4 == pCntx->nOutBufIndex) && (pCntx->nOutBufIndex>=8)) 
			{ 
				userstatus(pCntx, pCntx->OutBuffer, pCntx->nOutBufIndex); 
 
				memcpy(pCntx->OutBuffer, 0, 0); 
				pCntx->nOutBufIndex = 0; 
			} 
			else if(((BYTE)pCntx->OutBuffer[0] == 0x0C) && ((BYTE)pCntx->OutBuffer[1] == 0x80) &&  
				((BYTE)pCntx->OutBuffer[2] + (BYTE)pCntx->OutBuffer[3] * 256 + 4 == pCntx->nOutBufIndex) && (pCntx->nOutBufIndex>=8)) 
			{ 
				userconnect(pCntx, pCntx->OutBuffer, pCntx->nOutBufIndex); 
 
				memcpy(pCntx->OutBuffer, 0, 0); 
				pCntx->nOutBufIndex = 0; 
			} 
            // 开始读取 
            ReadPack(pCntx); 
        } 
    } 
 
    return 0; 
} 
 
 
void CreateWorkerThreads() 
{ 
    SYSTEM_INFO  sysinfo; 
    DWORD        dwThreadId; 
    DWORD        dwThreads; 
    DWORD        i; 
 
    GetSystemInfo(&sysinfo); 
    dwThreads = sysinfo.dwNumberOfProcessors * 2 + 2; 
 
    for (i=0; isock = newsocket; 
        pKey->ovOut.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//为写信息包过程设置(事件对象) event . 
        pKey->ovOut.hEvent = (HANDLE)((DWORD)pKey->ovOut.hEvent | 0x1);  
     
        CreateIoCompletionPort(                                   //为请求绑定端口 
                (HANDLE)newsocket, 
                ghCompletionPort, 
                (DWORD)pKey,    
                0); 
 
		sprintf(tmp, "%d.%d.%d.%d 连接", clientAddress.sin_addr.S_un.S_un_b.s_b1,  
					clientAddress.sin_addr.S_un.S_un_b.s_b2, 
					clientAddress.sin_addr.S_un.S_un_b.s_b3, 
					clientAddress.sin_addr.S_un.S_un_b.s_b4); 
 
		InsertLogMsg(tmp); 
 
        ReadPack(pKey);                                          // 完成第一次读操作 
    } 
//	uninstallsqldata(); 
	return 0; 
} 
 
int APIENTRY WinMain(HINSTANCE hInstance, 
                     HINSTANCE hPrevInstance, 
                     LPSTR     lpCmdLine, 
                     int       nCmdShow) 
{ 
 	// TODO: Place code here. 
	MSG msg; 
	HACCEL hAccelTable; 
	char szfilepath[256]; 
	char szfilename[256]; 
	char tmp[24]; 
	// Initialize global strings 
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 
	LoadString(hInstance, IDC_SERVERLOGIN, szWindowClass, MAX_LOADSTRING); 
 
	GetExeDir(szfilepath); 
 
	sprintf(szfilename, "%sserverlogin.ini", szfilepath); 
 
	GetPrivateProfileString("ODBC",   "ACCOUNT_DSN",      "", option.accountdsn,       24, szfilename); 
	GetPrivateProfileString("ODBC",   "ACCOUNT_UID",      "", option.accountuid,       24, szfilename); 
	GetPrivateProfileString("ODBC",   "ACCOUNT_PWD",      "", option.accountpwd,       24, szfilename); 
	GetPrivateProfileString("ODBC",   "LOG_DSN",          "", option.logdsn,           24, szfilename); 
	GetPrivateProfileString("ODBC",   "LOG_UID",          "", option.loguid,           24, szfilename); 
	GetPrivateProfileString("ODBC",   "LOG_PWD",          "", option.logpwd,           24, szfilename); 
	GetPrivateProfileString("SERVER", "PORT",             "", tmp,                     24, szfilename); 
	option.port = atoi(tmp); 
 
	if (!CheckOsVersion()) 
		return 0; 
 
	MyRegisterClass(hInstance); 
 
	if (!InitInstance (hInstance, nCmdShow))  
	{ 
		return FALSE; 
	} 
 
	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_SERVERLOGIN); 
 
    //    CloseHandle(hThread); 
	// Main message loop: 
	while (GetMessage(&msg, NULL, 0, 0))  
	{ 
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))  
		{ 
			TranslateMessage(&msg); 
			DispatchMessage(&msg); 
		} 
	} 
 
	return msg.wParam; 
} 
 
void SwitchMenuItem(BOOL fFlag) 
{ 
	HMENU hMainMenu = GetMenu(option.hMainWnd); 
	HMENU hMenu = GetSubMenu(hMainMenu, 0); 
 
	if (fFlag) 
	{ 
		EnableMenuItem(hMenu, IDM_STARTSERVICE, MF_GRAYED|MF_BYCOMMAND); 
		EnableMenuItem(hMenu, IDM_STOPSERVICE, MF_ENABLED|MF_BYCOMMAND); 
 
		SendMessage(option.hToolBar, TB_SETSTATE, (WPARAM)IDM_STARTSERVICE, (LPARAM)MAKELONG(TBSTATE_INDETERMINATE, 0)); 
		SendMessage(option.hToolBar, TB_SETSTATE, (WPARAM)IDM_STOPSERVICE, (LPARAM)MAKELONG(TBSTATE_ENABLED, 0)); 
 
		InsertLogMsg("开始服务"); 
	} 
	else 
	{ 
		EnableMenuItem(hMenu, IDM_STARTSERVICE, MF_ENABLED|MF_BYCOMMAND); 
		EnableMenuItem(hMenu, IDM_STOPSERVICE, MF_GRAYED|MF_BYCOMMAND); 
 
		SendMessage(option.hToolBar, TB_SETSTATE, (WPARAM)IDM_STARTSERVICE, (LPARAM)MAKELONG(TBSTATE_ENABLED, 0)); 
		SendMessage(option.hToolBar, TB_SETSTATE, (WPARAM)IDM_STOPSERVICE, (LPARAM)MAKELONG(TBSTATE_INDETERMINATE, 0)); 
 
		InsertLogMsg("停止服务"); 
	} 
} 
 
int AddNewLogMsg() 
{ 
	LV_ITEM		lvi; 
	TCHAR		szText[64]; 
 
	int nCount = ListView_GetItemCount(option.hLogMsgWnd); 
 
	if (nCount >= 50) 
	{ 
		ListView_DeleteItem(option.hLogMsgWnd, 0); 
		nCount--; 
	} 
 
	lvi.mask		= LVIF_TEXT; 
	lvi.iItem		= nCount; 
	lvi.iSubItem	= 0; 
	 
	_tstrdate(szText); 
 
	lvi.pszText = szText; 
	 
	ListView_InsertItem(option.hLogMsgWnd, &lvi); 
 
	_tstrtime(szText); 
 
	ListView_SetItemText(option.hLogMsgWnd, nCount, 1, szText); 
 
	return nCount; 
} 
 
void InsertLogMsg(char *lpszMsg) 
{ 
	int nCount = AddNewLogMsg(); 
 
	if (strlen(lpszMsg) <= 256) 
	{ 
		ListView_SetItemText(option.hLogMsgWnd, nCount, 2, lpszMsg); 
		ListView_Scroll(option.hLogMsgWnd, 0, 8); 
	} 
} 
 
void SetFontColor() 
{ 
	CHOOSECOLOR color; 
	static COLORREF acrCustClr[16];  
 
	memset( &color, 0, sizeof( color ) ); 
	color.hwndOwner		= option.hMainWnd; 
	color.lStructSize	= sizeof( color ); 
	color.Flags			= CC_FULLOPEN | CC_RGBINIT; 
	color.rgbResult		= ListView_GetTextColor(option.hLogMsgWnd ); 
	color.lpCustColors	= acrCustClr; 
 
	if ( !ChooseColor( &color ) ) 
		return; 
 
	ListView_SetTextColor(option.hLogMsgWnd, color.rgbResult ); 
 
	InvalidateRect(option.hLogMsgWnd, NULL, TRUE ); 
} 
 
 
void SetBackColor() 
{ 
	CHOOSECOLOR color; 
	static COLORREF acrCustClr[16];  
 
	memset( &color, 0, sizeof( color ) ); 
	color.hwndOwner		= option.hMainWnd; 
	color.lStructSize	= sizeof( color ); 
	color.Flags			= CC_FULLOPEN | CC_RGBINIT; 
	color.rgbResult		= ListView_GetBkColor(option.hLogMsgWnd ); 
	color.lpCustColors	= acrCustClr; 
 
	if ( !ChooseColor( &color ) ) 
		return; 
 
	ListView_SetTextBkColor(option.hLogMsgWnd, color.rgbResult ); 
	ListView_SetBkColor(option.hLogMsgWnd, color.rgbResult ); 
 
	InvalidateRect(option.hLogMsgWnd, NULL, TRUE ); 
} 
 
ATOM MyRegisterClass(HINSTANCE hInstance) 
{ 
    WNDCLASS  wc; 
 
    wc.style            = CS_GLOBALCLASS|CS_HREDRAW|CS_VREDRAW; 
    wc.lpfnWndProc      = (WNDPROC)WndProc; 
    wc.cbClsExtra       = 0; 
    wc.cbWndExtra       = 0; 
    wc.hIcon            = LoadIcon((HINSTANCE)hInstance, MAKEINTRESOURCE(IDI_SERVERLOGIN)); 
    wc.hInstance        = (HINSTANCE)hInstance; 
    wc.hCursor          = LoadCursor(NULL, IDC_ARROW); 
    wc.hbrBackground    = (HBRUSH)(COLOR_WINDOW + 1); 
    wc.lpszMenuName     = MAKEINTRESOURCE(IDR_MAINMENU); 
    wc.lpszClassName    = _LOGIN_SERVER_CLASS; 
 
	return RegisterClass(&wc); 
} 
 
// 
//   FUNCTION: InitInstance(HANDLE, int) 
// 
//   PURPOSE: Saves instance handle and creates main window 
// 
//   COMMENTS: 
// 
//        In this function, we save the instance handle in a global variable and 
//        create and display the main program window. 
// 
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 
{ 
	DWORD dwStyle; 
	int i; 
  	int	nStatusPartsWidths[_NUMOFMAX_STATUS_PARTS]; 
	int nCnt; 
	RECT rcMainWnd, rcToolBar, rcStatusBar; 
	LV_COLUMN	lvc; 
	char		szText[64]; 
	INITCOMMONCONTROLSEX icex; 
 
	option.hInst = hInstance; 
	dwStyle = WS_THICKFRAME | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; 
 
//	OleInitialize(NULL); 
 
	icex.dwSize = sizeof(INITCOMMONCONTROLSEX); 
	icex.dwICC = ICC_LISTVIEW_CLASSES | ICC_BAR_CLASSES | ICC_INTERNET_CLASSES | ICC_TAB_CLASSES; 
 
	InitCommonControlsEx(&icex); 
 
    option.hMainWnd = CreateWindowEx(0, _LOGIN_SERVER_CLASS, _LOGIN_SERVER_TITLE,  
							dwStyle | WS_VISIBLE, 
							CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,                  
							NULL, NULL, (HINSTANCE)hInstance, NULL); 
 
	option.hToolBar = CreateToolbarEx(option.hMainWnd, WS_CHILD|CCS_TOP|WS_VISIBLE|SBS_SIZEGRIP, 
									_IDW_TOOLBAR, sizeof(tbButtons) / sizeof(TBBUTTON), (HINSTANCE)hInstance, IDB_TOOLBAR, 
									(LPCTBBUTTON)&tbButtons, sizeof(tbButtons) / sizeof(TBBUTTON), 
									_BMP_CX, _BMP_CY, _BMP_CX, _BMP_CY, sizeof(TBBUTTON)); 
 
	GetClientRect(option.hMainWnd, &rcMainWnd); 
	GetWindowRect(option.hToolBar, &rcToolBar); 
 
	option.hStatusBar = CreateWindowEx(0L, STATUSCLASSNAME, _T(""), WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP, 
									0, rcMainWnd.bottom - _STATUS_HEIGHT, (rcMainWnd.right - rcMainWnd.left), _STATUS_HEIGHT, option.hMainWnd, (HMENU)_IDW_STATUSBAR, option.hInst, NULL); 
	nCnt = 0; 
	 
	for (i = _NUMOFMAX_STATUS_PARTS - 1; i >= 0; i--) 
		nStatusPartsWidths[nCnt++] = (rcMainWnd.right - rcMainWnd.left) - (90 * i); 
 
	SendMessage(option.hStatusBar, SB_SETPARTS, _NUMOFMAX_STATUS_PARTS, (LPARAM)nStatusPartsWidths); 
	SendMessage(option.hStatusBar, SB_SETTEXT, MAKEWORD(0, 0), (LPARAM)_TEXT("服务器关闭")); 
//	SendMessage(option.hStatusBar, SB_SETTEXT, MAKEWORD(1, 0), (LPARAM)_TEXT("在线 0 人")); 
//	SendMessage(option.hStatusBar, SB_SETTEXT, MAKEWORD(2, 0), (LPARAM)_TEXT("怪物 0 个")); 
//	SendMessage(option.hStatusBar, SB_SETTEXT, MAKEWORD(3, 0), (LPARAM)_TEXT("矿石 0 个")); 
 
	GetWindowRect(option.hStatusBar, &rcStatusBar); 
 
    option.hLogMsgWnd = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, _TEXT(""),  
							WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_REPORT|LVS_EDITLABELS, 
							0, (rcToolBar.bottom - rcToolBar.top) - 2, (rcMainWnd.right - rcMainWnd.left),  
							(rcMainWnd.bottom - rcMainWnd.top) - (rcToolBar.bottom - rcToolBar.top) + 2 
							- (rcStatusBar.bottom - rcStatusBar.top), 
							option.hMainWnd, NULL, (HINSTANCE)hInstance, NULL); 
 
	ListView_SetExtendedListViewStyleEx(option.hLogMsgWnd, 0, LVS_EX_FULLROWSELECT); 
 
	lvc.mask	= LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; 
	lvc.fmt		= LVCFMT_LEFT; 
	lvc.cx		= 100; 
	lvc.pszText	= szText; 
 
	for (i = 0; i < 3; i++) 
	{ 
		lvc.iSubItem = i; 
		LoadString((HINSTANCE)hInstance, IDS_LVS_LABEL1 + i, szText, sizeof(szText)); 
		 
		ListView_InsertColumn(option.hLogMsgWnd, i, &lvc); 
	} 
	 
	ListView_SetColumnWidth(option.hLogMsgWnd, 2, 220); 
 
	SendMessage(option.hToolBar, TB_SETSTATE, (WPARAM)IDM_STOPSERVICE, (LPARAM)MAKELONG(TBSTATE_INDETERMINATE, 0)); 
 
	ShowWindow(option.hMainWnd, SW_SHOW); 
	UpdateWindow(option.hMainWnd); 
 
	InvalidateRect(option.hMainWnd, NULL, TRUE); 
 
	return TRUE; 
} 
 
void OnCommand(WPARAM wParam, LPARAM lParam) 
{ 
	HANDLE hThread; 
	DWORD  dwThreadId; 
 
	switch (LOWORD(wParam)) 
	{ 
		case IDM_STARTSERVICE: // 开始服务 
		{ 
			if (!loaddata(szLoginInfo)) 
				return; 
			InsertLogMsg("加载欢迎语成功"); 
			if (!loadserverdata()) 
				return;  
			InsertLogMsg("加载服务器列表成功"); 
			if(!InitSQLEnvironment())	 
				return; 
	        InsertLogMsg("初始化ODBC环境成功"); 
			if(!ConnectDatabase())	 
				return; 
	        InsertLogMsg("安装ODBC成功");   
			 
			hThread = CreateThread(NULL, 0, ServerThread, NULL, 0, &dwThreadId); 
 
			return; 
		} 
		case IDM_STOPSERVICE: // 停止服务 
		{ 
		//	g_fTerminated = TRUE; 
 
		//	ClearSocket(g_gcSock); 
 
			SwitchMenuItem(FALSE); 
			SendMessage(option.hStatusBar, SB_SETTEXT, MAKEWORD(0, 0), (LPARAM)_TEXT("服务器关闭")); 
 
			return; 
		} 
		case IDM_FONTCOLOR: 
			SetFontColor(); 
			return; 
		case IDM_BACKCOLOR: 
			SetBackColor(); 
			return; 
		case ID_MENU_TALK: 
		//	DialogBox(hInst, (LPCTSTR)IDD_TALK_DIALOG, option.hMainWnd, (DLGPROC)TalkConfig); 
			return; 
		case ID_MENU_ABOUT: 
		{ 
			DialogBox(option.hInst, (LPCTSTR)IDD_ABOUTBOX, option.hMainWnd, (DLGPROC)About); 
			return; 
		} 
	} 
} 
 
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
	RECT rcToolBar, rcMain, rcStatusBar; 
	int	nStatusPartsWidths[_NUMOFMAX_STATUS_PARTS]; 
	int i, nCnt; 
	TCHAR	szMsg[128]; 
	TCHAR	szTitle[128]; 
 
	switch (message) 
	{ 
 
		case WM_INITDIALOG: 
			return TRUE; 
		case WM_COMMAND: 
			OnCommand(wParam, lParam); 
			return TRUE; 
/*		case WM_ERASEBKGND: 
			return TRUE; // ORZ: 濒糊芭府绰 巴 力芭 
		case WM_PAINT: 
			return TRUE; 
			*/ 
		case WM_SIZE: 
		{ 
			if (option.hToolBar && option.hMainWnd && option.hStatusBar)  
			{ 
				GetWindowRect(option.hToolBar, &rcToolBar); 
				GetClientRect(option.hMainWnd, &rcMain); 
				GetWindowRect(option.hStatusBar, &rcStatusBar); 
 
				MoveWindow(option.hToolBar, 0, 0, LOWORD(lParam), (rcToolBar.bottom - rcToolBar.top), TRUE); 
				MoveWindow(option.hStatusBar, 0, rcMain.bottom - (rcStatusBar.bottom - rcStatusBar.top),  
								LOWORD(lParam), (rcStatusBar.bottom - rcStatusBar.top), TRUE); 
				MoveWindow(option.hLogMsgWnd, 0, (rcToolBar.bottom - rcToolBar.top) - 2, (rcMain.right - rcMain.left),  
								(rcMain.bottom - rcMain.top) - (rcToolBar.bottom - rcToolBar.top) - (rcStatusBar.bottom - rcStatusBar.top) + 2,  
								TRUE); 
				nCnt = 0; 
 
				for (i = _NUMOFMAX_STATUS_PARTS - 1; i >= 0 ; i--) 
					nStatusPartsWidths[nCnt++] = (rcStatusBar.right - rcStatusBar.left) - (90 * i); 
 
				SendMessage(option.hStatusBar, SB_SETPARTS, _NUMOFMAX_STATUS_PARTS, (LPARAM)nStatusPartsWidths); 
 
			//	InvalidateRect(option.hStatusBar, NULL, TRUE ); 
 
			//	ShowWindow(option.hStatusBar, SW_SHOW); 
			} 
 
			break; 
		} 
		 
		case WM_CLOSE: 
		{ 
 
			LoadString(option.hInst, IDS_PROGRAM_QUIT, szMsg, sizeof(szMsg)); 
			LoadString(option.hInst, IDS_PROGRAM_TITLE, szTitle, sizeof(szTitle)); 
 
			if (MessageBox(option.hMainWnd, szMsg, szTitle, MB_ICONINFORMATION|MB_YESNO) == IDYES) 
			{			 
//				ClearServerSocket(); 
//				DisconnectFromServer(); 
 
//				savelumpinfo(Lump_info); 
 
				OnCommand(IDM_STOPSERVICE, 0L); 
 
//				CoUninitialize(); 
 
				WSACleanup(); 
 
				PostQuitMessage(0); 
			} 
 
			return 0L; 
		} 
	} 
 
	return (DefWindowProc(hWnd, message, wParam, lParam)); 
} 
 
// Mesage handler for about box. 
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
	switch (message) 
	{ 
		case WM_INITDIALOG: 
				return TRUE; 
 
		case WM_COMMAND: 
			if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)  
			{ 
				EndDialog(hDlg, LOWORD(wParam)); 
				return TRUE; 
			} 
			break; 
	} 
    return FALSE; 
}