📄 emule.cpp
字号:
//this file is part of eMule
//Copyright (C)2002 Merkur ( devs@emule-project.net / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
#include "stdafx.h"
#include <locale.h>
#include <io.h>
#include <share.h>
#include "emule.h"
#include "version.h"
#include "opcodes.h"
#include "mdump.h"
#include "Scheduler.h"
#include "SearchList.h"
#include "kademlia/kademlia/Kademlia.h"
#include "kademlia/kademlia/Prefs.h"
#include "kademlia/kademlia/Error.h"
#include "kademlia/utils/UInt128.h"
#include "PerfLog.h"
#include <..\src\mfc\sockimpl.h>
#include <..\src\mfc\afximpl.h>
#include "LastCommonRouteFinder.h"
#include "UploadBandwidthThrottler.h"
#include "ClientList.h"
#include "FriendList.h"
#include "ClientUDPSocket.h"
#include "DownloadQueue.h"
#include "IPFilter.h"
#include "MMServer.h"
#include "Statistics.h"
#include "OtherFunctions.h"
#include "WebServer.h"
#include "UploadQueue.h"
#include "SharedFileList.h"
#include "ServerList.h"
#include "Sockets.h"
#include "ListenSocket.h"
#include "ClientCredits.h"
#include "KnownFileList.h"
#include "Server.h"
#include "UpDownClient.h"
#include "ED2KLink.h"
#include "Preferences.h"
#include "secrunasuser.h"
#include "SafeFile.h"
#include "PeerCacheFinder.h"
#include "emuleDlg.h"
#include "SearchDlg.h"
#include "enbitmap.h"
#include "FirewallOpener.h"
#include "StringConversion.h"
#include "Log.h"
CLogFile theLog;
CLogFile theVerboseLog;
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "IP2Country.h"//EastShare - added by AndCycle, IP to Country
///////////////////////////////////////////////////////////////////////////////
// MSLU (Microsoft Layer for Unicode) support - UnicoWS
//
HMODULE g_hUnicoWS = NULL;
bool g_bUnicoWS = false;
void ShowUnicowsError()
{
// NOTE: Do *NOT* use any MFC nor W-functions here!
// NOTE: Do *NOT* use eMule's localization functions here!
MessageBoxA(NULL,
"This eMule version requires the \"Microsoft(R) Layer for Unicode(TM) on Windows(R) 95/98/ME Systems\".\r\n"
"\r\n"
"Download the MSLU package from Microsoft(R) here:\r\n"
" http://www.microsoft.com/downloads/details.aspx?FamilyId=73BA7BD7-ED06-4F0D-80A4-2A7EEAEE17E2\r\n"
"or\r\n"
" visit the eMule Project Download Page http://www.emule-project.net/home/perl/general.cgi?rm=download\r\n"
"or\r\n"
" search the Microsoft(R) Download Center http://www.microsoft.com/downloads/ for \"MSLU\" or \"unicows\"."
"\r\n"
"\r\n"
"\r\n"
"After downloading the MSLU package, run the \"unicows.exe\" program and specify your eMule installation folder "
"where to place the extracted files from the package.\r\n"
"\r\n"
"Ensure that the file \"unicows.dll\" was placed in your eMule installation folder and start eMule again.",
"eMule",
MB_ICONSTOP | MB_SYSTEMMODAL | MB_SETFOREGROUND);
}
extern "C" HMODULE __stdcall ExplicitPreLoadUnicows()
{
#ifdef _AFXDLL
// UnicoWS support *requires* statically linked MFC and C-RTL.
// NOTE: Do *NOT* use any MFC nor W-functions here!
// NOTE: Do *NOT* use eMule's localization functions here!
MessageBoxA(NULL,
"This eMule version (Unicode, MSLU, shared MFC) does not run with this version of Windows.",
"eMule",
MB_ICONSTOP | MB_SYSTEMMODAL | MB_SETFOREGROUND);
exit(1);
#endif
// Pre-Load UnicoWS -- needed for proper initialization of MFC/C-RTL
HMODULE g_hUnicoWS = LoadLibraryA("unicows.dll");
if (g_hUnicoWS == NULL)
{
ShowUnicowsError();
exit(1);
}
g_bUnicoWS = true;
return g_hUnicoWS;
}
// NOTE: Do *NOT* change the name of this function. It *HAS* to be named "_PfnLoadUnicows" !
extern "C" HMODULE (__stdcall *_PfnLoadUnicows)(void) = &ExplicitPreLoadUnicows;
///////////////////////////////////////////////////////////////////////////////
// C-RTL Memory Debug Support
//
#ifdef _DEBUG
static CMemoryState oldMemState, newMemState, diffMemState;
_CRT_ALLOC_HOOK g_pfnPrevCrtAllocHook = NULL;
CMap<const unsigned char*, const unsigned char*, UINT, UINT> g_allocations;
int eMuleAllocHook(int mode, void* pUserData, size_t nSize, int nBlockUse, long lRequest, const unsigned char* pszFileName, int nLine);
//CString _strCrtDebugReportFilePath(_T("eMule CRT Debug Log.txt"));
// don't use a CString for that memory - it will not be available on application termination!
#define APP_CRT_DEBUG_LOG_FILE _T("eMule CRT Debug Log.txt")
static TCHAR _szCrtDebugReportFilePath[MAX_PATH] = APP_CRT_DEBUG_LOG_FILE;
#endif //_DEBUG
struct SLogItem
{
UINT uFlags;
CString line;
};
void CALLBACK myErrHandler(Kademlia::CKademliaError *error)
{
CString msg;
msg.Format(_T("\r\nError 0x%08X : %hs\r\n"), error->m_ErrorCode, error->m_ErrorDescription);
if(theApp.emuledlg && theApp.emuledlg->IsRunning())
theApp.QueueDebugLogLine(false, _T("%s"), msg);
}
void CALLBACK myDebugAndLogHandler(LPCSTR lpMsg)
{
if(theApp.emuledlg && theApp.emuledlg->IsRunning())
theApp.QueueDebugLogLine(false, _T("%hs"), lpMsg);
}
void CALLBACK myLogHandler(LPCSTR lpMsg)
{
if(theApp.emuledlg && theApp.emuledlg->IsRunning())
theApp.QueueLogLine(false, _T("%hs"), lpMsg);
}
const static UINT UWM_ARE_YOU_EMULE=RegisterWindowMessage(EMULE_GUID);
// CemuleApp
BEGIN_MESSAGE_MAP(CemuleApp, CWinApp)
ON_COMMAND(ID_HELP, OnHelp)
END_MESSAGE_MAP()
CemuleApp::CemuleApp(LPCTSTR lpszAppName)
:CWinApp(lpszAppName)
{
srand(time(NULL));
m_dwPublicIP = 0;
m_bAutoStart = false;
m_ullComCtrlVer = MAKEDLLVERULL(4,0,0,0);
m_hSystemImageList = NULL;
m_sizSmallSystemIcon.cx = 16;
m_sizSmallSystemIcon.cy = 16;
m_iDfltImageListColorFlags = ILC_COLOR;
// MOD Note: Do not change this part - Merkur
// this is the "base" version number <major>.<minor>.<update>.<build>
m_dwProductVersionMS = MAKELONG(VERSION_MIN, VERSION_MJR);
m_dwProductVersionLS = MAKELONG(VERSION_BUILD, VERSION_UPDATE);
// create a string version (e.g. "0.30a")
ASSERT( VERSION_UPDATE + 'a' <= 'f' );
m_strCurVersionLong.Format(_T("%u.%u%c VeryCD Build 0208"), VERSION_MJR, VERSION_MIN, _T('a') + VERSION_UPDATE);
#ifdef _DEBUG
m_strCurVersionLong += _T(" DEBUG");
#endif
// create the protocol version number
CString strTmp;
strTmp.Format(_T("0x%u"), m_dwProductVersionMS);
VERIFY( _stscanf(strTmp, _T("0x%x"), &m_uCurVersionShort) == 1 );
ASSERT( m_uCurVersionShort < 0x99 );
// create the version check number
strTmp.Format(_T("0x%u%c"), m_dwProductVersionMS, _T('A') + VERSION_UPDATE);
VERIFY( _stscanf(strTmp, _T("0x%x"), &m_uCurVersionCheck) == 1 );
ASSERT( m_uCurVersionCheck < 0x999 );
// MOD Note: end
m_bGuardClipboardPrompt = false;
EnableHtmlHelp();
}
CemuleApp theApp(_T("eMule"));
// Workaround for buggy 'AfxSocketTerm' (needed at least for MFC 7.0)
#if _MFC_VER==0x0700 || _MFC_VER==0x0710
void __cdecl __AfxSocketTerm()
{
#if defined(_AFXDLL) && (_MFC_VER==0x0700 || _MFC_VER==0x0710)
VERIFY( WSACleanup() == 0 );
#else
_AFX_SOCK_STATE* pState = _afxSockState.GetData();
if (pState->m_pfnSockTerm != NULL){
VERIFY( WSACleanup() == 0 );
pState->m_pfnSockTerm = NULL;
}
#endif
}
#else
#error "You are using an MFC version which may require a special version of the above function!"
#endif
// CemuleApp Initialisierung
BOOL CemuleApp::InitInstance()
{
#ifdef _DEBUG
// set Floating Point Processor to throw several exceptions, in particular the 'Floating point devide by zero'
UINT uEmCtrlWord = _control87(0, 0) & _MCW_EM;
_control87(uEmCtrlWord & ~(/*_EM_INEXACT |*/ _EM_UNDERFLOW | _EM_OVERFLOW | _EM_ZERODIVIDE | _EM_INVALID), _MCW_EM);
// output all ASSERT messages to debug device
_CrtSetReportMode(_CRT_ASSERT, _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_REPORT_MODE) | _CRTDBG_MODE_DEBUG);
#endif
TCHAR szAppDir[MAX_PATH];
VERIFY( GetModuleFileName(m_hInstance, szAppDir, ARRSIZE(szAppDir)) );
VERIFY( PathRemoveFileSpec(szAppDir) );
TCHAR szPrefFilePath[MAX_PATH];
PathCombine(szPrefFilePath, szAppDir, CONFIGFOLDER _T("preferences.ini"));
if (m_pszProfileName)
free((void*)m_pszProfileName);
m_pszProfileName = _tcsdup(szPrefFilePath);
#ifdef _DEBUG
oldMemState.Checkpoint();
// Installing that memory debug code works fine in Debug builds when running within VS Debugger,
// but some other test applications don't like that all....
//g_pfnPrevCrtAllocHook = _CrtSetAllocHook(&eMuleAllocHook);
#endif
//afxMemDF = allocMemDF | delayFreeMemDF;
///////////////////////////////////////////////////////////////////////////
// Install crash dump creation
//
if (GetProfileInt(_T("eMule"), _T("CreateCrashDump"), 0))
theCrashDumper.Enable(_T("eMule ") + m_strCurVersionLong, true);
///////////////////////////////////////////////////////////////////////////
// Locale initialization -- BE VERY CAREFUL HERE!!!
//
_tsetlocale(LC_ALL, _T("")); // set all categories of locale to user-default ANSI code page obtained from the OS.
_tsetlocale(LC_NUMERIC, _T("C")); // set numeric category to 'C'
//_tsetlocale(LC_CTYPE, _T("C")); // set character types category to 'C' (VERY IMPORTANT, we need binary string compares!)
AfxOleInit();
pendinglink = 0;
if (ProcessCommandline())
return false;
extern bool CheckThreadLocale();
if (!CheckThreadLocale())
return false;
///////////////////////////////////////////////////////////////////////////
// Common Controls initialization
//
InitCommonControls();
DWORD dwComCtrlMjr = 4;
DWORD dwComCtrlMin = 0;
AtlGetCommCtrlVersion(&dwComCtrlMjr, &dwComCtrlMin);
m_ullComCtrlVer = MAKEDLLVERULL(dwComCtrlMjr,dwComCtrlMin,0,0);
if (m_ullComCtrlVer < MAKEDLLVERULL(5,8,0,0))
{
if (GetProfileInt(_T("eMule"), _T("CheckComctl32"), 1)) // just in case some user's can not install that package and have to survive without it..
{
if (AfxMessageBox(GetResString(IDS_COMCTRL32_DLL_TOOOLD),MB_ICONSTOP | MB_YESNO)==IDYES)
ShellOpenFile(_T("http://www.microsoft.com/downloads/details.aspx?FamilyID=cb2cf3a2-8025-4e8f-8511-9b476a8d35d2"));
// No need to exit eMule, it will most likely work as expected but it will have some GUI glitches here and there..
}
}
m_sizSmallSystemIcon.cx = GetSystemMetrics(SM_CXSMICON);
m_sizSmallSystemIcon.cy = GetSystemMetrics(SM_CYSMICON);
m_iDfltImageListColorFlags = GetAppImageListColorFlag();
// don't use 32bit color resources if not supported by commctl
if (m_iDfltImageListColorFlags == ILC_COLOR32 && m_ullComCtrlVer < MAKEDLLVERULL(6,0,0,0))
m_iDfltImageListColorFlags = ILC_COLOR16;
// don't use >8bit color resources with OSs with restricted memory for GDI resources
if (afxData.bWin95)
m_iDfltImageListColorFlags = ILC_COLOR8;
CWinApp::InitInstance();
if (!AfxSocketInit())
{
AfxMessageBox(GetResString(IDS_SOCKETS_INIT_FAILED));
return FALSE;
}
#if _MFC_VER==0x0700 || _MFC_VER==0x0710
atexit(__AfxSocketTerm);
#else
#error "You are using an MFC version which may require a special version of the above function!"
#endif
AfxEnableControlContainer();
if (!AfxInitRichEdit2()){
if (!AfxInitRichEdit())
AfxMessageBox(_T("Fatal Error: No Rich Edit control library found!")); // should never happen..
}
if (!Kademlia::CKademlia::initUnicode(AfxGetInstanceHandle())){
AfxMessageBox(_T("Fatal Error: Failed to load Unicode character tables for Kademlia!")); // should never happen..
return FALSE; // DO *NOT* START !!!
}
extern bool SelfTest();
if (!SelfTest())
return FALSE; // DO *NOT* START !!!
// create & initalize all the important stuff
thePrefs.Init();
theStats.Init();
// check if we have to restart eMule as Secure user
if (thePrefs.IsRunAsUserEnabled()){
CSecRunAsUser rau;
if ( rau.PrepareUser() && rau.RestartAsUser() )
return FALSE; // emule restart as secure user, kill this instance
else if ( !rau.IsRunningEmuleAccount() ){
// something went wrong
theApp.QueueLogLine(false, GetResString(IDS_RAU_FAILED), rau.GetCurrentUserW());
}
}
#ifdef _DEBUG
_sntprintf(_szCrtDebugReportFilePath, ARRSIZE(_szCrtDebugReportFilePath), _T("%s\\%s"), thePrefs.GetAppDir(), APP_CRT_DEBUG_LOG_FILE);
#endif
VERIFY( theLog.SetFilePath(thePrefs.GetLogDir() + _T("eMule.log")) );
VERIFY( theVerboseLog.SetFilePath(thePrefs.GetLogDir() + _T("eMule_Verbose.log")) );
theLog.SetMaxFileSize(thePrefs.GetMaxLogFileSize());
theVerboseLog.SetMaxFileSize(thePrefs.GetMaxLogFileSize());
if (thePrefs.GetLog2Disk())
theLog.Open();
if (thePrefs.GetDebug2Disk())
theVerboseLog.Open();
CemuleDlg dlg;
emuledlg = &dlg;
m_pMainWnd = &dlg;
// Barry - Auto-take ed2k links
if (thePrefs.AutoTakeED2KLinks())
Ask4RegFix(false, true);
if( thePrefs.GetAutoStart() )
::AddAutoStart();
else
::RemAutoStart();
m_pFirewallOpener = new CFirewallOpener();
m_pFirewallOpener->Init(true); // we need to init it now (even if we may not use it yet) because of CoInitializeSecurity - which kinda ruins the sense of the class interface but ooohh well :P
// Open WinXP firewallports if set in preferences and possible
if (thePrefs.IsOpenPortsOnStartupEnabled()){
if (m_pFirewallOpener->DoesFWConnectionExist()){
// delete old rules added by eMule
m_pFirewallOpener->RemoveRule(EMULE_DEFAULTRULENAME_UDP);
m_pFirewallOpener->RemoveRule(EMULE_DEFAULTRULENAME_TCP);
// open port for this session
if (m_pFirewallOpener->OpenPort(thePrefs.GetPort(), NAT_PROTOCOL_TCP, EMULE_DEFAULTRULENAME_TCP, true))
QueueLogLine(false, GetResString(IDS_FO_TEMPTCP_S), thePrefs.GetPort());
else
QueueLogLine(false, GetResString(IDS_FO_TEMPTCP_F), thePrefs.GetPort());
if (thePrefs.GetUDPPort()){
// open port for this session
if (m_pFirewallOpener->OpenPort(thePrefs.GetUDPPort(), NAT_PROTOCOL_UDP, EMULE_DEFAULTRULENAME_UDP, true))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -