OSDN Git Service

Success Send one email to gmail server
authorFrank Li <lznuaa@gmail.com>
Thu, 16 Apr 2009 14:43:27 +0000 (22:43 +0800)
committerFrank Li <lznuaa@gmail.com>
Thu, 16 Apr 2009 14:43:27 +0000 (22:43 +0800)
Signed-off-by: Frank Li <lznuaa@gmail.com>
13 files changed:
src/TortoiseProc/Patch.cpp
src/TortoiseProc/TortoiseProc.vcproj
src/Utils/CBase64.cpp [new file with mode: 0644]
src/Utils/HwSMTP.cpp [new file with mode: 0644]
src/Utils/HwSMTP.h [new file with mode: 0644]
src/Utils/NetAdapterInfo.cpp [new file with mode: 0644]
src/Utils/NetAdapterInfo.h [new file with mode: 0644]
src/Utils/Utils.vcproj
src/Utils/base64.cpp
src/Utils/base64.h
src/Utils/dnsmx.cpp [new file with mode: 0644]
src/Utils/dnsmx.h [new file with mode: 0644]
src/Utils/targetver.h

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