// Include #include "agentdemon.h" // Local definitions // memory¸¦ ¾ÈÀüÇÏ°Ô ÇØÁ¦ #define SafeDelete(P) if (P!=NULL) { delete(P); (P)=NULL; } // handle¸¦ ¾ÈÀüÇÏ°Ô ÇØÁ¦ #define SafeCloseHandle(P) if (P!=NULL) { CloseHandle(P); (P)=NULL; } // Global data AgentDemon* g_agentDemon = NULL; bool g_verbose = false; bool g_fps = false; bool g_packet = false; u_short g_loginPort = 15002; u_short g_gamePort = 15004; u_short g_logPort = 15000; // ¼­ºñ½º À̸§ ¹× Ç¥½ÃÀ̸§ ¼³Á¤ - ±âº»°ª. TCHAR g_serviceName[MAX_PATH] = TEXT( "AgentDemon" ); TCHAR g_description[MAX_PATH] = TEXT( "Copyright(c) 2009 EYA INTERACTIVE Corporation All rights reserved" ); TCHAR g_displayFmt[] = TEXT( "IRIS ON LINE - %s" ); // GenerateDump Prototype // 1. ¼Ó¼º < C/C++ < ÀÏ¹Ý < µð¹ö±ë Á¤º¸ Çü½Ä = ÇÁ·Î±×·¥ µ¥ÀÌÅͺ£À̽º(/Zi) // 2. SetUnhandledExceptionFilter( Exception_Minidump ); // 3. exceptionPointers->ExceptionRecord->ExceptionCode´Â winbase.h and winnt.h ÆÄÀÏÂüÁ¶ // (EXCEPTION_ACCESS_VIOLATION ... CONTROL_C_EXIT µî) // // ÁÖÀÇ: DBGHELP.DLL ÆÄÀÏÀÇ ¹öÀüÀº ÃÖ¼Ò 5.1.2600.0 ÀÌ»óÀ̾î¾ß ÇÑ´Ù. // (MiniDumpWriteDump ÇÔ¼ö°¡ DBGHELP.DLL¿¡ µé¾î ÀÖÀ½) #include #pragma comment(lib, "dbghelp.lib") LONG __stdcall GenerateDump(EXCEPTION_POINTERS* exceptionPointers) { char fileName[MAX_PATH]; SYSTEMTIME st; GetLocalTime( &st ); sprintf_s( fileName ,MAX_PATH ,"LogDemon_%4d%02d%02d_%02d%02d%02d(0x%08X 0x%08p 0x%02X 0x%04X 0x%08X).dmp" ,st.wYear ,st.wMonth ,st.wDay ,st.wHour ,st.wMinute ,st.wSecond ,exceptionPointers->ExceptionRecord->ExceptionCode ,exceptionPointers->ExceptionRecord->ExceptionAddress ,exceptionPointers->ExceptionRecord->NumberParameters ,exceptionPointers->ExceptionRecord->ExceptionInformation[0] ,exceptionPointers->ExceptionRecord->ExceptionInformation[1] ); //GetModuleFileName( NULL, fileName, sizeof(fileName) ); //char* ext = strrchr( fileName, '.' ); //strcpy( ext ? ext : fileName+strlen( fileName ), ".dmp" ); HANDLE process = GetCurrentProcess( ); DWORD processID = GetCurrentProcessId( ); HANDLE file = CreateFile( fileName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); MINIDUMP_EXCEPTION_INFORMATION expParam; expParam.ThreadId = GetCurrentThreadId( ); expParam.ExceptionPointers = exceptionPointers; expParam.ClientPointers = TRUE; MiniDumpWriteDump( process, processID, file, MiniDumpWithDataSegs, &expParam, NULL, NULL ); return EXCEPTION_EXECUTE_HANDLER; } // ErrorCode2String Method // // ¿À·ù Äڵ带 ¸Þ½ÃÁö·Î º¯È¯ÇÑ´Ù. // // msgBuf :¿À·ù¸Þ½ÃÁö (»ç¿ëÈÄ LocalFree ÇÏ¿© ÁØ´Ù.) // lastError :¿À·ùÄÚµå // priLangId :primary language identifier // subLangId :sublanguage identifier // // ¹®ÀÚ¸Þ½ÃÁö ¾ð¾î´Â ¾Æ·¡¿Í °°ÀÌ ¼³Á¤ÇÑ´Ù. // // Primary language identifier : Sublanguage identifier : Meaning // LANG_NEUTRAL SUBLANG_NEUTRAL Language neutral // LANG_NEUTRAL SUBLANG_DEFAULT User default language // LANG_NEUTRAL SUBLANG_SYS_DEFAULT System default language DWORD ErrorCode2String(VOID** msgBuf, DWORD lastError, WORD priLangId, WORD subLangId) { // default to system source HMODULE module = NULL; DWORD bufferLength; DWORD flags; flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM; // If lastError is in the network range, load the message source. // ¸¸¾à lastError°¡ NERR_BASE ¿¡¼­ MAX_NERR Àϰæ¿ì, netmsg.dll ÀÇ // ¸Þ½ÃÁö¸¦ »ç¿ëÇÑ´Ù. (NERR_BASE, MAX_NERR´Â lmerr.h ÆÄÀÏ¿¡ Á¤ÀÇ) if ( lastError >= NERR_BASE && lastError <= MAX_NERR ) { module = LoadLibraryEx( "netmsg.dll", NULL, LOAD_LIBRARY_AS_DATAFILE ); if ( module != NULL ) { flags |= FORMAT_MESSAGE_FROM_HMODULE; } } // If lastError is in the Exception Code range, load the message source. // ¸¸¾à lastError°¡ 0xC0000000L º¸´Ù Ŭ°æ¿ì, ntdll.dllÀÇ ¸Þ½ÃÁö¸¦ »ç¿ëÇÑ´Ù. // (winbase.h, winnt.h ÆÄÀÏ¿¡ Á¤ÀÇ) if ( lastError > 0xC0000000L ) { module = LoadLibraryEx( "ntdll.dll", NULL, LOAD_LIBRARY_AS_DATAFILE ); if ( module != NULL ) { flags |= FORMAT_MESSAGE_FROM_HMODULE; } } // Call FormatMessage() to allow for message text to be acquired // from the system or from the supplied module handle. module to // get message from (NULL == system) bufferLength = FormatMessage( flags, module, lastError, MAKELANGID(priLangId, subLangId), (LPTSTR)msgBuf, 0, NULL ); // If we loaded a message source, unload it. if ( module != NULL ) { FreeLibrary( module ); } return bufferLength; } // ConsolCtrlHandler Prototype - Windows Command Processor Á¦¾î¿ë ÇÔ¼ö. BOOL WINAPI ConsolCtrlHandler(DWORD opcode) { if ( g_agentDemon ) return g_agentDemon->ConsolCtrlHandler( opcode ); else return FALSE; } // main Prototype (This method is the standard Windows program entry point.) int main(int argc, char* argv[]) { LPTOP_LEVEL_EXCEPTION_FILTER previousFilter = NULL; previousFilter = SetUnhandledExceptionFilter( GenerateDump ); AgentDemon* agentDemon = NULL; agentDemon = new AgentDemon( ); agentDemon->ConsoleRun( argc, argv ); SafeDelete( agentDemon ); SetUnhandledExceptionFilter( previousFilter ); return 0L; } // ServiceCtrlHandler Prototype - Windows Service Á¦¾î¿ë ÇÔ¼ö. void WINAPI ServiceCtrlHandler(DWORD opcode) { if ( g_agentDemon ) g_agentDemon->ServiceCtrlHandler( opcode ); } // ServiceMain Prototype (This method is the entry point for a service.) void WINAPI ServiceMain(DWORD argc, LPTSTR* argv) { AgentDemon* agentDemon = NULL; agentDemon = new AgentDemon( ); agentDemon->ServiceRun( argc, argv ); SafeDelete( agentDemon ); } // AgentDemon Constructor. AgentDemon::AgentDemon(void) : mAgentProcess(NULL), mAgentUdpSend(NULL) { g_agentDemon = this; mRunService = false; mEndService = false; mVersion = MAKEWORD(1, 0); memset( mServerAddr, 0, sizeof(mServerAddr) ); memset( mBroadcastAddr, 0, sizeof(mBroadcastAddr) ); } // ~AgentDemon Destructor. AgentDemon::~AgentDemon(void) { // AgentProcess Ŭ·¡½º ÇØÁ¦. SafeDelete( mAgentProcess ); SafeDelete( mAgentUdpSend ); g_agentDemon = NULL; } // InstallService Method - ¼­ºñ½º ¼³Ä¡ ÇÔ¼ö. bool AgentDemon::InstallService(LPCTSTR binaryPathName, LPCTSTR serviceName, DWORD startType) { SC_HANDLE hManager(NULL); SC_HANDLE hService(NULL); bool retValue(false); TCHAR batchPathName[MAX_PATH]; sprintf( batchPathName, "%s -def %s", binaryPathName, serviceName ); TCHAR displayName[MAX_PATH]; sprintf( displayName, g_displayFmt, serviceName ); // Open a handle to the SC Manager database. hManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if ( hManager != NULL ) { // The function creates a service object and adds it to the specified service control manager database. hService = CreateService( hManager, // handle to SCM database serviceName, // name of service to start displayName, // display name SERVICE_ALL_ACCESS, // type of access to service SERVICE_WIN32_OWN_PROCESS, // type of service startType, // when to start service SERVICE_ERROR_NORMAL, // severity of service failure batchPathName, // name of binary file NULL, // name of load ordering group NULL, // tag identifier NULL, // array of dependency names NULL, // account name NULL ); // account password if ( hService != NULL ) { // Success CreateService retValue = true; // The function changes the optional configuration parameters of a service. SERVICE_DESCRIPTION scDesc; scDesc.lpDescription = g_description; ChangeServiceConfig2( hService, SERVICE_CONFIG_DESCRIPTION, &scDesc ); // Close the handle to the service. CloseServiceHandle( hService ); } else { // ¿À·ù¸Þ½ÃÁö Ãâ·Â - CreateService. VOID* msgBuf; if ( ErrorCode2String( &msgBuf ) ) { printf( "\nCreateService (%d): %s\n", GetLastError( ), (char*)msgBuf ); LocalFree( msgBuf ); } } } return retValue; } // UninstallService Method - ¼­ºñ½º »èÁ¦ ÇÔ¼ö. bool AgentDemon::UninstallService(LPCTSTR serviceName) { SC_HANDLE hManager(NULL); SC_HANDLE hService(NULL); bool retValue(false); DWORD lastError(0); // Open a handle to the SC Manager database. hManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if ( hManager != NULL ) { // Open a handle to the service. hService = OpenService( hManager, serviceName, SERVICE_ALL_ACCESS ); if ( hService != NULL ) { // The function marks the specified service for deletion from the service control manager database. if ( DeleteService( hService ) != 0 ) retValue = true; // Success DeleteService else lastError = GetLastError( ); // Close the handle to the service. CloseServiceHandle( hService ); } else lastError = GetLastError( ); } if ( lastError != 0 ) { // ¿À·ù¸Þ½ÃÁö Ãâ·Â - OpenService VOID* msgBuf; if ( ErrorCode2String( &msgBuf ) ) { printf( "\nOpenService (%d): %s\n", GetLastError( ), (char*)msgBuf ); LocalFree( msgBuf ); } } return retValue; } // ConsolCtrlHandler Method BOOL AgentDemon::ConsolCtrlHandler(DWORD opcode) { switch ( opcode ) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: case CTRL_CLOSE_EVENT: case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: Destroy( ); return TRUE; default: // unknown type--better pass it on. return FALSE; } } // ConsoleRun Method void AgentDemon::ConsoleRun(DWORD argc, LPTSTR* argv) { char moduleName[MAX_PATH]; GetModuleFileName( NULL, moduleName, sizeof(moduleName) ); char drive[_MAX_DRIVE]; char directory[_MAX_DIR]; char fileName[_MAX_FNAME]; char ext[_MAX_EXT]; _splitpath( moduleName, drive, directory, fileName, ext ); if ( argc < 2 ) { // »ç¿ë¼³¸í. printf( "USAGE:\n" ); printf( "%s [/INSTALL | /UNINSTALL | /TEST]\n\n", fileName ); printf( " /INSTALL Creates a service object and adds it to the specified service\n" ); printf( " control manager database.\n" ); printf( " OPTION -DEF NAME Uses the name specified during installation.\n" ); printf( " /UNINSTALL Marks the specified service for deletion from the service\n" ); printf( " control manager database.\n" ); printf( " OPTION -DEF NAME While deleting the specified name is used.\n" ); printf( " /TEST Running the Demon Program in Console mode.\n" ); printf( " OPTIONS -VERBOSE Display Debug Information.\n" ); printf( " -PACKET Display Network Information.\n" ); printf( " -DEF NAME Uses the name specified during execution.\n" ); } else if ( argc == 3 && !_stricmp( argv[1], "-def" ) ) { // ¼­ºñ½º À̸§ Àç¼³Á¤. strcpy( g_serviceName, argv[2] ); // 1. ¼­ºñ½º ÇÁ·Î¼¼½ºÀÇ ¸ÞÀÎ ¾²·¹µå¸¦ SCM(Service Control Manager)·Î ³Ñ±â´Â ÇÔ¼ö´Ù. // ÀÌ ÇÔ¼ö¸¦ ºÎ¸¥ ¾²·¹µå´Â Service Control Dispatcher ¾²·¹µå°¡ µÈ´Ù. // // 2. ¼­ºñ½º ÇÁ·Î±×·¥ÀÌ ½ÃÀ۵Ǹé, SCMÀº StartServiceCtrlDispatcher¸¦ ºÒ¸®±æ ±â´Ù¸®°Ô µÈ´Ù. // StartServiceCtrlDispatcher°¡ ¼º°øÇϸé, ¾²·¹µå´Â SCM ÀÌ °ü¸®Çϸç, ¼­ºñ½º°¡ ³¡³¯¶§±îÁö ¸®ÅϵÇÁö ¾Ê´Â´Ù. // ½ÇÁ¦ ¼­ºñ½ºÀÇ ½ÃÀÛÁöÁ¡Àº ÀÌ ÇÔ¼ö°¡ ³Ñ±â´Â ÀÎÀÚ°ªÀÎ ServiceMain À̶ó°í º¼¼ö ÀÖ´Ù. // // !. SERVICE_TABLE_ENTRY¸¦ µî·ÏÇØ¾ß¸¸ ServiceMainÀÌ È£Ã⠵ȴÙ. SERVICE_TABLE_ENTRY DispatchTable[]= { { g_serviceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain }, { NULL, (LPSERVICE_MAIN_FUNCTION)NULL } }; printf( "\n" ); printf( "StartServiceCtrlDispatcher being called.\n" ); printf( "This may take several seconds. Please wait.\n" ); if ( !StartServiceCtrlDispatcher( DispatchTable ) ) { VOID* msgBuf; if ( ErrorCode2String( &msgBuf ) ) { printf( "\nStartServiceCtrlDispatcher (%d): %s\n", GetLastError( ), (char*)msgBuf ); LocalFree( msgBuf ); } } } else if ( !_stricmp( argv[1], "/INSTALL" ) ) { if ( argc == 4 && !stricmp( argv[2], "-DEF" ) ) { // ¼­ºñ½º·Î ¼³Ä¡¸¦ ½ÃµµÇÕ´Ï´Ù. printf( "\nInstallation to your service is initiated.\n" ); if ( InstallService( moduleName, argv[3] ) ) { // ¼­ºñ½º·Î ¼³Ä¡¸¦ ¿Ï·á ÇÏ¿´½À´Ï´Ù. printf( "\nInstallation to your service is completed.\n" ); } else { // ¼­ºñ½º·Î ¼³Ä¡¸¦ ¿Ï·áÇÏÁö ¸ø ÇÏ¿´½À´Ï´Ù. printf( "\nInstallation to your service is not completed.\n" ); } } else { printf( "USAGE:\n" ); printf( " /INSTALL Creates a service object and adds it to the specified service\n" ); printf( " control manager database.\n" ); printf( " OPTION -DEF NAME Uses the name specified during installation." ); } } else if ( !_stricmp( argv[1], "/UNINSTALL" ) ) { if ( argc == 4 && !stricmp( argv[2], "-def" ) ) { // ¼­ºñ½º·Î »èÁ¦¸¦ ½ÃµµÇÕ´Ï´Ù. printf( "\nDeleting your service is initiated.\n" ); if ( UninstallService( argv[3] ) ) { // ¼­ºñ½º·Î »èÁ¦¸¦ ¿Ï·á ÇÏ¿´½À´Ï´Ù. printf( "\nDeleting your service is completed.\n" ); } else { // ¼­ºñ½º·Î »èÁ¦¸¦ ¿Ï·áÇÏÁö ¸ø ÇÏ¿´½À´Ï´Ù. printf( "\nDeleting our service is not completed.\n" ); } } else { printf( "USAGE:\n" ); printf( " /UNINSTALL Marks the specified service for deletion from the service\n" ); printf( " control manager database.\n" ); printf( " OPTION -DEF NAME While deleting the specified name is used." ); } } else if ( !_stricmp( argv[1], "/TEST" ) ) { DWORD status; DWORD error; if ( SetConsoleCtrlHandler( ::ConsolCtrlHandler, TRUE ) != 0 ) { // Å×½ºÆ® ¿É¼Ç °Ë»ç. for ( DWORD i = 2; i < argc; i++ ) { if ( !_stricmp( argv[ i ], "-VERBOSE" ) ) { g_verbose = true; } else if ( !_stricmp( argv[ i ], "-FPS" ) ) { g_fps = true; } else if ( !_stricmp( argv[ i ], "-PACKET" ) ) { g_packet = true; } else if ( !_stricmp( argv[ i ], "-DEF" ) ) { // ¼­ºñ½º À̸§ Àç¼³Á¤. if ( (++i) < argc ) strcpy( g_serviceName, argv[i] ); } } // Äֿܼ¡¼­ÀÇ Å×½ºÆ®. status = Initialization( argc, argv, &error ); if ( status == NO_ERROR ) { printf( "\nRunning the Server in Console mode.\n" ); Run( ); printf( "\nStopping the Server in Console mode.\n" ); } else { printf( "\nInitialize fail.\n" ); } SetConsoleCtrlHandler( ::ConsolCtrlHandler, FALSE ); } } } // ServiceCtrlHandler Method void AgentDemon::ServiceCtrlHandler(DWORD opcode) { switch ( opcode ) { case SERVICE_CONTROL_STOP: // Notifies a service that it should stop. mServiceStatus.dwWin32ExitCode = 0; mServiceStatus.dwCurrentState = SERVICE_STOPPED; mServiceStatus.dwCheckPoint = 0; mServiceStatus.dwWaitHint = 0; // Updates the service control manager's status information for the calling service. SetServiceStatus( mServiceStatusHandle, &mServiceStatus ); // Á¾·áÇÒ ÄÚµå´Â Destroy ÇÔ¼ö¸¦ »ç¿ë. Destroy( ); return; case SERVICE_CONTROL_PAUSE: // Notifies a service that it should pause. mServiceStatus.dwCurrentState = SERVICE_PAUSED; break; case SERVICE_CONTROL_CONTINUE: // Notifies a paused service that it should resume. mServiceStatus.dwCurrentState = SERVICE_RUNNING; break; case SERVICE_CONTROL_INTERROGATE: // Notifies a service that it should report its current status information to the service control manager. break; case SERVICE_CONTROL_SHUTDOWN: // Notifies a service that the system is shutting down so the service can perform cleanup tasks. break; case SERVICE_CONTROL_PARAMCHANGE: // Notifies a service that its startup parameters have changed. The service should reread its startup parameters. break; case SERVICE_CONTROL_NETBINDADD: // Notifies a network service that there is a new component for binding. The service should bind to the new component. break; case SERVICE_CONTROL_NETBINDREMOVE: // Notifies a network service that a component for binding has been removed. // The service should reread its binding information and unbind from the removed component. break; case SERVICE_CONTROL_NETBINDENABLE: // Notifies a network service that a disabled binding has been enabled. // The service should reread its binding information and add the new binding. break; case SERVICE_CONTROL_NETBINDDISABLE: // Notifies a network service that one of its bindings has been disabled. // The service should reread its binding information and remove the binding. break; } // Updates the service control manager's status information for the calling service. SetServiceStatus( mServiceStatusHandle, &mServiceStatus ); } // ServiceRun Method void AgentDemon::ServiceRun(DWORD argc, LPTSTR* argv) { DWORD status; DWORD error; mServiceStatus.dwServiceType = SERVICE_WIN32; mServiceStatus.dwCurrentState = SERVICE_START_PENDING; mServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; mServiceStatus.dwWin32ExitCode = 0; mServiceStatus.dwServiceSpecificExitCode = 0; mServiceStatus.dwCheckPoint = 0; mServiceStatus.dwWaitHint = 0; // ¼­ºñ½º Á¦¾î ó¸®ÀÚ¸¦ µî·ÏÇÑ´Ù. - ½ÇÆÐ½Ã 0¸¦ ¹Ýȯ ÇÑ´Ù. mServiceStatusHandle = RegisterServiceCtrlHandler( g_serviceName, ::ServiceCtrlHandler ); if ( mServiceStatusHandle == (SERVICE_STATUS_HANDLE)0 ) return; // Initialization code goes here. // - ÃʱâÈ­ ÇÒ ÄÚµå´Â ServiceInitialization ÇÔ¼ö¸¦ »ç¿ë // - ½ÇÆÐ½Ã NO_ERROR(0)°¡ ¾Æ´Ñ °ª¸¦ ¹Ýȯ. status = Initialization( argc, argv, &error ); // Handle error condition - ÃʱâÈ­ ½ÇÆÐ ÇÒ °æ¿ì Á¾·áÄÚµå(status)¸¦ Ç¥½ÃÇØ ÁØ´Ù. if ( status != NO_ERROR ) { mServiceStatus.dwCurrentState = SERVICE_STOPPED; mServiceStatus.dwCheckPoint = 0; mServiceStatus.dwWaitHint = 0; mServiceStatus.dwWin32ExitCode = status; mServiceStatus.dwServiceSpecificExitCode = error; // Updates the service control manager's status information for the calling service. if ( SetServiceStatus( mServiceStatusHandle, &mServiceStatus ) == FALSE ) return; } // Initialization complete - report running status. // - ÃʱâÈ­ ¿Ï·á - ¼­ºñ½º »óŸ¦ µ¿ÀÛ(RUNNING)À¸·Î ¼³Á¤. mServiceStatus.dwCurrentState = SERVICE_RUNNING; mServiceStatus.dwCheckPoint = 0; mServiceStatus.dwWaitHint = 0; // Updates the service control manager's status information for the calling service. if ( SetServiceStatus( mServiceStatusHandle, &mServiceStatus ) == FALSE ) return; // Run - ¼­ºñ½º ½ÃÀÛ. Run( ); } /*-- Initialization Method (Stub initialization function.) */ DWORD AgentDemon::Initialization(DWORD argc, LPTSTR* argv, DWORD* error) { // WINSOCK2 ÃʱâÈ­ (¹öÀü 2.2). if ( LOBYTE( m_wsaData.wVersion ) != 2 || HIBYTE( m_wsaData.wVersion ) != 2 ) return 1L; /*-- ODBC-DNS & WINSOCK2 ÃʱâÈ­. --*/ timeBeginPeriod( 1 ); // »ç¿ëÀÚ Á¤º¸. DWORD userNameSize = 0; DWORD userNameRetVal = 0; userNameRetVal = GetUserName( mUserName, &userNameSize ); if ( userNameRetVal == 0 && GetLastError( ) == ERROR_INSUFFICIENT_BUFFER ) { mUserName = (TCHAR*)GlobalAlloc( GPTR, userNameSize ); userNameRetVal = GetUserName( mUserName, &userNameSize ); } if ( userNameRetVal == 0 && GetLastError( ) == ERROR_INSUFFICIENT_BUFFER ) { if ( g_verbose == true ) { VOID* msgBuf; if ( ErrorCode2String( &msgBuf ) ) { printf( "\nGetUserName (%d): %s\n", GetLastError( ), (char*)msgBuf ); LocalFree( msgBuf ); } } return 1L; } // È£½ºÆ® Á¤º¸. if ( GetLocalHostInfo( ) == false ) { if ( g_verbose == true ) { VOID* msgBuf; if ( ErrorCode2String( &msgBuf ) ) { printf( "\nGetNetworkParams (%d): %s\n", GetLastError( ), (char*)msgBuf ); LocalFree( msgBuf ); } } return 1L; } // »ç¿ëÀÚ & È£½ºÆ® Á¤º¸Ãâ·Â. if ( g_verbose == true ) { printf( "\n" ); printf( "User Name............: %s \n", mUserName ); printf( "Host Name............: %s \n", mFixedInfo->HostName ); printf( "NetBIOS Scope ID.....: %s \n", mFixedInfo->ScopeId ); printf( "IP Routing Enabled...: %s \n", (mFixedInfo->EnableRouting ? "YES" : "NO") ); printf( "WINS Proxy Enabled...: %s \n", (mFixedInfo->EnableProxy ? "YES" : "NO") ); printf( "\n" ); } // ½ÇÇàȯ°æ ¼³Á¤. char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; TCHAR filename[MAX_PATH]="\0"; TCHAR directory[MAX_PATH]="\0"; GetModuleFileName( NULL, filename, sizeof(filename) ); _splitpath( filename, drive, dir, fname, ext ); char* _ext = strrchr( filename, '.' ); strcpy( _ext ? _ext : filename+strlen( filename ), ".cfg" ); sprintf( directory, "%s%s", drive, dir ); // ¼­ºñ½º & ÄÜ¼Ö & µð¹ö±× ¸ðµå ȣȯ¼º Àû¿ë. if ( GetFileAttributes( filename ) == INVALID_FILE_ATTRIBUTES ) { GetCurrentDirectory( sizeof(directory), directory ); sprintf( filename, "%s\\%s.cfg", directory, fname ); } // ½ÇÇàÆÄÀϰæ·Î Ãâ·Â. if ( g_verbose == true ) { printf( "Binary Path Name.....: %s%s%s%s \n", drive, dir, fname, ext ); printf( "Working Directory....: %s \n", directory ); printf( "Module Path Name.....: %s \n", filename ); printf( "\n" ); } FILE* stream = fopen( filename, "rt" ); char buffer[MAX_PATH]; char seps[] = " \t\n"; // ÆÄ½Ì±¸¹® Parsing. char *token; /// °ü¸®ÇÒ ¼­¹ö Á¤º¸ struct sManageSrv { char name[100]; char ip[100]; }; unsigned char srvCount = 0; sManageSrv srvList[10]; memset( srvList, 0x00, sizeof(srvList) ); if ( stream != NULL ) { try { while ( fgets( buffer, MAX_PATH, stream ) != NULL ) { token = strtok( buffer, seps ); if ( token && stricmp( token, "SERVICE_NAME:" ) == 0 ) { token = strtok( NULL, seps ); if ( token && stricmp( token, g_serviceName ) == 0 ) { if ( fgets( buffer, MAX_PATH, stream ) == NULL ) throw true; token = strtok( buffer, seps ); if ( token && stricmp( token, "AGENT_DEMON_ADDRESS(IPv4):" ) != 0 ) throw true; sprintf( mServerAddr, "%s", strtok( NULL, seps ) ); if ( fgets( buffer, MAX_PATH, stream ) == NULL ) throw true; token = strtok( buffer, seps ); if ( token && stricmp( token, "AGENT_BROADCAST_ADDRESS(IPv4):" ) != 0 ) throw true; sprintf( mBroadcastAddr, "%s", strtok( NULL, seps ) ); if ( fgets( buffer, MAX_PATH, stream ) == NULL ) throw true; token = strtok( buffer, seps ); if ( token && stricmp( token, "LOGIN_PORT:" ) != 0 ) throw true; g_loginPort = (u_short)atoi( strtok( NULL, seps ) ); if ( fgets( buffer, MAX_PATH, stream ) == NULL ) throw true; token = strtok( buffer, seps ); if ( token && stricmp( token, "GAME_PORT:" ) != 0 ) throw true; g_gamePort = (u_short)atoi( strtok( NULL, seps ) ); if ( fgets( buffer, MAX_PATH, stream ) == NULL ) throw true; token = strtok( buffer, seps ); if ( token && stricmp( token, "LOG_PORT:" ) != 0 ) throw true; g_logPort = (u_short)atoi( strtok( NULL, seps ) ); while( !feof( stream ) ) { fscanf( stream, "%s", buffer ); if ( stricmp( buffer, "MANAGE_SERVER:" ) == 0 ) { fscanf( stream, "%s", srvList[srvCount].name ); fscanf( stream, "%s", srvList[srvCount].ip ); ++srvCount; } else throw 1; if( srvCount >= 10 ) break; } throw 0; } } } throw 1; } catch ( int error ) { fclose( stream ); if ( error != 0L ) return error; } } else return 1L; if ( g_verbose == true ) { printf( "\nAgent Demon Address.....: %s", mServerAddr ); printf( "\nAgent Broadcast Address.: %s", mBroadcastAddr ); printf( "\nLogin Port..............: %d", g_loginPort ); printf( "\nGame Port...............: %d", g_gamePort ); printf( "\nLog Port................: %d", g_logPort ); printf( "\n" ); } // ÀÛ¾÷ µð·ºÅ丮 ¼³Á¤. if ( SetCurrentDirectory( directory ) == false ) return 1L; // AgentUdpSend Ŭ·¡½º »ý¼º. mAgentUdpSend = new AgentUdpSend( ); if ( mAgentUdpSend->Initialize( mBroadcastAddr, 2, 32768 ) == false ) return 1L; // AgentProcess Ŭ·¡½º »ý¼º. mAgentProcess = new AgentProcess( ); /// °ü¸® ¼­¹ö ¸®½ºÆ® µî·Ï for( int i = 0; i < srvCount; i++ ) mAgentProcess->AddServieCtrl( srvList[i].name, srvList[i].ip ); /// AgentProcess ÃʱâÈ­ if ( mAgentProcess->Initialize( mServerAddr, 14900 ) == false ) return 1L; return 0L; } // Destroy Method void AgentDemon::Destroy(void) { if ( mEndService == false ) { mEndService = true; // AgentProcess Ŭ·¡½º Á¾·á. mAgentProcess->Shutdown( ); // AgentUdpSend Ŭ·¡½º Á¾·á. mAgentUdpSend->Shutdown( ); // ½ÇÇàÁ¾·á. mRunService = false; } } // Run Method void AgentDemon::Run(void) { DWORD currentTick = 0; DWORD elapsedTick = 0; // ¼­ºñ½º°¡ ½ÃÀÛ µÊ. mRunService = true; while ( mRunService ) { currentTick = GetTickCount( ); // Áö¿¬½Ã°£ ¾à100(ms) - CPU °úºÎÈ­ ¹æÁö & ³»ºÎ µ¿±âÈ­. elapsedTick = GetTickCount( ) - currentTick; if ( elapsedTick < 100 ) { Sleep( (100 - elapsedTick) ); } } }