From 62078bcba706b66d18cdae5acf1016aed7d39ffc Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 16 Apr 2009 22:43:27 +0800 Subject: [PATCH] Success Send one email to gmail server Signed-off-by: Frank Li --- src/TortoiseProc/Patch.cpp | 26 + src/TortoiseProc/TortoiseProc.vcproj | 32 +- src/Utils/CBase64.cpp | 161 ++++++ src/Utils/HwSMTP.cpp | 939 +++++++++++++++++++++++++++++++++++ src/Utils/HwSMTP.h | 127 +++++ src/Utils/NetAdapterInfo.cpp | 581 ++++++++++++++++++++++ src/Utils/NetAdapterInfo.h | 100 ++++ src/Utils/Utils.vcproj | 12 + src/Utils/base64.cpp | 4 +- src/Utils/base64.h | 2 +- src/Utils/dnsmx.cpp | 730 +++++++++++++++++++++++++++ src/Utils/dnsmx.h | 31 ++ src/Utils/targetver.h | 4 + 13 files changed, 2730 insertions(+), 19 deletions(-) create mode 100644 src/Utils/CBase64.cpp create mode 100644 src/Utils/HwSMTP.cpp create mode 100644 src/Utils/HwSMTP.h create mode 100644 src/Utils/NetAdapterInfo.cpp create mode 100644 src/Utils/NetAdapterInfo.h create mode 100644 src/Utils/dnsmx.cpp create mode 100644 src/Utils/dnsmx.h diff --git a/src/TortoiseProc/Patch.cpp b/src/TortoiseProc/Patch.cpp index b17693a..accea84 100644 --- a/src/TortoiseProc/Patch.cpp +++ b/src/TortoiseProc/Patch.cpp @@ -3,6 +3,8 @@ #include "csmtp.h" #include "registry.h" #include "unicodeutils.h" +#include "hwsmtp.h" +#include "Windns.h" CPatch::CPatch() { @@ -27,7 +29,29 @@ int CPatch::Send(CString &pathfile,CString &TO,CString &CC,bool bAttachment) if(this->Parser(pathfile) ) return -1; + int at=TO.Find(_T('@')); + int start =0; + TO = TO.Tokenize(_T(";"),start); + CString server=TO.Mid(at+1); + + PDNS_RECORD pDnsRecord; + + DnsQuery(server, DNS_TYPE_MX,DNS_QUERY_BYPASS_CACHE, + NULL, //Contains DNS server IP address. + &pDnsRecord, //Resource record that contains the response. + NULL); + + CString name,address; + GetNameAddress(this->m_Author,name,address); + + + SendEmail(FALSE,pDnsRecord->Data.MX.pNameExchange, + NULL,NULL,FALSE,address,TO,this->m_Author,TO,this->m_Subject,_T("Test")); + + DnsRecordListFree(pDnsRecord,DnsFreeRecordList); + +#if 0 CRegString server(REG_SMTP_SERVER); CRegDWORD port(REG_SMTP_PORT,25); CRegDWORD bAuth(REG_SMTP_ISAUTH); @@ -61,6 +85,8 @@ int CPatch::Send(CString &pathfile,CString &TO,CString &CC,bool bAttachment) } return !mail.Send(); +#endif + } diff --git a/src/TortoiseProc/TortoiseProc.vcproj b/src/TortoiseProc/TortoiseProc.vcproj index 7c20b83..5c94fe9 100644 --- a/src/TortoiseProc/TortoiseProc.vcproj +++ b/src/TortoiseProc/TortoiseProc.vcproj @@ -75,7 +75,7 @@ /> 0 ) + { + sOutput += m_sBase64Alphabet[ (int)nDigit ]; + nDigit = read_bits( nNumBits, &nNumBits, lp ); + } + // Pad with '=' as per RFC 1521 + while( sOutput.GetLength() % 4 != 0 ) + { + sOutput += '='; + } + return sOutput; +} + +// The size of the output buffer must not be less than +// 3/4 the size of the input buffer. For simplicity, +// make them the same size. +// return : ½âÂëºóÊý¾Ý³¤¶È +int CBase64::Decode ( IN const char* szDecoding, char* szOutput ) +{ + CString sInput; + int c, lp =0; + int nDigit; + int nDecode[ 256 ]; + + ASSERT( szDecoding != NULL ); + ASSERT( szOutput != NULL ); + if( szOutput == NULL ) + return 0; + if( szDecoding == NULL ) + return 0; + sInput = szDecoding; + if( sInput.GetLength() == 0 ) + return 0; + + // Build Decode Table + // + int i; + for( i = 0; i < 256; i++ ) + nDecode[i] = -2; // Illegal digit + for( i=0; i < 64; i++ ) + { + nDecode[ m_sBase64Alphabet[ i ] ] = i; + nDecode[ m_sBase64Alphabet[ i ] | 0x80 ] = i; // Ignore 8th bit + nDecode[ '=' ] = -1; + nDecode[ '=' | 0x80 ] = -1; // Ignore MIME padding char + } + + // Clear the output buffer + memset( szOutput, 0, sInput.GetLength() + 1 ); + + // Decode the Input + // + for( lp = 0, i = 0; lp < sInput.GetLength(); lp++ ) + { + c = sInput[ lp ]; + nDigit = nDecode[ c & 0x7F ]; + if( nDigit < -1 ) + { + return 0; + } + else if( nDigit >= 0 ) + // i (index into output) is incremented by write_bits() + write_bits( nDigit & 0x3F, 6, szOutput, i ); + } + return i; +} + +UINT CBase64::read_bits(int nNumBits, int * pBitsRead, int& lp) +{ + ULONG lScratch; + while( ( m_nBitsRemaining < nNumBits ) && + ( lp < m_nInputSize ) ) + { + int c = m_szInput[ lp++ ]; + m_lBitStorage <<= 8; + m_lBitStorage |= (c & 0xff); + m_nBitsRemaining += 8; + } + if( m_nBitsRemaining < nNumBits ) + { + lScratch = m_lBitStorage << ( nNumBits - m_nBitsRemaining ); + *pBitsRead = m_nBitsRemaining; + m_nBitsRemaining = 0; + } + else + { + lScratch = m_lBitStorage >> ( m_nBitsRemaining - nNumBits ); + *pBitsRead = nNumBits; + m_nBitsRemaining -= nNumBits; + } + return (UINT)lScratch & f_nMask[nNumBits]; +} + + +void CBase64::write_bits(UINT nBits, + int nNumBits, + LPSTR szOutput, + int& i) +{ + UINT nScratch; + + m_lBitStorage = (m_lBitStorage << nNumBits) | nBits; + m_nBitsRemaining += nNumBits; + while( m_nBitsRemaining > 7 ) + { + nScratch = m_lBitStorage >> (m_nBitsRemaining - 8); + szOutput[ i++ ] = nScratch & 0xFF; + m_nBitsRemaining -= 8; + } +} \ No newline at end of file diff --git a/src/Utils/HwSMTP.cpp b/src/Utils/HwSMTP.cpp new file mode 100644 index 0000000..84d0b20 --- /dev/null +++ b/src/Utils/HwSMTP.cpp @@ -0,0 +1,939 @@ +// HwSMTP.cpp: implementation of the CHwSMTP class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "afxstr.h" +#include "HwSMTP.h" +#include "CBase64.h" +#include "SpeedPostEmail.h" + +#include + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +CPtrArray g_PtrAry_Threads; +::CCriticalSection m_CSFor__g_PtrAry_Threads; + +class CEMailObject +{ +public: + CEMailObject ( + LPCTSTR lpszSmtpSrvHost, + LPCTSTR lpszUserName, + LPCTSTR lpszPasswd, + BOOL bMustAuth, + LPCTSTR lpszAddrFrom, + LPCTSTR lpszAddrTo, + LPCTSTR lpszSenderName, + LPCTSTR lpszReceiverName, + LPCTSTR lpszSubject, + LPCTSTR lpszBody, + LPCTSTR lpszCharSet, + CStringArray *pStrAryAttach, + CStringArray *pStrAryCC, + UINT nSmtpSrvPort + ) + { + m_csSmtpSrvHost = GET_SAFE_STRING(lpszSmtpSrvHost); + m_csUserName = GET_SAFE_STRING(lpszUserName); + m_csPasswd = GET_SAFE_STRING(lpszPasswd); + m_bMustAuth = bMustAuth; + m_csAddrFrom = GET_SAFE_STRING(lpszAddrFrom); + m_csAddrTo = GET_SAFE_STRING(lpszAddrTo); + m_csSenderName = GET_SAFE_STRING(lpszSenderName); + m_csReceiverName = GET_SAFE_STRING(lpszReceiverName); + m_csSubject = GET_SAFE_STRING(lpszSubject); + m_csBody = GET_SAFE_STRING(lpszBody); + m_csCharSet = GET_SAFE_STRING(lpszCharSet); + if ( pStrAryAttach ) + m_StrAryAttach.Append ( *pStrAryAttach ); + if ( pStrAryCC ) + m_StrAryCC.Append ( *pStrAryCC ); + m_nSmtpSrvPort = nSmtpSrvPort; + m_hThread = NULL; + } + +public: + CString m_csSmtpSrvHost; + CString m_csUserName; + CString m_csPasswd; + BOOL m_bMustAuth; + CString m_csAddrFrom; + CString m_csAddrTo; + CString m_csSenderName; + CString m_csReceiverName; + CString m_csSubject; + CString m_csBody; + CString m_csCharSet; + CStringArray m_StrAryAttach; + CStringArray m_StrAryCC; + UINT m_nSmtpSrvPort; + + HANDLE m_hThread; +}; + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CHwSMTP::CHwSMTP () : + m_bConnected ( FALSE ), + m_nSmtpSrvPort ( 25 ), + m_bMustAuth ( TRUE ) +{ + m_csMIMEContentType = _T( "multipart/mixed"); + m_csPartBoundary = _T( "WC_MAIL_PaRt_BoUnDaRy_05151998" ); + m_csNoMIMEText = _T( "This is a multi-part message in MIME format." ); +// m_csCharSet = _T("\r\n\tcharset=\"iso-8859-1\"\r\n"); +} + +CHwSMTP::~CHwSMTP() +{ +} + +BOOL CHwSMTP::SendEmail ( + LPCTSTR lpszSmtpSrvHost, + LPCTSTR lpszUserName, + LPCTSTR lpszPasswd, + BOOL bMustAuth, + LPCTSTR lpszAddrFrom, + LPCTSTR lpszAddrTo, + LPCTSTR lpszSenderName, + LPCTSTR lpszReceiverName, + LPCTSTR lpszSubject, + LPCTSTR lpszBody, + LPCTSTR lpszCharSet, // ×Ö·û¼¯ÀàÐÍ£¬ÀýÈ磺·±ÌåÖÐÎÄÕâÀïÓ¦ÊäÈë"big5"£¬¼òÌåÖÐÎÄʱÊäÈë"gb2312" + CStringArray *pStrAryAttach/*=NULL*/, + CStringArray *pStrAryCC/*=NULL*/, + UINT nSmtpSrvPort/*=25*/ + ) +{ + TRACE ( _T("·¢ËÍÓʼþ£º%s, %s, %s\n"), lpszAddrTo, lpszReceiverName, lpszBody ); + m_StrAryAttach.RemoveAll(); + m_StrAryCC.RemoveAll(); + m_csSmtpSrvHost = GET_SAFE_STRING ( lpszSmtpSrvHost ); + if ( m_csSmtpSrvHost.GetLength() <= 0 ) + { + m_csLastError.Format ( _T("Parameter Error!") ); + return FALSE; + } + m_csUserName = GET_SAFE_STRING ( lpszUserName ); + m_csPasswd = GET_SAFE_STRING ( lpszPasswd ); + m_bMustAuth = bMustAuth; + if ( m_bMustAuth && m_csUserName.GetLength() <= 0 ) + { + m_csLastError.Format ( _T("Parameter Error!") ); + return FALSE; + } + + m_csAddrFrom = GET_SAFE_STRING ( lpszAddrFrom ); + m_csAddrTo = GET_SAFE_STRING ( lpszAddrTo ); + m_csSenderName = GET_SAFE_STRING ( lpszSenderName ); + m_csReceiverName = GET_SAFE_STRING ( lpszReceiverName ); + m_csSubject = GET_SAFE_STRING ( lpszSubject ); + m_csBody = GET_SAFE_STRING ( lpszBody ); + m_nSmtpSrvPort = nSmtpSrvPort; + if ( lpszCharSet && lstrlen(lpszCharSet) > 0 ) + m_csCharSet.Format ( _T("\r\n\tcharset=\"%s\"\r\n"), lpszCharSet ); + + if ( + m_csAddrFrom.GetLength() <= 0 || m_csAddrTo.GetLength() <= 0 || + m_csSenderName.GetLength() <= 0 || m_csReceiverName.GetLength() <= 0 || + m_csSubject.GetLength() <= 0 || m_csBody.GetLength() <= 0 + ) + { + m_csLastError.Format ( _T("Parameter Error!") ); + return FALSE; + } + + if ( pStrAryAttach ) + { + m_StrAryAttach.Append ( *pStrAryAttach ); + } + if ( m_StrAryAttach.GetSize() < 1 ) + m_csMIMEContentType = _T( "text/plain"); + + if ( pStrAryCC ) + { + m_StrAryCC.Append ( *pStrAryCC ); + } + + // ´´½¨Socket + if ( !m_SendSock.Create () ) + { + m_csLastError.Format ( _T("Create socket failed!") ); + return FALSE; + } + + // Á¬½Óµ½·þÎñÆ÷ + if ( !m_SendSock.Connect ( m_csSmtpSrvHost, m_nSmtpSrvPort ) ) + { + m_csLastError.Format ( _T("Connect to [ %s ] failed"), m_csSmtpSrvHost ); + TRACE ( _T("%d\n"), GetLastError() ); + return FALSE; + } + if ( !GetResponse( _T("220") ) ) return FALSE; + + m_bConnected = TRUE; + return SendEmail(); + +} + + +BOOL CHwSMTP::GetResponse ( LPCTSTR lpszVerifyCode, int *pnCode/*=NULL*/) +{ + if ( !lpszVerifyCode || lstrlen(lpszVerifyCode) < 1 ) + return FALSE; + + char szRecvBuf[1024] = {0}; + int nRet = 0; + char szStatusCode[4] = {0}; + nRet = m_SendSock.Receive ( szRecvBuf, sizeof(szRecvBuf) ); + TRACE ( _T("Received : %s\r\n"), szRecvBuf ); + if ( nRet <= 0 ) + { + m_csLastError.Format ( _T("Receive TCP data failed") ); + return FALSE; + } +// TRACE ( _T("ÊÕµ½·þÎñÆ÷»ØÓ¦£º%s\n"), szRecvBuf ); + + memcpy ( szStatusCode, szRecvBuf, 3 ); + if ( pnCode ) (*pnCode) = atoi ( szStatusCode ); + + if ( strcmp ( szStatusCode, CMultiByteString(lpszVerifyCode).GetBuffer() ) != 0 ) + { + m_csLastError.Format ( _T("Received invalid response : %s"), GetCompatibleString(szRecvBuf,FALSE) ); + return FALSE; + } + + return TRUE; +} + +// ÀûÓÃsocket·¢ËÍÊý¾Ý£¬Êý¾Ý³¤¶È²»Äܳ¬¹ý10M +BOOL CHwSMTP::Send(LPCTSTR lpszData, ... ) +{ + if ( !m_bConnected ) + { + m_csLastError.Format ( _T("Didn't connect") ); + return FALSE; + } + + TCHAR *buf = NULL; + // Ñ­»·¸ñʽ»¯×Ö·û´®£¬Èç¹û»º³å²»¹»Ôò½«»º³å¼Ó´óÈ»ºóÖØÊÔÒÔ±£Ö¤»º³å¹»ÓÃͬʱÓÖ²»ÀË·Ñ + for ( int nBufCount = 1024; nBufCount<10*1024*1024; nBufCount += 1024 ) + { + buf = new TCHAR[nBufCount]; + if ( !buf ) + { + ::AfxThrowMemoryException (); + return FALSE; + } + memset ( buf, 0, nBufCount*sizeof(TCHAR) ); + + va_list va; + va_start (va, lpszData); + int nLen = _vsnprintf_hw ((TCHAR*)buf, nBufCount-sizeof(TCHAR), lpszData, va); + va_end(va); + if ( nLen <= (int)(nBufCount-sizeof(TCHAR)) ) + break; + delete[] buf; buf = NULL; + } + if ( !buf ) + { + m_csLastError.Format ( _T("Memory too small or data too big.") ); + return FALSE; + } + + CMultiByteString cbsData ( buf ); + delete[] buf; buf = NULL; + TRACE ( _T("Send : %s\r\n"), cbsData.GetBuffer() ); + if ( m_SendSock.Send ( cbsData.GetBuffer(), cbsData.GetLength() ) != cbsData.GetLength() ) + { + m_csLastError.Format ( _T("Socket send data failed") ); + return FALSE; + } + + return TRUE; +} + +BOOL CHwSMTP::SendEmail() +{ + BOOL bRet = TRUE; + char szLocalHostName[64] = {0}; + gethostname ( (char*)szLocalHostName, sizeof(szLocalHostName) ); + + // hello£¬ÎÕÊÖ + if ( !Send ( _T("HELO %s\r\n"), GetCompatibleString(szLocalHostName,FALSE) ) ) + { + return FALSE; + } + if ( !GetResponse ( _T("250") ) ) + { + return FALSE; + } + // Éí·ÝÑéÖ¤ + if ( m_bMustAuth && !auth() ) + { + return FALSE; + } + // ·¢ËÍÓʼþÍ· + if ( !SendHead() ) + { + return FALSE; + } + // ·¢ËÍÓʼþÖ÷Ìâ + if ( !SendSubject() ) + { + return FALSE; + } + // ·¢ËÍÓʼþÕýÎÄ + if ( !SendBody() ) + { + return FALSE; + } + // ·¢Ë͸½¼þ + if ( !SendAttach() ) + { + return FALSE; + } + // ½áÊøÓʼþÕýÎÄ + if ( !Send ( _T(".\r\n") ) ) return FALSE; + if ( !GetResponse ( _T("250") ) ) + return FALSE; + + // Í˳ö·¢ËÍ + if ( HANDLE_IS_VALID(m_SendSock.m_hSocket) ) + Send ( _T("QUIT\r\n") ); + m_bConnected = FALSE; + + return bRet; +} + +BOOL CHwSMTP::auth() +{ + int nResponseCode = 0; + if ( !Send ( _T("auth login\r\n") ) ) return FALSE; + if ( !GetResponse ( _T("334"), &nResponseCode ) ) return FALSE; + if ( nResponseCode != 334 ) // ²»ÐèÒªÑéÖ¤Óû§ÃûºÍÃÜÂë + return TRUE; + + CBase64 Base64Encode; + CMultiByteString cbsUserName ( m_csUserName ), cbsPasswd ( m_csPasswd ); + CString csBase64_UserName = GetCompatibleString ( Base64Encode.Encode ( cbsUserName.GetBuffer(), cbsUserName.GetLength() ).GetBuffer(0), FALSE ); + CString csBase64_Passwd = GetCompatibleString ( Base64Encode.Encode ( cbsPasswd.GetBuffer(), cbsPasswd.GetLength() ).GetBuffer(0), FALSE ); + + if ( !Send ( _T("%s\r\n"), csBase64_UserName ) ) return FALSE; + if ( !GetResponse ( _T("334") ) ) + { + m_csLastError.Format ( _T("Authentication UserName failed") ); + return FALSE; + } + + if ( !Send ( _T("%s\r\n"), csBase64_Passwd ) ) return FALSE; + if ( !GetResponse ( _T("235") ) ) + { + m_csLastError.Format ( _T("Authentication Password failed") ); + return FALSE; + } + + return TRUE; +} + +BOOL CHwSMTP::SendHead() +{ + if ( !Send ( _T("MAIL From: <%s>\r\n"), m_csAddrFrom ) ) return FALSE; + if ( !GetResponse ( _T("250") ) ) return FALSE; + if ( !Send ( _T("RCPT TO: <%s>\r\n"), m_csAddrTo ) ) return FALSE; + if ( !GetResponse ( _T("250") ) ) return FALSE; + + for ( int i=0; i\r\n"), m_StrAryCC.GetAt(i) ) ) return FALSE; + if ( !GetResponse ( _T("250") ) ) return FALSE; + } + if ( !Send ( _T("DATA\r\n") ) ) return FALSE; + if ( !GetResponse ( _T("354") ) ) return FALSE; + + return TRUE; +} + +BOOL CHwSMTP::SendSubject() +{ + CString csSubject; + csSubject += _T("Date: "); + COleDateTime tNow = COleDateTime::GetCurrentTime(); + if ( tNow > 1 ) + { + csSubject += GetCompatibleString(FormatDateTime (tNow, _T("%a, %d %b %y %H:%M:%S %Z")).GetBuffer(0),FALSE); + } + csSubject += _T("\r\n"); + csSubject += FormatString ( _T("From: %s\r\nTo: %s\r\n"), m_csSenderName, m_csReceiverName ); + csSubject += FormatString ( _T("Subject: %s\r\n"), m_csSubject ); + csSubject += FormatString ( _T("X-Mailer: chrys\r\nMIME-Version: 1.0\r\nContent-Type: %s; %s boundary=%s\r\n\r\n") , + m_csMIMEContentType, m_csCharSet, m_csPartBoundary ); + + return Send ( csSubject ); +} + +BOOL CHwSMTP::SendBody() +{ + CString csBody, csTemp; + + if ( m_StrAryAttach.GetSize() > 0 ) + { + csTemp.Format ( _T("%s\r\n\r\n"), m_csNoMIMEText ); + csBody += csTemp; + + csTemp.Format ( _T("--%s\r\n"), m_csPartBoundary ); + csBody += csTemp; + + csTemp.Format ( _T("Content-Type: text/plain\r\n%sContent-Transfer-Encoding: 7Bit\r\n\r\n"), + m_csCharSet ); + csBody += csTemp; + } + + csTemp.Format ( _T("%s\r\n"), m_csBody ); + csBody += csTemp; + + if ( m_StrAryAttach.GetSize() > 0 ) + { + csTemp.Format ( _T("--%s\r\n"), m_csPartBoundary ); + csBody += csTemp; + } + + return Send ( csBody ); +} + +BOOL CHwSMTP::SendAttach() +{ + int nCountAttach = (int)m_StrAryAttach.GetSize(); + if ( nCountAttach < 1 ) return TRUE; + + for ( int i=0; i 5*1024*1024 ) + { + m_csLastError.Format ( _T("File [%s] too big. File size is : %s"), lpszFileName, FormatBytes(dwFileSize) ); + return FALSE; + } + char *pBuf = new char[dwFileSize+1]; + if ( !pBuf ) + { + ::AfxThrowMemoryException (); + return FALSE; + } + + CFile file; + try + { + if ( !file.Open ( lpszFileName, CFile::modeRead ) ) + { + m_csLastError.Format ( _T("Open file [%s] failed"), lpszFileName ); + return FALSE; + } + UINT nFileLen = file.Read ( pBuf, dwFileSize ); + CBase64 Base64Encode; + csTemp = Base64Encode.Encode ( pBuf, nFileLen ); + csAttach += csTemp; + csAttach += _T("\r\n\r\n"); + } + catch ( CFileException e ) + { + e.Delete(); + m_csLastError.Format ( _T("Read file [%s] failed"), lpszFileName ); + delete[] pBuf; + return FALSE; + } + + csTemp.Format ( _T("--%s\r\n"), m_csPartBoundary ); + csAttach += csTemp; + + delete[] pBuf; + + return Send ( csAttach ); +} + +CString CHwSMTP::GetLastErrorText() +{ + return m_csLastError; +} + + +DWORD WINAPI ThreadProc_SendEmail( LPVOID lpParameter ) +{ + CEMailObject *pEMailObject = (CEMailObject*)lpParameter; + ASSERT ( pEMailObject ); + + CHwSMTP HwSMTP; + BOOL bRet = HwSMTP.SendEmail ( + pEMailObject->m_csSmtpSrvHost, + pEMailObject->m_csUserName, + pEMailObject->m_csPasswd, + pEMailObject->m_bMustAuth, + pEMailObject->m_csAddrFrom, + pEMailObject->m_csAddrTo, + pEMailObject->m_csSenderName, + pEMailObject->m_csReceiverName, + pEMailObject->m_csSubject, + pEMailObject->m_csBody, + pEMailObject->m_csCharSet, + &pEMailObject->m_StrAryAttach, + &pEMailObject->m_StrAryCC, + pEMailObject->m_nSmtpSrvPort + ); + if ( !bRet) + { +#ifdef _DEBUG + CString csError = HwSMTP.GetLastErrorText (); + csError = FormatString ( _T("Send a email to [%s] failed."), pEMailObject->m_csSmtpSrvHost ); + AfxMessageBox ( csError ); +#endif + } + + m_CSFor__g_PtrAry_Threads.Lock (); + int nFindPos = FindFromArray ( g_PtrAry_Threads, pEMailObject->m_hThread ); + if ( nFindPos >= 0 ) + g_PtrAry_Threads.RemoveAt ( nFindPos ); + m_CSFor__g_PtrAry_Threads.Unlock (); + + delete pEMailObject; + return bRet; +} + +// +// Óà SMTP ·þÎñ·¢Ë͵ç×ÓÓʼþ£¬Èç¹ûÉèÖòÎÊý bViaThreadSend=TRUE£¬ÄÇÔÚ³ÌÐò½áÊøʱӦ¸ÃÔÚ ExitInstance() Öе÷Óà EndOfSMTP() º¯Êý +// +BOOL SendEmail ( + BOOL bViaThreadSend, + LPCTSTR lpszSmtpSrvHost, + LPCTSTR lpszUserName, + LPCTSTR lpszPasswd, + BOOL bMustAuth, + LPCTSTR lpszAddrFrom, + LPCTSTR lpszAddrTo, + LPCTSTR lpszSenderName, + LPCTSTR lpszReceiverName, + LPCTSTR lpszSubject, + LPCTSTR lpszBody, + LPCTSTR lpszCharSet/*=NULL*/, + CStringArray *pStrAryAttach/*=NULL*/, + CStringArray *pStrAryCC/*=NULL*/, + UINT nSmtpSrvPort/*=25*/ + ) +{ + if ( !lpszSmtpSrvHost || lstrlen(lpszSmtpSrvHost) < 1 || + !lpszSubject || lstrlen(lpszSubject) < 1 || + !lpszBody || lstrlen(lpszBody) < 1 ) + { + AfxMessageBox ( _T("Parameter error !") ); + return FALSE; + } + + CEMailObject *pEMailObject = new CEMailObject ( + lpszSmtpSrvHost, + lpszUserName, + lpszPasswd, + bMustAuth, + lpszAddrFrom, + lpszAddrTo, + lpszSenderName, + lpszReceiverName, + lpszSubject, + lpszBody, + lpszCharSet, + pStrAryAttach, + pStrAryCC, + nSmtpSrvPort + ); + if ( !pEMailObject ) return FALSE; + + BOOL bRet = FALSE; + if ( bViaThreadSend ) + { + DWORD dwThreadId = 0; + pEMailObject->m_hThread = ::CreateThread ( NULL, 0, ::ThreadProc_SendEmail, pEMailObject, CREATE_SUSPENDED, &dwThreadId ); + bRet = HANDLE_IS_VALID(pEMailObject->m_hThread); + m_CSFor__g_PtrAry_Threads.Lock(); + g_PtrAry_Threads.Add ( pEMailObject->m_hThread ); + m_CSFor__g_PtrAry_Threads.Unlock(); + ResumeThread ( pEMailObject->m_hThread ); + } + else + { + bRet = (BOOL)ThreadProc_SendEmail ( pEMailObject ); + } + + return bRet; +} + +void EndOfSMTP () +{ + // µÈ´ýËùÓÐÏß³ÌÖ´ÐÐÍê±Ï + for ( int i=0; i 0 ) + { + m_pszData = pOutBuf; + m_nDataSize = nOutBufSize; + } + // ×Ô¼ºÉêÇëÄڴ滺³å + else + { + m_pszData = (char*)new BYTE[m_nDataSize]; + if ( !m_pszData ) + { + ::AfxThrowMemoryException (); + return; + } + m_bNewBuffer = TRUE; + } + memset ( m_pszData, 0, m_nDataSize ); + + if ( bOrgIsUnicode ) + { + m_nCharactersNumber = WideCharToMultiByte ( CP_ACP, 0, (LPCWSTR)lpszOrg, m_nCharactersNumber, (LPSTR)m_pszData, m_nDataSize/sizeof(char)-1, NULL, NULL ); + if ( m_nCharactersNumber < 1 ) m_nCharactersNumber = (int)strlen ( m_pszData ); + } + else + { + m_nCharactersNumber = __min ( m_nCharactersNumber, (int)(m_nDataSize/sizeof(char)-1) ); + strncpy ( m_pszData, (const char*)lpszOrg, m_nCharactersNumber ); + m_nCharactersNumber = (int)strlen ( m_pszData ); + } + m_nDataSize = ( m_nCharactersNumber + 1 ) * sizeof(char); +} + +CMultiByteString::~CMultiByteString () +{ + if ( m_bNewBuffer && m_pszData ) + { + delete[] m_pszData; + } +} + +// +// ½« lpszOrg ת»»Îª¸Ã³ÌÐòʹÓõıàÂë×Ö·û´®£¬Èç¹û¸Ã³ÌÐòÊÇ UNICODE ¾ÍתΪ UNICODE£¬Èç¹ûÊÇ ANSI ¾ÍתΪ ANSI µÄ +// +CString GetCompatibleString ( LPVOID lpszOrg, BOOL bOrgIsUnicode, int nOrgLength/*=-1*/ ) +{ + if ( !lpszOrg ) return _T(""); + + TRY + { +#ifdef UNICODE + if ( bOrgIsUnicode ) + { + if ( nOrgLength > 0 ) + { + WCHAR *szRet = new WCHAR[nOrgLength+1]; + if ( !szRet ) return _T(""); + memset ( szRet, 0, (nOrgLength+1)*sizeof(WCHAR) ); + memcpy ( szRet, lpszOrg, nOrgLength*sizeof(WCHAR) ); + CString csRet = szRet; + delete[] szRet; + return csRet; + } + else if ( nOrgLength == 0 ) + return _T(""); + else + return (LPCTSTR)lpszOrg; + } + + if ( nOrgLength < 0 ) + nOrgLength = (int)strlen((const char*)lpszOrg); + int nWideCount = nOrgLength + 1; + WCHAR *wchar = new WCHAR[nWideCount]; + if ( !wchar ) return _T(""); + memset ( wchar, 0, nWideCount*sizeof(WCHAR) ); + ::MultiByteToWideChar(CP_ACP, 0, (LPCSTR)lpszOrg, nOrgLength, wchar, nWideCount); + CString csRet = wchar; + delete[] wchar; + return csRet; +#else + if ( !bOrgIsUnicode ) + { + if ( nOrgLength > 0 ) + { + char *szRet = new char[nOrgLength+1]; + if ( !szRet ) return _T(""); + memset ( szRet, 0, (nOrgLength+1)*sizeof(char) ); + memcpy ( szRet, lpszOrg, nOrgLength*sizeof(char) ); + CString csRet = szRet; + delete[] szRet; + return csRet; + } + else if ( nOrgLength == 0 ) + return _T(""); + else + return (LPCTSTR)lpszOrg; + } + + if ( nOrgLength < 0 ) + nOrgLength = (int)wcslen((WCHAR*)lpszOrg); + int nMultiByteCount = nOrgLength + 1; + char *szMultiByte = new char[nMultiByteCount]; + if ( !szMultiByte ) return _T(""); + memset ( szMultiByte, 0, nMultiByteCount*sizeof(char) ); + ::WideCharToMultiByte ( CP_ACP, 0, (LPCWSTR)lpszOrg, nOrgLength, (LPSTR)szMultiByte, nMultiByteCount, NULL, NULL ); + CString csRet = szMultiByte; + delete[] szMultiByte; + return csRet; +#endif + } + CATCH_ALL(e) + { + THROW_LAST (); + } + END_CATCH_ALL + + return _T(""); +} + +CString FormatDateTime ( COleDateTime &DateTime, LPCTSTR pFormat ) +{ + // If null, return empty string + if ( DateTime.GetStatus() == COleDateTime::null || DateTime.GetStatus() == COleDateTime::invalid ) + return _T(""); + + UDATE ud; + if (S_OK != VarUdateFromDate(DateTime.m_dt, 0, &ud)) + { + return _T(""); + } + + struct tm tmTemp; + tmTemp.tm_sec = ud.st.wSecond; + tmTemp.tm_min = ud.st.wMinute; + tmTemp.tm_hour = ud.st.wHour; + tmTemp.tm_mday = ud.st.wDay; + tmTemp.tm_mon = ud.st.wMonth - 1; + tmTemp.tm_year = ud.st.wYear - 1900; + tmTemp.tm_wday = ud.st.wDayOfWeek; + tmTemp.tm_yday = ud.wDayOfYear - 1; + tmTemp.tm_isdst = 0; + + CString strDate; + LPTSTR lpszTemp = strDate.GetBufferSetLength(256); + _tcsftime(lpszTemp, strDate.GetLength(), pFormat, &tmTemp); + strDate.ReleaseBuffer(); + + return strDate; +} + +CString FormatString ( LPCTSTR lpszStr, ... ) +{ + TCHAR *buf = NULL; + // Ñ­»·¸ñʽ»¯×Ö·û´®£¬Èç¹û»º³å²»¹»Ôò½«»º³å¼Ó´óÈ»ºóÖØÊÔÒÔ±£Ö¤»º³å¹»ÓÃͬʱÓÖ²»ÀË·Ñ + for ( int nBufCount = 1024; nBufCount<5*1024*1024; nBufCount += 1024 ) + { + buf = new TCHAR[nBufCount]; + if ( !buf ) + { + ::AfxThrowMemoryException (); + return _T(""); + } + memset ( buf, 0, nBufCount*sizeof(TCHAR) ); + + va_list va; + va_start (va, lpszStr); + int nLen = _vsnprintf_hw ((TCHAR*)buf, nBufCount-sizeof(TCHAR), lpszStr, va); + va_end(va); + if ( nLen <= (int)(nBufCount-sizeof(TCHAR)) ) + break; + delete[] buf; buf = NULL; + } + if ( !buf ) + { + return _T(""); + } + + CString csMsg = buf; + delete[] buf; buf = NULL; + return csMsg; +} + +/******************************************************************************** +* Function Type : Global +* Parameter : lpFileName - Îļþ·¾¶ +* Return Value : -1 - ʧ°Ü +* >=0 - Îļþ´óС +* Description : »ñÈ¡ÎļþÊôÐÔ ( Îļþ´óС¡¢´´½¨Ê±¼ä ) +*********************************************************************************/ +int hwGetFileAttr ( LPCTSTR lpFileName, OUT CFileStatus *pFileStatus/*=NULL*/ ) +{ + if ( !lpFileName || lstrlen(lpFileName) < 1 ) return -1; + + CFileStatus fileStatus; + fileStatus.m_attribute = 0; + fileStatus.m_size = 0; + memset ( fileStatus.m_szFullName, 0, sizeof(fileStatus.m_szFullName) ); + BOOL bRet = FALSE; + TRY + { + if ( CFile::GetStatus(lpFileName,fileStatus) ) + { + bRet = TRUE; + } + } + CATCH (CFileException, e) + { + ASSERT ( FALSE ); + bRet = FALSE; + } + CATCH_ALL(e) + { + ASSERT ( FALSE ); + bRet = FALSE; + } + END_CATCH_ALL; + + if ( pFileStatus ) + { + pFileStatus->m_ctime = fileStatus.m_ctime; + pFileStatus->m_mtime = fileStatus.m_mtime; + pFileStatus->m_atime = fileStatus.m_atime; + pFileStatus->m_size = fileStatus.m_size; + pFileStatus->m_attribute = fileStatus.m_attribute; + pFileStatus->_m_padding = fileStatus._m_padding; + lstrcpy ( pFileStatus->m_szFullName, fileStatus.m_szFullName ); + + } + + return (int)fileStatus.m_size; +} + +// +// ½«Ò»¸ö±íʾ×Ö½ÚµÄÊýÓÿɶÁÐԺõÄ×Ö·û´®À´±íʾ£¬ÀýÈ罫 12345678 ×Ö½Úת»»Îª£º +// 11.77M +// nFlag - 0 : ×Ô¶¯Æ¥Å䵥λ +// 1 : ÒÔ Kb Ϊµ¥Î» +// 2 : ÒÔ Mb Ϊµ¥Î» +// 3 : ÒÔ Gb Ϊµ¥Î» +// +CString FormatBytes ( double fBytesNum, BOOL bShowUnit/*=TRUE*/, int nFlag/*=0*/ ) +{ + CString csRes; + if ( nFlag == 0 ) + { + if ( fBytesNum >= 1024.0 && fBytesNum < 1024.0*1024.0 ) + csRes.Format ( _T("%.2f%s"), fBytesNum / 1024.0, bShowUnit?_T(" K"):_T("") ); + else if ( fBytesNum >= 1024.0*1024.0 && fBytesNum < 1024.0*1024.0*1024.0 ) + csRes.Format ( _T("%.2f%s"), fBytesNum / (1024.0*1024.0), bShowUnit?_T(" M"):_T("") ); + else if ( fBytesNum >= 1024.0*1024.0*1024.0 ) + csRes.Format ( _T("%.2f%s"), fBytesNum / (1024.0*1024.0*1024.0), bShowUnit?_T(" G"):_T("") ); + else + csRes.Format ( _T("%.2f%s"), fBytesNum, bShowUnit?_T(" B"):_T("") ); + } + else if ( nFlag == 1 ) + { + csRes.Format ( _T("%.2f%s"), fBytesNum / 1024.0, bShowUnit?_T(" K"):_T("") ); + } + else if ( nFlag == 2 ) + { + csRes.Format ( _T("%.2f%s"), fBytesNum / (1024.0*1024.0), bShowUnit?_T(" M"):_T("") ); + } + else if ( nFlag == 3 ) + { + csRes.Format ( _T("%.2f%s"), fBytesNum / (1024.0*1024.0*1024.0), bShowUnit?_T(" G"):_T("") ); + } + + return csRes; +} + +// +// µÈ´ýÏß³ÌÍ˳ö +// +BOOL WaitForThreadEnd ( HANDLE *phThread, DWORD dwWaitTime /*=10*1000*/ ) +{ + BOOL bRet = TRUE; + ASSERT ( phThread ); + if ( !(*phThread) ) return TRUE; + if ( ::WaitForSingleObject ( *phThread, dwWaitTime ) == WAIT_TIMEOUT ) + { + bRet = FALSE; + ::TerminateThread ( *phThread, 0 ); + } + ::CloseHandle ( *phThread ); + (*phThread) = NULL; + return bRet; +} diff --git a/src/Utils/HwSMTP.h b/src/Utils/HwSMTP.h new file mode 100644 index 0000000..5d8454f --- /dev/null +++ b/src/Utils/HwSMTP.h @@ -0,0 +1,127 @@ +// HwSMTP.h: interface for the CHwSMTP class. +// +////////////////////////////////////////////////////////////////////// + +/******************************************************************* + ˵Ã÷ + 1¡¢ÕâÊÇÎÒ×Ô¼ºÐ´µÄÒ»¸öÀûÓÃSMTP·þÎñÆ÷·¢ËÍÓʼþµÄÀ࣬¿ÉÒÔʵÏÖ¸½¼þµÄ +·¢ËÍ¡£ + 2¡¢ÔÚ InitInstance() º¯Êýµ÷Óà + if (!AfxSocketInit()) + { + AfxMessageBox(IDP_SOCKETS_INIT_FAILED); + return FALSE; + } + ÔÚ ExitInstance () Öе÷Óà ::WSACleanup (); +*******************************************************************/ + +/**************************************************************************************************************** +Ͷ¸å˵Ã÷£º +****************************************************************************************************************/ +#define NOTE_SpeedPostMail \ +_T("\ + ¡¾Èí¼þÃû³Æ¡¿\r\n\ + ÎÞÐëSMTP·þÎñÆ÷ÖÐתֱ½Ó½«E-Mailµç×ÓÓʼþ·¢Ë͵½¶Ô·½ÓÊÏä\r\n\ + ¡¾°æ ±¾¡¿\r\n\ + 1.0.0\r\n\ + ¡¾²Ù×÷ϵͳ¡¿\r\n\ + Windows ×ÀÃæϵÁÐ\r\n\ + ¡¾×÷ Õß¡¿\r\n\ + лºìΰ ¡¤ chrys ¡¤ chrys@163.com ¡¤ http://www.viction.net\r\n\ + ¡¾Èí¼þ˵Ã÷¡¿\r\n\ + ´ó¼ÒÒ»¶¨ÊìϤFoxmailÖеġ°ÌØ¿ìרµÝ¡±£¬ËüÄÜÖ±½Ó½«Óʼþ·¢Ë͵½¶Ô·½µÄÓʼþ·þÎñÆ÷ÖУ¬¶ø²»ÐèÒª¾­¹ýSMTP·þÎñÆ÷ÖÐת£¬\ +±¾´úÂ뽫ÏòÄãÆÊÎö¡°ÌØ¿ìרµÝ¡±·¢Ë͵ç×ÓÓʼþµÄ·½·¨¡£´úÂëÖÐÌṩÁËÍø¿¨ÐÅÏ¢»ñÈ¡À࣬¿ÉÒÔ»ñÈ¡±¾»úIPµØÖ·¡¢×ÓÍøÑÚÂë¡¢DNS¡¢\ +Wins¡¢Íø¿¨MACµØÖ·µÈÏà¹ØÐÅÏ¢£»»¹ÌṩÁËSMTPЭÒé½âÎöÀ࣬¸ÃÀàʵÏÖÁËSMTP¿Í»§¶Ë¹¦ÄܵÄʵÏÖÀ࣬ʵÏÖµç×ÓÓʼþÊÕ·¢£»Base64±àÂëʵÏÖ\ +ÁË×Ö·û±àÂëµÄ·½·¨¡£\r\n\ + Äã¿ÉÒÔÈÎÒâÐ޸ĸ´ÖƱ¾´úÂ룬µ«Çë±£ÁôÕâ¶ÎÎÄ×Ö²»ÒªÐ޸ġ£\r\n\ + Ï£ÍûÎÒÄÜΪÖйúµÄÈí¼þÐÐÒµ¾¡Ò»·Ý±¡Á¦£¡\r\n\ + ¡¾¿ª·¢ÈÕÆÚ¡¿\r\n\ + 2008-11-23 3:54\r\n") + +#include + +#if !defined(AFX_HwSMTP_H__633A52B7_1CBE_41D7_BDA3_188D98D692AF__INCLUDED_) +#define AFX_HwSMTP_H__633A52B7_1CBE_41D7_BDA3_188D98D692AF__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class CHwSMTP +{ +public: + CString GetLastErrorText(); + BOOL SendEmail ( + LPCTSTR lpszSmtpSrvHost, + LPCTSTR lpszUserName, + LPCTSTR lpszPasswd, + BOOL bMustAuth, + LPCTSTR lpszAddrFrom, + LPCTSTR lpszAddrTo, + LPCTSTR lpszSenderName, + LPCTSTR lpszReceiverName, + LPCTSTR lpszSubject, + LPCTSTR lpszBody, + LPCTSTR lpszCharSet, // ×Ö·û¼¯ÀàÐÍ£¬ÀýÈ磺·±ÌåÖÐÎÄÕâÀïÓ¦ÊäÈë"big5"£¬¼òÌåÖÐÎÄʱÊäÈë"gb2312" + CStringArray *pStrAryAttach=NULL, + CStringArray *pStrAryCC=NULL, + UINT nSmtpSrvPort=25 + ); + CHwSMTP(); + virtual ~CHwSMTP(); + +private: + BOOL SendSubject(); + CStringArray m_StrAryCC; + BOOL SendHead(); + BOOL auth(); + BOOL SendEmail(); + BOOL Send ( LPCTSTR lpszData, ... ); + BOOL GetResponse( LPCTSTR lpszVerifyCode, int *pnCode=NULL ); + BOOL m_bConnected; + CSocket m_SendSock; + CStringArray m_StrAryAttach; + CString m_csSmtpSrvHost; + CString m_csUserName; + CString m_csPasswd; + CString m_csAddrFrom; + CString m_csAddrTo; + CString m_csSenderName; + CString m_csReceiverName; + CString m_csSubject; + CString m_csBody; +private: + BOOL m_bMustAuth; + UINT m_nSmtpSrvPort; + CString m_csCharSet; + + CString m_csLastError; + BOOL SendOnAttach(LPCTSTR lpszFileName); + BOOL SendAttach(); + BOOL SendBody(); + CString m_csMIMEContentType; + CString m_csPartBoundary; + CString m_csNoMIMEText; + +}; + +BOOL SendEmail ( + BOOL bViaThreadSend, // FALSE - Ö±½Ó·¢ËÍ£¬ TRUE - ÔÚÏß³ÌÖз¢ËÍ£¬·µ»ØÏ߳̾ä±ú + LPCTSTR lpszSmtpSrvHost, // SMTP ·þÎñÆ÷£¬È磺smtp.21cn.com + LPCTSTR lpszUserName, // µÇ¼·þÎñÆ÷ÑéÖ¤Éí·ÝµÄÓû§Ãû + LPCTSTR lpszPasswd, // µÇ¼·þÎñÆ÷ÑéÖ¤Éí·ÝµÄÃÜÂë + BOOL bMustAuth, // SMTP ·þÎñÆ÷ÐèÒªÉí·ÝÑéÖ¤ + LPCTSTR lpszAddrFrom, // ·¢ËÍÕß E-Mail µØÖ· + LPCTSTR lpszAddrTo, // ½ÓÊÕÕßµÄ E-Mail µØÖ· + LPCTSTR lpszSenderName, // ·¢ËÍÕßµÄÃû×Ö£¬ÀýÈ磺лºìΰ + LPCTSTR lpszReceiverName, // ½ÓÊÕÕßµÄÃû×Ö£¬ÀýÈ磺ÕÅ·É + LPCTSTR lpszSubject, // ÓʼþÖ÷Ìâ + LPCTSTR lpszBody, // ÓʼþÄÚÈÝ + LPCTSTR lpszCharSet=NULL, // ×Ö·û¼¯ÀàÐÍ£¬ÀýÈ磺·±ÌåÖÐÎÄÕâÀïÓ¦ÊäÈë"big5"£¬¼òÌåÖÐÎÄʱÊäÈë"gb2312" + CStringArray *pStrAryAttach=NULL, // ¸½¼þÎļþ·¾¶£¬¿ÉÒÔ¶à¸ö + CStringArray *pStrAryCC=NULL, // ³­ËÍ E-Mail µØÖ·£¬¿ÉÒÔ¶à¸ö + UINT nSmtpSrvPort=25 // SMTP ·þÎñÆ÷µÄ TCP ¶Ë¿ÚºÅ + ); +void EndOfSMTP (); + +#endif // !defined(AFX_HwSMTP_H__633A52B7_1CBE_41D7_BDA3_188D98D692AF__INCLUDED_) diff --git a/src/Utils/NetAdapterInfo.cpp b/src/Utils/NetAdapterInfo.cpp new file mode 100644 index 0000000..d993a90 --- /dev/null +++ b/src/Utils/NetAdapterInfo.cpp @@ -0,0 +1,581 @@ +// OneNetAdapterInfo.cpp: implementation of the COneNetAdapterInfo class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "SpeedPostEmail.h" +#include "NetAdapterInfo.h" +#include "Iphlpapi.h" +#include "IpTypes.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +#define MALLOC( bytes ) ::HeapAlloc( ::GetProcessHeap(), HEAP_ZERO_MEMORY, (bytes) ) +#define FREE( ptr ) if( ptr ) ::HeapFree( ::GetProcessHeap(), 0, ptr ) +#define REMALLOC( ptr, bytes ) ::HeapReAlloc( ::GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, bytes ) + +#pragma comment ( lib, "iphlpapi.lib" ) + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// +COneNetAdapterInfo::COneNetAdapterInfo ( IP_ADAPTER_INFO *pAdptInfo ) +{ + m_bInitOk = FALSE; + memset ( &m_PhysicalAddress, 0, sizeof(m_PhysicalAddress) ); + m_nPhysicalAddressLength = 0; + ASSERT ( pAdptInfo ); + memcpy ( &m_AdptInfo, pAdptInfo, sizeof(IP_ADAPTER_INFO) ); + if ( !Init() ) + { + TRACE ( _T("[%s - %s] initialize failed."), Get_Name(), Get_Desc() ); + } +} + +COneNetAdapterInfo::~COneNetAdapterInfo() +{ + +} + +// +// ¸ù¾Ý´«ÈëµÄ pAdptInfo ÐÅÏ¢À´»ñÈ¡Ö¸¶¨Íø¿¨µÄ»ù±¾ÐÅÏ¢ +// +BOOL COneNetAdapterInfo::Init () +{ + IP_ADDR_STRING* pNext = NULL; + IP_PER_ADAPTER_INFO* pPerAdapt = NULL; + ULONG ulLen = 0; + DWORD dwErr = ERROR_SUCCESS; + ASSERT ( m_AdptInfo.AddressLength > 0 ); + t_IPINFO iphold; + + // ½«±äÁ¿Çå¿Õ + m_bInitOk = FALSE; + m_csName.Empty (); + m_csDesc.Empty (); + m_CurIPInfo.csIP.Empty (); + m_CurIPInfo.csSubnet.Empty (); + m_Ary_IP.RemoveAll (); + m_Ary_DNS.RemoveAll (); + m_Ary_Gateway.RemoveAll (); + +#ifndef _UNICODE + m_csName = m_AdptInfo.AdapterName; + m_csDesc = m_AdptInfo.Description; +#else + USES_CONVERSION; + m_csName = A2W ( m_AdptInfo.AdapterName ); + m_csDesc = A2W ( m_AdptInfo.Description ); +#endif + + // »ñÈ¡µ±Ç°ÕýÔÚʹÓõÄIPµØÖ· + if ( m_AdptInfo.CurrentIpAddress ) + { + m_CurIPInfo.csIP = m_AdptInfo.CurrentIpAddress->IpAddress.String; + m_CurIPInfo.csSubnet = m_AdptInfo.CurrentIpAddress->IpMask.String; + } + else + { + m_CurIPInfo.csIP = _T("0.0.0.0"); + m_CurIPInfo.csSubnet = _T("0.0.0.0"); + } + + // »ñÈ¡±¾Íø¿¨ÖÐËùÓеÄIPµØÖ· + pNext = &( m_AdptInfo.IpAddressList ); + while ( pNext ) + { + iphold.csIP = pNext->IpAddress.String; + iphold.csSubnet = pNext->IpMask.String; + m_Ary_IP.Add ( iphold ); + pNext = pNext->Next; + } + + // »ñÈ¡±¾Íø¿¨ÖÐËùÓеÄÍø¹ØÐÅÏ¢ + pNext = &( m_AdptInfo.GatewayList ); + while ( pNext ) + { + m_Ary_Gateway.Add ( A2W( pNext->IpAddress.String )); + pNext = pNext->Next; + } + + // »ñÈ¡±¾Íø¿¨ÖÐËùÓÐµÄ DNS + dwErr = ::GetPerAdapterInfo ( m_AdptInfo.Index, pPerAdapt, &ulLen ); + if( dwErr == ERROR_BUFFER_OVERFLOW ) + { + pPerAdapt = ( IP_PER_ADAPTER_INFO* ) MALLOC( ulLen ); + dwErr = ::GetPerAdapterInfo( m_AdptInfo.Index, pPerAdapt, &ulLen ); + + // if we succeed than we need to drop into our loop + // and fill the dns array will all available IP + // addresses. + if( dwErr == ERROR_SUCCESS ) + { + pNext = &( pPerAdapt->DnsServerList ); + while( pNext ) + { + m_Ary_DNS.Add( A2W( pNext->IpAddress.String ) ); + pNext = pNext->Next; + } + m_bInitOk = TRUE; + } + + // this is done outside the dwErr == ERROR_SUCCES just in case. the macro + // uses NULL pointer checking so it is ok if pPerAdapt was never allocated. + FREE( pPerAdapt ); + } + + return m_bInitOk; +} + +// +// ÊÍ·Å»òˢб¾Íø¿¨µÄIPµØÖ· +// +BOOL COneNetAdapterInfo::RenewReleaseIP( Func_OperateIP func ) +{ + IP_INTERFACE_INFO* pInfo = NULL; + BOOL bDidIt = FALSE; + ULONG ulLen = 0; + int nNumInterfaces = 0; + int nCnt = 0; + DWORD dwErr = ERROR_SUCCESS; + + dwErr = ::GetInterfaceInfo ( pInfo, &ulLen ); + if( dwErr == ERROR_INSUFFICIENT_BUFFER ) + { + pInfo = ( IP_INTERFACE_INFO* ) MALLOC( ulLen ); + dwErr = ::GetInterfaceInfo ( pInfo, &ulLen ); + + if( dwErr != ERROR_SUCCESS ) + { + return FALSE; + } + } + + // we can assume from here out that we have a valid array + // of IP_INTERFACE_INFO structures due to the error + // checking one above. + nNumInterfaces = ulLen / sizeof( IP_INTERFACE_INFO ); + for( nCnt = 0; nCnt < nNumInterfaces; nCnt++ ) + { + if( pInfo[ nCnt ].Adapter[ 0 ].Index == m_AdptInfo.Index ) + { + dwErr = func( &pInfo[ nCnt ].Adapter[ 0 ] ); + + // free all used memory since we don't need it any more. + FREE( pInfo ); + + bDidIt = ( dwErr == NO_ERROR ); + if( ! bDidIt ) { + return FALSE; + } + + break; + } + } + + return bDidIt; +} + +//////////////////////////////////////////////////////////// +// Desc: +// Releases the addresses held by this adapter. +//////////////////////////////////////////////////////////// +BOOL COneNetAdapterInfo::ReleaseIP() +{ + return RenewReleaseIP ( ::IpReleaseAddress ); +} + +//////////////////////////////////////////////////////////// +// Desc: +// Renews the address being held by this adapter. +//////////////////////////////////////////////////////////// +BOOL COneNetAdapterInfo::RenewIP() +{ + return RenewReleaseIP ( ::IpRenewAddress ); +} + +CString COneNetAdapterInfo::GetAdapterTypeString () +{ + UINT nType = m_AdptInfo.Type; + CString csType = _T(""); + switch( nType ) + { + case MIB_IF_TYPE_OTHER: csType = _T("Other"); break; + case MIB_IF_TYPE_ETHERNET: csType = _T("Ethernet"); break; + case MIB_IF_TYPE_TOKENRING: csType = _T("Token Ring"); break; + case MIB_IF_TYPE_FDDI: csType = _T("FDDI"); break; + case MIB_IF_TYPE_PPP: csType = _T("PPP"); break; + case MIB_IF_TYPE_LOOPBACK: csType = _T("Loopback"); break; + case MIB_IF_TYPE_SLIP: csType = _T("SLIP"); break; + default: csType = _T("Invalid Adapter Type"); break; + }; + + return csType; +} + +time_t COneNetAdapterInfo::Get_LeaseObtained() const { return m_AdptInfo.LeaseObtained; } +time_t COneNetAdapterInfo::Get_LeaseExpired() const { return m_AdptInfo.LeaseExpires; } +int COneNetAdapterInfo::Get_IPCount() const { return (int)m_Ary_IP.GetSize(); } +int COneNetAdapterInfo::Get_DNSCount() const { return (int)m_Ary_DNS.GetSize(); } +CString COneNetAdapterInfo::Get_CurrentIP() const { return m_CurIPInfo.csIP; } +BOOL COneNetAdapterInfo::Is_DHCP_Used() const { return m_AdptInfo.DhcpEnabled; } +CString COneNetAdapterInfo::Get_DHCPAddr() const { return m_AdptInfo.DhcpServer.IpAddress.String; } +BOOL COneNetAdapterInfo::Is_Wins_Used() const { return m_AdptInfo.HaveWins; } +CString COneNetAdapterInfo::Get_PrimaryWinsServer() const { return m_AdptInfo.PrimaryWinsServer.IpAddress.String; } +CString COneNetAdapterInfo::Get_SecondaryWinsServer() const { return m_AdptInfo.SecondaryWinsServer.IpAddress.String; } +int COneNetAdapterInfo::Get_GatewayCount() const { return m_Ary_Gateway.GetSize(); } +DWORD COneNetAdapterInfo::Get_AdapterIndex() const { return m_AdptInfo.Index; } +UINT COneNetAdapterInfo::Get_AdapterType() const { return m_AdptInfo.Type; } + +CString COneNetAdapterInfo::Get_IPAddr ( int nIndex ) const +{ + CString csAddr = _T(""); + if ( nIndex >= 0 && nIndex < m_Ary_IP.GetSize() ) + { + csAddr = m_Ary_IP.GetAt(nIndex).csIP; + } + + return csAddr; +} + +CString COneNetAdapterInfo::Get_Subnet ( int nIndex ) const +{ + CString csAddr = _T(""); + if ( nIndex >= 0 && nIndex < m_Ary_IP.GetSize() ) + { + csAddr = m_Ary_IP.GetAt(nIndex).csSubnet; + } + + return csAddr; +} + +CString COneNetAdapterInfo::Get_DNSAddr ( int nIndex ) const +{ + CString csAddr = _T(""); + if ( nIndex >= 0 && nIndex < m_Ary_DNS.GetSize() ) + { + csAddr = m_Ary_DNS.GetAt(nIndex); + } + + return csAddr; +} + +CString COneNetAdapterInfo::Get_GatewayAddr ( int nIndex ) const +{ + CString csAddr = _T(""); + if ( nIndex >= 0 && nIndex < m_Ary_Gateway.GetSize() ) + { + csAddr = m_Ary_Gateway.GetAt(nIndex); + } + + return csAddr; +} + +void COneNetAdapterInfo::Set_PhysicalAddress ( int nPhysicalAddressLength, BYTE *pPhysicalAddress ) +{ + if ( !pPhysicalAddress ) return; + m_nPhysicalAddressLength = __min(nPhysicalAddressLength,sizeof(m_PhysicalAddress)); + memcpy ( m_PhysicalAddress, pPhysicalAddress, m_nPhysicalAddressLength ); +} + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CNetAdapterInfo::CNetAdapterInfo () +{ +} + +CNetAdapterInfo::~CNetAdapterInfo() +{ + DeleteAllNetAdapterInfo (); +} + +void CNetAdapterInfo::DeleteAllNetAdapterInfo() +{ + for ( int i=0; i=0 - ÍøÂçÊÊÅäÆ÷ÊýÁ¿ +// +int CNetAdapterInfo::EnumNetworkAdapters () +{ + DeleteAllNetAdapterInfo (); + + IP_ADAPTER_INFO* pAdptInfo = NULL; + IP_ADAPTER_INFO* pNextAd = NULL; + ULONG ulLen = 0; + int nCnt = 0; + + DWORD dwError = ::GetAdaptersInfo ( pAdptInfo, &ulLen ); + if( dwError != ERROR_BUFFER_OVERFLOW ) return -1; + pAdptInfo = ( IP_ADAPTER_INFO* )MALLOC ( ulLen ); + dwError = ::GetAdaptersInfo( pAdptInfo, &ulLen ); + if ( dwError != ERROR_SUCCESS ) return -1; + + pNextAd = pAdptInfo; + while( pNextAd ) + { + COneNetAdapterInfo *pOneNetAdapterInfo = new COneNetAdapterInfo ( pNextAd ); + if ( pOneNetAdapterInfo ) + { + m_Ary_NetAdapterInfo.Add ( pOneNetAdapterInfo ); + } + nCnt ++; + pNextAd = pNextAd->Next; + } + + // free any memory we allocated from the heap before + // exit. we wouldn't wanna leave memory leaks now would we? ;p + FREE( pAdptInfo ); + + return nCnt; +} + +COneNetAdapterInfo* CNetAdapterInfo::Get_OneNetAdapterInfo ( int nIndex ) +{ + if ( nIndex < 0 || nIndex >= m_Ary_NetAdapterInfo.GetSize() ) + { + ASSERT ( FALSE ); + return NULL; + } + + return (COneNetAdapterInfo*)m_Ary_NetAdapterInfo.GetAt(nIndex); +} + +COneNetAdapterInfo* CNetAdapterInfo::Get_OneNetAdapterInfo ( DWORD dwIndex ) +{ + for ( int i=0; iGet_AdapterIndex() == dwIndex ) + return pOneNetAdapterInfo; + } + + return NULL; +} + +void CNetAdapterInfo::Refresh () +{ + DeleteAllNetAdapterInfo (); + EnumNetworkAdapters (); + GetAdapterAddress (); +} + +// +// »ñÈ¡Íø¿¨µÄµØÖ·ÐÅÏ¢£¬Ö÷ÒªÊÇMACµØÖ· +// +BOOL CNetAdapterInfo::GetAdapterAddress () +{ + DWORD dwSize = 0; + DWORD dwRetVal = 0; + BOOL bRet = FALSE; + + int i = 0; + + // Set the flags to pass to GetAdaptersAddresses + ULONG flags = GAA_FLAG_INCLUDE_PREFIX; + + // default to unspecified address family (both) + // AF_INET for IPv4, AF_INET6 for IPv6 + ULONG family = AF_UNSPEC; + + LPVOID lpMsgBuf = NULL; + + PIP_ADAPTER_ADDRESSES pAddresses = NULL; + ULONG outBufLen = 0; + + PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; + PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL; + PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL; + PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL; + IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL; + IP_ADAPTER_PREFIX *pPrefix = NULL; + + outBufLen = sizeof (IP_ADAPTER_ADDRESSES); + pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen); + if (pAddresses == NULL) return FALSE; + + // Make an initial call to GetAdaptersAddresses to get the + // size needed into the outBufLen variable + if ( ::GetAdaptersAddresses ( family, flags, NULL, pAddresses, &outBufLen ) == ERROR_BUFFER_OVERFLOW ) + { + FREE(pAddresses); + pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen); + } + if (pAddresses == NULL) return FALSE; + + // Make a second call to GetAdapters Addresses to get the + // actual data we want +#ifdef _DEBUG + TRACE ( _T("Memory allocated for GetAdapterAddresses = %d bytes\n"), outBufLen); + TRACE ( _T("Calling GetAdaptersAddresses function with family = " ) ); + if (family == AF_INET) + TRACE(_T("AF_INET\n")); + if (family == AF_INET6) + TRACE(_T("AF_INET6\n")); + if (family == AF_UNSPEC) + TRACE(_T("AF_UNSPEC\n\n")); +#endif + dwRetVal = GetAdaptersAddresses ( family, flags, NULL, pAddresses, &outBufLen ); + + if ( dwRetVal == NO_ERROR ) + { + // If successful, output some information from the data we received + pCurrAddresses = pAddresses; + while (pCurrAddresses) + { + TRACE(_T("\tLength of the IP_ADAPTER_ADDRESS struct: %ld\n"), + pCurrAddresses->Length); + TRACE(_T("\tIfIndex (IPv4 interface): %u\n"), pCurrAddresses->IfIndex); + TRACE(_T("\tAdapter name: %s\n"), pCurrAddresses->AdapterName); + + pUnicast = pCurrAddresses->FirstUnicastAddress; + if (pUnicast != NULL) + { + for (i = 0; pUnicast != NULL; i++) + pUnicast = pUnicast->Next; + TRACE(_T("\tNumber of Unicast Addresses: %d\n"), i); + } + else + { + TRACE(_T("\tNo Unicast Addresses\n")); + } + + pAnycast = pCurrAddresses->FirstAnycastAddress; + if (pAnycast) + { + for (i = 0; pAnycast != NULL; i++) + pAnycast = pAnycast->Next; + TRACE(_T("\tNumber of Anycast Addresses: %d\n"), i); + } + else + { + TRACE(_T("\tNo Anycast Addresses\n")); + } + + pMulticast = pCurrAddresses->FirstMulticastAddress; + if (pMulticast) + { + for (i = 0; pMulticast != NULL; i++) + pMulticast = pMulticast->Next; + TRACE(_T("\tNumber of Multicast Addresses: %d\n"), i); + } + else + { + TRACE(_T("\tNo Multicast Addresses\n")); + } + + pDnServer = pCurrAddresses->FirstDnsServerAddress; + if (pDnServer) + { + for (i = 0; pDnServer != NULL; i++) + pDnServer = pDnServer->Next; + TRACE(_T("\tNumber of DNS Server Addresses: %d\n"), i); + } + else + { + TRACE(_T("\tNo DNS Server Addresses\n")); + } + + TRACE(_T("\tDNS Suffix: %wS\n"), pCurrAddresses->DnsSuffix); + TRACE(_T("\tDescription: %wS\n"), pCurrAddresses->Description); + TRACE(_T("\tFriendly name: %wS\n"), pCurrAddresses->FriendlyName); + + if (pCurrAddresses->PhysicalAddressLength != 0) + { + TRACE(_T("\tPhysical address: ")); + for (i = 0; i < (int) pCurrAddresses->PhysicalAddressLength; i++) + { + if ( i == (int)(pCurrAddresses->PhysicalAddressLength - 1)) + TRACE(_T("%.2X\n"), (int) pCurrAddresses->PhysicalAddress[i]); + else + TRACE(_T("%.2X-"), (int) pCurrAddresses->PhysicalAddress[i]); + } + + COneNetAdapterInfo* pNetAdapterInfo = Get_OneNetAdapterInfo ( pCurrAddresses->IfIndex ); + if ( pNetAdapterInfo ) + { + pNetAdapterInfo->Set_PhysicalAddress ( pCurrAddresses->PhysicalAddressLength, pCurrAddresses->PhysicalAddress ); + } + } + TRACE(_T("\tFlags: %ld\n"), pCurrAddresses->Flags); + TRACE(_T("\tMtu: %lu\n"), pCurrAddresses->Mtu); + TRACE(_T("\tIfType: %ld\n"), pCurrAddresses->IfType); + TRACE(_T("\tOperStatus: %ld\n"), pCurrAddresses->OperStatus); + TRACE(_T("\tIpv6IfIndex (IPv6 interface): %u\n"), + pCurrAddresses->Ipv6IfIndex); + TRACE(_T("\tZoneIndices (hex): ")); + for (i = 0; i < 16; i++) + TRACE(_T("%lx "), pCurrAddresses->ZoneIndices[i]); + TRACE(_T("\n")); + + pPrefix = pCurrAddresses->FirstPrefix; + if (pPrefix) + { + for (i = 0; pPrefix != NULL; i++) + pPrefix = pPrefix->Next; + TRACE(_T("\tNumber of IP Adapter Prefix entries: %d\n"), i); + } + else + { + TRACE(_T("\tNumber of IP Adapter Prefix entries: 0\n")); + } + + TRACE(_T("\n")); + + pCurrAddresses = pCurrAddresses->Next; + bRet = TRUE; + } + } + else + { + TRACE(_T("Call to GetAdaptersAddresses failed with error: %d\n"), dwRetVal ); + if (dwRetVal == ERROR_NO_DATA) + { + TRACE(_T("\tNo addresses were found for the requested parameters\n")); + } + else + { + if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) & lpMsgBuf, 0, NULL)) + { + TRACE(_T("\tError: %s"), lpMsgBuf); + LocalFree(lpMsgBuf); + FREE(pAddresses); + } + } + bRet = FALSE; + } + FREE(pAddresses); + + return bRet; +} + +CString MacAddress2String ( int nPhysicalAddressLength, BYTE *pPhysicalAddress ) +{ + ASSERT ( nPhysicalAddressLength >= 6 ); + AfxIsValidAddress(pPhysicalAddress,nPhysicalAddressLength,TRUE); + CString csMacAddress, csOneCell; + for ( int i=0; i 1000 +#pragma once +#endif // _MSC_VER > 1000 + +/* + ˵Ã÷ + »ñÈ¡Íø¿¨ÐÅÏ¢£¬°üÀ¨IPµØÖ·¡¢DNS¡¢Íø¹Ø¡¢ÊÇ·ñΪ¶¯Ì¬IP¡¢DHCPµÈ£¬¸ÃÀ಻ÓöÁȡע²á±í¼´¿É»ñÈ¡×îеÄÍø¿¨ÐÅÏ¢ +ÁíÍ⻹¿ÉÒÔÊÍ·ÅÍø¿¨µØÖ·²¢ÖØÐÂˢеØÖ· +*/ + +#include +#include +#include + +typedef struct _IPINFO +{ + CString csIP; + CString csSubnet; +} t_IPINFO; +typedef CArray t_Ary_IPINFO; + +typedef DWORD ( __stdcall *Func_OperateIP)( PIP_ADAPTER_INDEX_MAP AdapterInfo ); +CString MacAddress2String ( int nPhysicalAddressLength, BYTE *pPhysicalAddress ); + +class COneNetAdapterInfo +{ +public: + COneNetAdapterInfo ( IP_ADAPTER_INFO *pAdptInfo ); + virtual ~COneNetAdapterInfo(); + CString Get_Name() { return m_csName; } + CString Get_Desc() { return m_csDesc; } + BOOL ReleaseIP(); + BOOL RenewIP(); + CString GetAdapterTypeString (); + + time_t Get_LeaseObtained() const; + time_t Get_LeaseExpired() const; + int Get_IPCount() const; + int Get_DNSCount() const; + CString Get_CurrentIP() const; + BOOL Is_DHCP_Used() const; + CString Get_DHCPAddr() const; + BOOL Is_Wins_Used() const; + CString Get_PrimaryWinsServer() const; + CString Get_SecondaryWinsServer() const; + int Get_GatewayCount() const; + DWORD Get_AdapterIndex() const; + UINT Get_AdapterType() const; + CString Get_IPAddr ( int nIndex ) const; + CString Get_Subnet ( int nIndex ) const; + CString Get_DNSAddr ( int nIndex ) const; + CString Get_GatewayAddr ( int nIndex ) const; + void Set_PhysicalAddress ( int nPhysicalAddressLength, BYTE *pPhysicalAddress ); + CString Get_PhysicalAddressStr () { return MacAddress2String ( m_nPhysicalAddressLength, m_PhysicalAddress ); } + +private: + BOOL Init (); + BOOL RenewReleaseIP( Func_OperateIP func ); + +public: + BOOL m_bInitOk; +private: + IP_ADAPTER_INFO m_AdptInfo; + CString m_csName; + CString m_csDesc; + t_IPINFO m_CurIPInfo; // this is also in the ip address list but this is the address currently active. + t_Ary_IPINFO m_Ary_IP; + CStringArray m_Ary_DNS; + CStringArray m_Ary_Gateway; + BYTE m_PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH]; + int m_nPhysicalAddressLength; +}; + +class CNetAdapterInfo +{ +public: + CNetAdapterInfo (); + ~CNetAdapterInfo(); + int GetNetCardCount () { return m_Ary_NetAdapterInfo.GetSize(); } + COneNetAdapterInfo* Get_OneNetAdapterInfo ( int nIndex ); + COneNetAdapterInfo* CNetAdapterInfo::Get_OneNetAdapterInfo ( DWORD dwIndex ); + void Refresh (); + +private: + int EnumNetworkAdapters (); + void DeleteAllNetAdapterInfo(); + BOOL GetAdapterAddress (); + +private: + CPtrArray m_Ary_NetAdapterInfo; +}; + +#endif // !defined(AFX_OneNetAdapterInfo_H__A899410F_5CFF_4958_80C4_D1AC693F62E3__INCLUDED_) diff --git a/src/Utils/Utils.vcproj b/src/Utils/Utils.vcproj index 341e021..df58e7c 100644 --- a/src/Utils/Utils.vcproj +++ b/src/Utils/Utils.vcproj @@ -345,6 +345,10 @@ > + + @@ -405,6 +409,14 @@ > + + + + diff --git a/src/Utils/base64.cpp b/src/Utils/base64.cpp index c1716e8..d9ac7b4 100644 --- a/src/Utils/base64.cpp +++ b/src/Utils/base64.cpp @@ -1,7 +1,7 @@ /* base64.cpp and base64.h - Copyright (C) 2004-2008 René Nyffenegger + Copyright (C) 2004-2008 Ren?Nyffenegger This source code is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages @@ -21,7 +21,7 @@ 3. This notice may not be removed or altered from any source distribution. - René Nyffenegger rene.nyffenegger@adp-gmbh.ch + Ren?Nyffenegger rene.nyffenegger@adp-gmbh.ch */ diff --git a/src/Utils/base64.h b/src/Utils/base64.h index 9e3017b..d66490f 100644 --- a/src/Utils/base64.h +++ b/src/Utils/base64.h @@ -6,4 +6,4 @@ std::string base64_encode(unsigned char const* , unsigned int len); std::string base64_decode(std::string const& s); -#endif \ No newline at end of file +#endif diff --git a/src/Utils/dnsmx.cpp b/src/Utils/dnsmx.cpp new file mode 100644 index 0000000..71de61b --- /dev/null +++ b/src/Utils/dnsmx.cpp @@ -0,0 +1,730 @@ +#include "stdafx.h" +#include "dnsmx.h" + +#define ASCII_NULL '\0' +#define MAXHOSTNAME 256 +#define BUFSIZE 2048 + +// #pragma comment ( lib, "ws2_32.lib" ) + +/* DNS Header Format +* +* All DNS Message Formats have basically the same structure +* (note that an RR (DNS Resource Record) is described in +* the other structures that follow this header description): +* +* +--------------------------------+ +* | DNS Header: | +* +--------------------------------+ +* | Question: type of query | +* | QNAME: | +* | QTYPE: 2-octet RR type | +* | QCLASS: 2-octet RR class | +* +--------------------------------+ +* | Answer: RR answer to query | +* +--------------------------------+ +* | Authority: RR for name server | +* +--------------------------------+ +* | Additional: RR(s) other info | +* +--------------------------------+ +* +* QNAME is a variable length field where each portion of the +* "dotted-notation" domain name is replaced by the number of +* octets to follow. So, for example, the domain name +* "www.sockets.com" is represented by: +* +* 0 1 +* octet 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* |3|w|w|w|7|s|o|c|k|e|t|s|3|c|o|m|0| +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* +* NOTE: The last section, "Additional," often contains records +* for queries the server anticipates will be sent (to reduce +* traffic). For example, a response to an MX query, would +* usually have the A record in additional information. +*/ +typedef struct dns_hdr +{ + USHORT dns_id; /* client query ID number */ + USHORT dns_flags; /* qualify contents */ + USHORT dns_q_count; /* number of questions */ + USHORT dns_rr_count; /* number of answer RRs */ + USHORT dns_auth_count; /* number of authority RRs */ + USHORT dns_add_count; /* number of additional RRs */ +} DNS_HDR, *PDNS_HDR, FAR *LPDNS_HDR; + +#define DNS_HDR_LEN 12 + +/* DNS Flags field values +* +* bits: 0 1-4 5 6 7 8 9-11 12-15 +* +----+--------+----+----+----+----+--------+-------+ +* | QR | opcode | AA | TC | RD | RA | | rcode | +* +----+--------+----+----+----+----+--------+-------+ +* +* QR: 0 for query, and 1 for response +* opcode: type of query (0: standard, and 1: inverse query) +* AA: set if answer from domain authority +* TC: set if message had to be truncated +* RD: set if recursive query desired +* RA: set if recursion is available from server +* : reserved field +* rcode: resulting error non-zero value from authoritative +* server (0: no error, 3: name does not exist) +*/ +#define DNS_FLAG_QR 0x8SpeedPostEmail +#define DNS_FLAG_AA 0x0400 +#define DNS_FLAG_TC 0x0200 +#define DNS_FLAG_RD 0x0100 +#define DNS_FLAG_RA 0x0080 +#define DNS_RCODE_MASK 0xSpeedPostEmailF +#define DNS_OPCODE_MASK 0x7800 + +/* DNS Opcode (type of query) */ +char *DNS_Opcode[] = +{ + "Standard Query", /* 0: QUERY */ + "Inverse Query", /* 1: IQUERY */ + "Server Status Request", /* 2: STATUS */ +}; + +/* DNS Response Codes (error descriptions) */ +char *DNS_RCode[] = +{ + "No Error", /* 0: ok */ + "Format Error", /* 1: bad query */ + "Server Failure", /* 2: server is hosed */ + "Name Error", /* 3: name doesn't exist (authoritative) */ + "Not Implemented", /* 4: server doesn't support query */ + "Refused" /* 5: server refused request */ +}; + +/* DNS Generic Resource Record format (from RFC 1034 and 1035) +* +* NOTE: The first field in the DNS RR Record header is always +* the domain name in QNAME format (see earlier description) +*/ +typedef struct dns_rr_hdr +{ + USHORT rr_type; /* RR type code (e.g. A, MX, NS, etc.) */ + USHORT rr_class; /* RR class code (IN for Internet) */ + ULONG rr_ttl; /* Time-to-live for resource */ + USHORT rr_rdlength; /* length of RDATA field (in octets) */ + USHORT rr_rdata; /* (fieldname used as a ptr) */ +} DNS_RR_HDR, *PDNS_RR_HDR, FAR *LPDNS_RR_HDR; + +#define DNS_RR_HDR_LEN 12 + +/* DNS Resource Record RDATA Field Descriptions +* +* The RDATA field contains resource record data associated +* with the specified domain name +* +* Type Value Description +* ------------------------------------------------------------- +* A 1 IP Address (32-bit IP version 4) +* NS 2 Name server QNAME (for referrals & recursive queries) +* CNAME 5 Canonical name of an alias (in QNAME format) +* SOA 6 Start of Zone Transfer (see definition below) +* WKS 11 Well-known services (see definition below) +* PTR 12 QNAME pointing to other nodes (e.g. in inverse lookups) +* HINFO 13 Host Information (CPU string, then OS string) +* MX 15 Mail server preference and QNAME (see below) +*/ +char *DNS_RR_Type [] = +{ + "", + "A", // 1: Host Address + "NS", // 2: Authoritative Name Server + "MD", // 3: + "MF", // 4: + "CNAME", // 5: The true, canonical name for an alias + "SOA", // 6: Start-of-Zone of authority record + "MB", // 7: Mailbox + "MG", // 8: Mailgroup + "MR", // 9: Mail Rename Domain Name + "NULL", // 10: NULL Resource Record + "WKS", // 11: Well-known service description + "PTR", // 12: Domain Name Pointer + "HINFO", // 13: Host Information + "MINFO", // 14: Mailbox or Mail List information + "MX", // 15: Mail Exchange (from RFC 974) + "TXT" // 16: Text String +}; + +#define DNS_RRTYPE_A 1 +#define DNS_RRTYPE_NS 2 +#define DNS_RRTYPE_CNAME 5 +#define DNS_RRTYPE_SOA 6 +#define DNS_RRTYPE_WKS 11 +#define DNS_RRTYPE_PTR 12 +#define DNS_RRTYPE_HINFO 13 +#define DNS_RRTYPE_MX 15 + +/* DNS Resource Record Classes: +* +* One almost always uses Internet RR Class (also note: the +* class value 255 denotes a wildcard, all classes) +*/ +char *DNS_RR_Class [] = +{ + "", + "IN", // 1: Internet - used for most queries! + "CS", // 2: CSNET + "CH", // 3: CHAOS Net + "HS" // 4: Hesiod +}; + +#define DNS_RRCLASS_IN 1 +#define DNS_RRCLASS_CS 2 +#define DNS_RRCLASS_CH 3 +#define DNS_RRCLASS_HS 4 + +/* DNS SOA Resource Data Field +* +* NOTE: First two fields not shown here. They are: +* MNAME: QNAME of primary server for this zone +* RNAME: QNAME of mailbox of admin for this zone +*/ +typedef struct dns_rdata_soa +{ + ULONG soa_serial; /* data version for this zone */ + ULONG soa_refresh; /* time-to-live for data (in seconds) */ + ULONG soa_retry; /* time between retrieds (in seconds) */ + ULONG soa_expire; /* time until zone not auth (in seconds) */ + ULONG soa_minimum; /* default TTL for RRs (in seconds) */ +} DNS_RDATA_SOA, PDNS_RDATA_SOA, FAR *LPDNS_RDATA_SOA; + +#define DNS_SOA_LEN 20 + +/* DNS WKS Resource Data Field (RFC 1035) +* +* NOTE: The bitmap field is variable length, with as many +* octets necessary to indicate the bit field for the port +* number. +*/ +typedef struct dns_rdata_wks +{ + ULONG wks_addr; /* IPv4 address */ + UCHAR wks_protocol; /* Protocol (e.g. 6=TCP, 17=UDP) */ + UCHAR wks_bitmap; /* e.g. bit 26 = SMTP (port 25) */ +} DNS_RDATA_WKS, *PDNS_RDATA_WKS, FAR *LPDNS_RDATA_WKS; + +#define DNS_WKX_LEN 6 + +/* DNS MX Resource Data Field +*/ +typedef struct dns_rdata_mx +{ + USHORT mx_pref; /* Preference value */ + USHORT mx_xchange; /* QNAME (field used as ptr) */ +} DNS_RDATA_MX, *PDNS_RDATA_MX, FAR *LPDNS_RDATA_MX; + +#define DNS_MX_LEN 4 + +/* Variables used for DNS Header construction & parsing */ +PDNS_HDR pDNShdr; +PDNS_RR_HDR pDNS_RR; +PDNS_RDATA_SOA pDNS_SOA; +PDNS_RDATA_WKS pDNS_WKS; +PDNS_RDATA_MX pDNS_MX; + +/* For Parsing Names in a Reply */ +#define INDIR_MASK 0xc0 + +/* Number of bytes of fixed size data in query structure */ +#define QFIXEDSZ 4 +/* number of bytes of fixed size data in resource record */ +#define RRFIXEDSZ 10 + +/* Processor Types */ +char *aszProcessor[] = +{ + "", + "", + "", + "Intel 386", + "Intel 486", + "Intel Pentium" +}; + + +void GetQName( char FAR *pszHostName, char FAR *pQName ); +void PrintQName( char FAR *pQName ); +int PutQName( char FAR *pszHostName, char FAR *pQName ); + +USHORT _getshort(char *msgp) +{ + register UCHAR *p = (UCHAR *) msgp; + register USHORT u; + + u = *p++ << 8; + return ((USHORT)(u | *p)); +} + +ULONG _getlong(char *msgp) +{ + register UCHAR *p = (UCHAR *) msgp; + register ULONG u; + + u = *p++; u <<= 8; + u |= *p++; u <<= 8; + u |= *p++; u <<= 8; + return (u | *p); +} + + +/* +* Expand compressed domain name 'comp_dn' to full domain name. +* 'msg' is a pointer to the begining of the message, +* 'eomorig' points to the first location after the message, +* 'exp_dn' is a pointer to a buffer of size 'length' for the result. +* Return size of compressed name or -1 if there was an error. +*/ +int dn_expand(char *msg,char *eomorig,char *comp_dn,char *exp_dn,int length) +{ + register char *cp, *dn; + register int n, c; + char *eom; + int len = -1, checked = 0; + + dn = exp_dn; + cp = comp_dn; + eom = exp_dn + length - 1; + /* + * fetch next label in domain name + */ + while (n = *cp++) { + /* + * Check for indirection + */ + switch (n & INDIR_MASK) { + case 0: + if (dn != exp_dn) { + if (dn >= eom) + return (-1); + *dn++ = '.'; + } + if (dn+n >= eom) + return (-1); + checked += n + 1; + while (--n >= 0) { + if ((c = *cp++) == '.') { + if (dn+n+1 >= eom) + return (-1); + *dn++ = '\\'; + } + *dn++ = c; + if (cp >= eomorig) /* out of range */ + return(-1); + } + break; + + case INDIR_MASK: + if (len < 0) + len = cp - comp_dn + 1; + cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff)); + if (cp < msg || cp >= eomorig) /* out of range */ + return(-1); + checked += 2; + /* + * Check for loops in the compressed name; + * if we've looked at the whole message, + * there must be a loop. + */ + if (checked >= eomorig - msg) + return (-1); + break; + + default: + return (-1); /* flag error */ + } + } + *dn = '\0'; + if (len < 0) + len = cp - comp_dn; + return (len); +} + +/* +* Skip over a compressed domain name. Return the size or -1. +*/ +int dn_skipname(UCHAR *comp_dn, UCHAR *eom) +{ + register UCHAR *cp; + register int n; + + cp = comp_dn; + while (cp < eom && (n = *cp++)) { + /* + * check for indirection + */ + switch (n & INDIR_MASK) { + case 0: /* normal case, n == len */ + cp += n; + continue; + default: /* illegal type */ + return (-1); + case INDIR_MASK: /* indirection */ + cp++; + } + break; + } + return (cp - comp_dn); +} + +// +// ÉèÖÃ×èÈûģʽ +// +BOOL SetBlockingMode ( SOCKET hSocket, BOOL bNonblockingEnable ) +{ + if ( hSocket == INVALID_SOCKET || hSocket == 0 ) + { + return FALSE; + } + + long cmd = FIONBIO; + long zero = 0; + u_long* argp = NULL; + if ( bNonblockingEnable ) + argp = (u_long*)&cmd; + else + argp = (u_long*)&zero; + int err = ioctlsocket ( hSocket, cmd, argp ); + if ( err != 0 ) + { + return FALSE; + } + + return TRUE; +} + + +BOOL GetMX ( + char *pszQuery, + char *pszServer, + OUT t_Ary_MXHostInfos &Ary_MXHostInfos + ) +{ + SOCKET hSocket; + SOCKADDR_IN stSockAddr; // socket address structures + int nAddrLen = sizeof( SOCKADDR_IN ); + + HOSTENT *pHostEnt; + + char achBufOut[ BUFSIZE ] = { 0 }; + char achBufIn[ BUFSIZE ] = { 0 }; + int nQueryLen = 0; + int nRC; + + char *p, *np, name[128], *eom; + int count, j, i, n; + + memset( &stSockAddr, ASCII_NULL, sizeof( stSockAddr ) ); + + stSockAddr.sin_family = AF_INET; + stSockAddr.sin_port = htons( 53); + stSockAddr.sin_addr.s_addr = inet_addr( pszServer ); + if ( stSockAddr.sin_addr.s_addr == INADDR_NONE ) + { + pHostEnt = gethostbyname( pszServer ); + if ( pHostEnt ) + { + stSockAddr.sin_addr.s_addr = *((ULONG *)pHostEnt->h_addr_list[0]); + } + else + { + return FALSE; + } // end if + } // end if + + + /*------------------------------------------------------------ + * Get a DGRAM socket + */ + + hSocket = socket( AF_INET, SOCK_DGRAM, 0 ); + + if ( hSocket == INVALID_SOCKET ) + { + return FALSE; + } // end if + + /*----------------------------------------------------------- + * Format DNS Query + */ + + pDNShdr = (PDNS_HDR)&( achBufOut[ 0 ] ); + pDNShdr->dns_id = htons( 0xDEAD ); + pDNShdr->dns_flags = htons( DNS_FLAG_RD ); // do recurse + pDNShdr->dns_q_count = htons( 1 ); // one query + pDNShdr->dns_rr_count = 0; // none in query + pDNShdr->dns_auth_count = 0; // none in query + pDNShdr->dns_add_count = 0; // none in query + + nQueryLen = PutQName( pszQuery, &(achBufOut[ DNS_HDR_LEN ] ) ); + nQueryLen += DNS_HDR_LEN; + + achBufOut[ nQueryLen++ ] = 0; + achBufOut[ nQueryLen++ ] = 0; + achBufOut[ nQueryLen ] = DNS_RRTYPE_MX; + achBufOut[ nQueryLen + 1 ] = 0; + achBufOut[ nQueryLen + 2 ] = DNS_RRCLASS_IN; + achBufOut[ nQueryLen + 3 ] = 0; + + nQueryLen += 4; + + /*----------------------------------------------------------- + * Send DNS Query to server + */ + + nRC = sendto( hSocket, + achBufOut, + nQueryLen, + 0, + (LPSOCKADDR)&stSockAddr, + sizeof( SOCKADDR_IN ) ); + + if ( nRC == SOCKET_ERROR ) + { + + closesocket( hSocket ); + return FALSE; + } + else + { + + } + +// VERIFY ( SetBlockingMode ( hSocket, TRUE ) ); + + // Óà select Ä£ÐÍʵÏÖÁ¬½Ó³¬Ê± + struct timeval timeout; + fd_set r; + FD_ZERO(&r); + FD_SET(hSocket, &r); + timeout.tv_sec = 5; //Á¬½Ó³¬Ê±Ãë + timeout.tv_usec =0; + int ret = select(0, &r, 0, 0, &timeout); + if ( ret == SOCKET_ERROR ) + { + ::closesocket(hSocket); + hSocket = SOCKET_ERROR; + return FALSE; + } + + // µÃµ½¿É¶ÁµÄÊý¾Ý³¤¶È + long cmd = FIONREAD; + u_long argp = 0; + BOOL err = ioctlsocket ( hSocket, cmd, (u_long*)&argp ); + if ( err || argp < 1 ) + { + ::closesocket(hSocket); + hSocket = SOCKET_ERROR; + return FALSE; + } + + nRC = recvfrom( hSocket, + achBufIn, + BUFSIZE, + 0, + (LPSOCKADDR)&stSockAddr, + &nAddrLen ); + + if ( nRC == SOCKET_ERROR ) + { + int nWSAErr = WSAGetLastError(); + + if ( nWSAErr != WSAETIMEDOUT ) + { + + closesocket( hSocket ); + return FALSE; + } + else + { + + closesocket( hSocket ); + return FALSE; + } + } + else + { + pDNShdr = (PDNS_HDR)&( achBufIn[ 0 ] ); + p = (char *)&pDNShdr[0]; + p+=12; + count = (int)*p; + + // Parse the Question... + for (i = 0; i< ntohs(pDNShdr->dns_q_count); i++) + { + np = name; + eom = (char *)pDNShdr+nRC; + + if ( (n = dn_expand((char *)pDNShdr, eom, p, name, 127)) < 0 ) + { + return FALSE; + + } + p += n + QFIXEDSZ; + } + + for (i = 0; i< ntohs(pDNShdr->dns_rr_count); i++) + { + + // The Question Name appears Again... + if ((n = dn_expand((char *)pDNShdr, eom, p, name, 127)) < 0) + { + return FALSE; + } + p+=n; + + + j = _getshort(p);; //TYPE + p+=2; + //printf("%s\tType:%d", name, j); + + j = _getshort(p); //CLASS + p+=2; + // printf("\tClass:%d", j); + + j = _getlong(p); //TTL + p+=4; + // printf("\tTTL:%d", j); + + j = _getshort(p); //RDLENGTH + p+=2; + // printf("\tRDLENGTH:%d", j); + + j = _getshort(p); //N?? + p+=2; + + // This should be an MX Name... + if ( (n = dn_expand((char *)pDNShdr, eom, p, name, 127)) < 0 ) + { + return FALSE; + } + + t_MXHostInfo tMXHostInfo = {0}; + strncpy ( (char*)tMXHostInfo.szMXHost, name, sizeof(tMXHostInfo.szMXHost)/sizeof(tMXHostInfo.szMXHost[0]) ); + tMXHostInfo.N = j; + Ary_MXHostInfos.Add ( tMXHostInfo ); + TRACE ( _T("%s\t%d\r\n"), name, j ); + p += n; + } + return TRUE; + + + } + + + closesocket( hSocket ); + return FALSE; +} + + +void GetQName( char FAR *pszHostName, char FAR *pQName ) +{ + + int i, j, k; + + for ( i = 0; i < BUFSIZE; i++ ) + { + j = *pQName; + + if ( j == 0 ) + break; + + for ( k = 1; k <= j; k++ ) + { + *pszHostName++ = *( pQName + i + k ); + } // end for loop + } // end for loop + + *pszHostName++ = ASCII_NULL; +} /* end GetQName() */ + + +void PrintQName( char FAR *pQName ) +{ + int i, j, k; + + for ( i = 0; i < BUFSIZE; i++ ) + { + j = *pQName; + + if ( j == 0 ) + break; + + for ( k = 1; k <= j; k++ ) + { + //printf( "%c", *( pQName + i + k ) ); + } // end for loop + } // end for loop +} /* end PrintQName() */ + + +int PutQName( char FAR *pszHostName, char FAR *pQName ) +{ + int i; + int j = 0; + int k = 0; + + + for ( i = 0; *( pszHostName + i ); i++ ) + { + char c = *( pszHostName + i ); /* get next character */ + + + if ( c == '.' ) + { + /* dot encountered, fill in previous length */ + *( pQName + j ) = k; + + k = 0; /* reset segment length */ + j = i + 1; /* set index to next counter */ + } + else + { + *( pQName + i + 1 ) = c; /* assign to QName */ + k++; /* inc count of seg chars */ + } // end if + } // end for loop + + *(pQName + j ) = k; /* count for final segment */ + *(pQName + i + 1 ) = 0; /* count for trailing NULL segment is 0 */ + + return ( i + 1 ); /* return total length of QName */ +} + +// +// ³¢ÊÔËùÓеÄDNSÀ´²éѯÓʾַþÎñÆ÷µØÖ· +// +BOOL GetMX ( + char *pszQuery, // Òª²éѯµÄÓòÃû + OUT t_Ary_MXHostInfos &Ary_MXHostInfos // Êä³ö Mail Exchange Ö÷»úÃû + ) +{ + CNetAdapterInfo m_NetAdapterInfo; + m_NetAdapterInfo.Refresh (); + int nNetAdapterCount = m_NetAdapterInfo.GetNetCardCount(); + for ( int i=0; iGet_DNSCount (); + for ( int j=0; jGet_DNSAddr ( j ); + if ( GetMX ( pszQuery, csDNS.GetBuffer(0), Ary_MXHostInfos ) ) + { + return TRUE; + } + } + } + } + + return FALSE; +} \ No newline at end of file diff --git a/src/Utils/dnsmx.h b/src/Utils/dnsmx.h new file mode 100644 index 0000000..833b6e6 --- /dev/null +++ b/src/Utils/dnsmx.h @@ -0,0 +1,31 @@ +//DNS Query + +/* ˵Ã÷ + 1¡¢ÔÚ InitInstance() º¯ÊýÖмÓÉÏÒÔÏ´úÂ룺 +WSADATA wsaData; +int err = WSAStartup( MAKEWORD( 2, 2 ), &wsaData ); +if ( err ) +{ + return FALSE; +} + + 2¡¢ÔÚ ExitInstance() º¯ÊýÖмÓÉÏÒÔÏ´úÂ룺 + WSACleanup(); + +*/ + +#include +#include "NetAdapterInfo.h" + +typedef struct _MXHostInfo +{ + char szMXHost[1024]; + int N; +} t_MXHostInfo; +typedef CArray t_Ary_MXHostInfos; + +BOOL GetMX ( + char *pszQuery, // Òª²éѯµÄÓòÃû + OUT t_Ary_MXHostInfos &Ary_MXHostInfos // Êä³ö Mail Exchange Ö÷»úÃû + ); + diff --git a/src/Utils/targetver.h b/src/Utils/targetver.h index 8d61047..0b9d4ad 100644 --- a/src/Utils/targetver.h +++ b/src/Utils/targetver.h @@ -22,3 +22,7 @@ #ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0. #define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE. #endif + +#ifndef NTDDI_VERSION +#define NTDDI_VERSION NTDDI_WIN2KSP1 +#endif \ No newline at end of file -- 2.11.0