1 // HwSMTP.cpp: implementation of the CHwSMTP class.
3 //////////////////////////////////////////////////////////////////////
9 #include "SpeedPostEmail.h"
15 static char THIS_FILE
[]=__FILE__
;
19 CPtrArray g_PtrAry_Threads
;
20 ::CCriticalSection m_CSFor__g_PtrAry_Threads
;
26 LPCTSTR lpszSmtpSrvHost
,
33 LPCTSTR lpszReceiverName
,
37 CStringArray
*pStrAryAttach
,
44 m_csSmtpSrvHost
= GET_SAFE_STRING(lpszSmtpSrvHost
);
45 m_csUserName
= GET_SAFE_STRING(lpszUserName
);
46 m_csPasswd
= GET_SAFE_STRING(lpszPasswd
);
47 m_bMustAuth
= bMustAuth
;
48 m_csAddrFrom
= GET_SAFE_STRING(lpszAddrFrom
);
49 m_csAddrTo
= GET_SAFE_STRING(lpszAddrTo
);
50 m_csFromName
= GET_SAFE_STRING(lpszFromName
);
51 m_csReceiverName
= GET_SAFE_STRING(lpszReceiverName
);
52 m_csSubject
= GET_SAFE_STRING(lpszSubject
);
53 m_csBody
= GET_SAFE_STRING(lpszBody
);
54 m_csCharSet
= GET_SAFE_STRING(lpszCharSet
);
55 m_StrCC
= GET_SAFE_STRING(pStrAryCC
);
56 m_csSender
= GET_SAFE_STRING(pSender
);
57 m_csToList
= GET_SAFE_STRING(pToList
);
60 m_StrAryAttach
.Append ( *pStrAryAttach
);
62 m_nSmtpSrvPort
= nSmtpSrvPort
;
67 CString m_csSmtpSrvHost
;
74 CString m_csReceiverName
;
78 CStringArray m_StrAryAttach
;
87 //////////////////////////////////////////////////////////////////////
88 // Construction/Destruction
89 //////////////////////////////////////////////////////////////////////
92 m_bConnected ( FALSE
),
93 m_nSmtpSrvPort ( 25 ),
96 m_csPartBoundary
= _T( "WC_MAIL_PaRt_BoUnDaRy_05151998" );
97 m_csMIMEContentType
= FormatString ( _T( "multipart/mixed; boundary=%s" ), m_csPartBoundary
);
98 m_csNoMIMEText
= _T( "This is a multi-part message in MIME format." );
99 //m_csCharSet = _T("\r\n\tcharset=\"iso-8859-1\"\r\n");
108 void CHwSMTP::GetNameAddress(CString
&in
, CString
&name
,CString
&address
)
111 start
=in
.Find(_T('<'));
112 end
=in
.Find(_T('>'));
114 if(start
>=0 && end
>=0)
117 address
=in
.Mid(start
+1,end
-start
-1);
123 CString
CHwSMTP::GetServerAddress(CString
&email
)
128 start
= email
.Find(_T("<"));
129 end
= email
.Find(_T(">"));
131 if(start
>=0 && end
>=0)
133 str
=email
.Mid(start
+1,end
-start
-1);
140 start
= str
.Find(_T('@'));
141 return str
.Mid(start
+1);
145 BOOL
CHwSMTP::SendSpeedEmail
147 LPCTSTR lpszAddrFrom
,
152 CStringArray
*pStrAryAttach
,
161 To
+= GET_SAFE_STRING(lpszAddrTo
);
163 To
+= GET_SAFE_STRING(pStrAryCC
);
165 std::map
<CString
,std::vector
<CString
>> Address
;
170 CString one
= To
.Tokenize(_T(";"),start
);
176 addr
= GetServerAddress(one
);
180 Address
[addr
].push_back(one
);
184 std::map
<CString
,std::vector
<CString
>>::iterator itr1
= Address
.begin();
185 for( ; itr1
!= Address
.end(); ++itr1
)
187 PDNS_RECORD pDnsRecord
;
190 DnsQuery(itr1
->first
,
191 DNS_TYPE_MX
,DNS_QUERY_STANDARD
,
192 NULL
, //Contains DNS server IP address.
193 &pDnsRecord
, //Resource record that contains the response.
199 for(int i
=0;i
<itr1
->second
.size();i
++)
210 if(pNext
->wType
== DNS_TYPE_MX
)
211 if(SendEmail(pNext
->Data
.MX
.pNameExchange
,NULL
,NULL
,false,
212 lpszAddrFrom
,to
,lpszSubject
,lpszBody
,lpszCharSet
,pStrAryAttach
,pStrAryCC
,
213 25,pSend
,lpszAddrTo
))
220 //SendEmail(itr1.first,NULL,NULL,false,lpszAddrFrom,,lpszFromname);
221 DnsRecordListFree(pDnsRecord
,DnsFreeRecordList
);
226 BOOL
CHwSMTP::SendEmail (
227 LPCTSTR lpszSmtpSrvHost
,
228 LPCTSTR lpszUserName
,
231 LPCTSTR lpszAddrFrom
,
235 LPCTSTR lpszCharSet
, // ×Ö·û¼¯ÀàÐÍ£¬ÀýÈ磺·±ÌåÖÐÎÄÕâÀïÓ¦ÊäÈë"big5"£¬¼òÌåÖÐÎÄʱÊäÈë"gb2312"
236 CStringArray
*pStrAryAttach
/*=NULL*/,
237 LPCTSTR pStrAryCC
/*=NULL*/,
238 UINT nSmtpSrvPort
,/*=25*/
243 TRACE ( _T("·¢ËÍÓʼþ£º%s, %s\n"), lpszAddrTo
, lpszBody
);
244 m_StrAryAttach
.RemoveAll();
246 m_StrCC
+= GET_SAFE_STRING(pStrAryCC
);
248 m_csSmtpSrvHost
= GET_SAFE_STRING ( lpszSmtpSrvHost
);
249 if ( m_csSmtpSrvHost
.GetLength() <= 0 )
251 m_csLastError
.Format ( _T("Parameter Error!") );
254 m_csUserName
= GET_SAFE_STRING ( lpszUserName
);
255 m_csPasswd
= GET_SAFE_STRING ( lpszPasswd
);
256 m_bMustAuth
= bMustAuth
;
257 if ( m_bMustAuth
&& m_csUserName
.GetLength() <= 0 )
259 m_csLastError
.Format ( _T("Parameter Error!") );
263 m_csAddrFrom
= GET_SAFE_STRING ( lpszAddrFrom
);
264 m_csAddrTo
= GET_SAFE_STRING ( lpszAddrTo
);
265 // m_csFromName = GET_SAFE_STRING ( lpszFromName );
266 // m_csReceiverName = GET_SAFE_STRING ( lpszReceiverName );
267 m_csSubject
= GET_SAFE_STRING ( lpszSubject
);
268 m_csBody
= GET_SAFE_STRING ( lpszBody
);
270 this->m_csSender
= GET_SAFE_STRING(pSender
);
271 this->m_csToList
= GET_SAFE_STRING(pToList
);
273 m_nSmtpSrvPort
= nSmtpSrvPort
;
275 if ( lpszCharSet
&& lstrlen(lpszCharSet
) > 0 )
276 m_csCharSet
.Format ( _T("\r\n\tcharset=\"%s\"\r\n"), lpszCharSet
);
279 m_csAddrFrom
.GetLength() <= 0 || m_csAddrTo
.GetLength() <= 0
282 m_csLastError
.Format ( _T("Parameter Error!") );
288 m_StrAryAttach
.Append ( *pStrAryAttach
);
290 if ( m_StrAryAttach
.GetSize() < 1 )
291 m_csMIMEContentType
= FormatString ( _T( "text/plain; %s" ), m_csCharSet
);
295 if ( !m_SendSock
.Create () )
297 int nResult
= GetLastError();
298 m_csLastError
.Format ( _T("Create socket failed!") );
303 if ( !m_SendSock
.Connect ( m_csSmtpSrvHost
, m_nSmtpSrvPort
) )
305 m_csLastError
.Format ( _T("Connect to [ %s ] failed"), m_csSmtpSrvHost
);
306 TRACE ( _T("%d\n"), GetLastError() );
309 if ( !GetResponse( _T("220") ) ) return FALSE
;
312 BOOL ret
= SendEmail();
320 BOOL
CHwSMTP::GetResponse ( LPCTSTR lpszVerifyCode
, int *pnCode
/*=NULL*/)
322 if ( !lpszVerifyCode
|| lstrlen(lpszVerifyCode
) < 1 )
325 char szRecvBuf
[1024] = {0};
327 char szStatusCode
[4] = {0};
328 nRet
= m_SendSock
.Receive ( szRecvBuf
, sizeof(szRecvBuf
) );
329 TRACE ( _T("Received : %s\r\n"), szRecvBuf
);
332 m_csLastError
.Format ( _T("Receive TCP data failed") );
335 // TRACE ( _T("ÊÕµ½·þÎñÆ÷»ØÓ¦£º%s\n"), szRecvBuf );
337 memcpy ( szStatusCode
, szRecvBuf
, 3 );
338 if ( pnCode
) (*pnCode
) = atoi ( szStatusCode
);
340 if ( strcmp ( szStatusCode
, CMultiByteString(lpszVerifyCode
).GetBuffer() ) != 0 )
342 m_csLastError
.Format ( _T("Received invalid response : %s"), GetCompatibleString(szRecvBuf
,FALSE
) );
348 BOOL
CHwSMTP::SendBuffer(char *buff
,int size
)
354 m_csLastError
.Format ( _T("Didn't connect") );
358 if ( m_SendSock
.Send ( buff
, size
) != size
)
360 m_csLastError
.Format ( _T("Socket send data failed") );
366 // ÀûÓÃsocket·¢ËÍÊý¾Ý£¬Êý¾Ý³¤¶È²»Äܳ¬¹ý10M
367 BOOL
CHwSMTP::Send(CString
&str
)
371 m_csLastError
.Format ( _T("Didn't connect") );
375 CMultiByteString
cbsData ( str
);
377 TRACE ( _T("Send : %s\r\n"), cbsData
.GetBuffer() );
378 if ( m_SendSock
.Send ( cbsData
.GetBuffer(), cbsData
.GetLength() ) != cbsData
.GetLength() )
380 m_csLastError
.Format ( _T("Socket send data failed") );
387 BOOL
CHwSMTP::SendEmail()
390 char szLocalHostName
[64] = {0};
391 gethostname ( (char*)szLocalHostName
, sizeof(szLocalHostName
) );
395 str
.Format(_T("HELO %s\r\n"), GetCompatibleString(szLocalHostName
,FALSE
));
400 if ( !GetResponse ( _T("250") ) )
405 if ( m_bMustAuth
&& !auth() )
415 if ( !SendSubject() )
430 if ( !Send ( CString(_T(".\r\n") ) ) ) return FALSE
;
431 if ( !GetResponse ( _T("250") ) )
435 if ( HANDLE_IS_VALID(m_SendSock
.m_hSocket
) )
436 Send ( CString(_T("QUIT\r\n")) );
437 m_bConnected
= FALSE
;
444 int nResponseCode
= 0;
445 if ( !Send ( CString(_T("auth login\r\n")) ) ) return FALSE
;
446 if ( !GetResponse ( _T("334"), &nResponseCode
) ) return FALSE
;
447 if ( nResponseCode
!= 334 ) // ²»ÐèÒªÑéÖ¤Óû§ÃûºÍÃÜÂë
450 CBase64 Base64Encode
;
451 CMultiByteString
cbsUserName ( m_csUserName
), cbsPasswd ( m_csPasswd
);
452 CString csBase64_UserName
= GetCompatibleString ( Base64Encode
.Encode ( cbsUserName
.GetBuffer(), cbsUserName
.GetLength() ).GetBuffer(0), FALSE
);
453 CString csBase64_Passwd
= GetCompatibleString ( Base64Encode
.Encode ( cbsPasswd
.GetBuffer(), cbsPasswd
.GetLength() ).GetBuffer(0), FALSE
);
456 str
.Format( _T("%s\r\n"), csBase64_UserName
);
460 if ( !GetResponse ( _T("334") ) )
462 m_csLastError
.Format ( _T("Authentication UserName failed") );
466 str
.Format(_T("%s\r\n"), csBase64_Passwd
);
470 if ( !GetResponse ( _T("235") ) )
472 m_csLastError
.Format ( _T("Authentication Password failed") );
479 BOOL
CHwSMTP::SendHead()
483 GetNameAddress(m_csAddrFrom
,name
,addr
);
485 str
.Format( _T("MAIL From: <%s>\r\n"), addr
);
486 if ( !Send ( str
) ) return FALSE
;
488 if ( !GetResponse ( _T("250") ) ) return FALSE
;
493 CString one
=m_csAddrTo
.Tokenize(_T(";"),start
);
499 GetNameAddress(one
,name
,addr
);
501 str
.Format(_T("RCPT TO: <%s>\r\n"), addr
);
502 if ( !Send ( str
) ) return FALSE
;
503 if ( !GetResponse ( _T("250") ) ) return FALSE
;
507 for ( int i
=0; i
<m_StrAryCC
.GetSize(); i
++ )
509 str
.Format(_T("RCPT TO: <%s>\r\n"), m_StrAryCC
.GetAt(i
) );
510 if ( !Send ( str
) ) return FALSE
;
511 if ( !GetResponse ( _T("250") ) ) return FALSE
;
515 if ( !Send ( CString(_T("DATA\r\n") ) ) ) return FALSE
;
516 if ( !GetResponse ( CString(_T("354") )) ) return FALSE
;
521 BOOL
CHwSMTP::SendSubject()
524 csSubject
+= _T("Date: ");
525 COleDateTime tNow
= COleDateTime::GetCurrentTime();
528 csSubject
+= FormatDateTime (tNow
, _T("%a, %d %b %y %H:%M:%S %Z"));
530 csSubject
+= _T("\r\n");
531 csSubject
+= FormatString ( _T("From: %s\r\n"), this->m_csAddrFrom
);
533 csSubject
+= FormatString ( _T("CC: %s\r\n"), this->m_StrCC
);
535 if(m_csSender
.IsEmpty())
536 m_csSender
= this->m_csAddrFrom
;
538 csSubject
+= FormatString ( _T("Sender: %s\r\n"), this->m_csSender
);
540 if(this->m_csToList
.IsEmpty())
541 m_csToList
= m_csReceiverName
;
543 csSubject
+= FormatString ( _T("To: %s\r\n"), this->m_csToList
);
547 csSubject
+= FormatString ( _T("Subject: %s\r\n"), m_csSubject
);
549 csSubject
+= FormatString ( _T("X-Mailer: TortoiseGit\r\nMIME-Version: 1.0\r\nContent-Type: %s\r\n\r\n"),
550 m_csMIMEContentType
);
552 return Send ( csSubject
);
555 BOOL
CHwSMTP::SendBody()
557 CString csBody
, csTemp
;
559 if ( m_StrAryAttach
.GetSize() > 0 )
561 csTemp
.Format ( _T("%s\r\n\r\n"), m_csNoMIMEText
);
564 csTemp
.Format ( _T("--%s\r\n"), m_csPartBoundary
);
567 csTemp
.Format ( _T("Content-Type: text/plain\r\n%sContent-Transfer-Encoding: 7Bit\r\n\r\n"),
572 //csTemp.Format ( _T("%s\r\n"), m_csBody );
574 csBody
+= _T("\r\n");
576 return Send ( csBody
);
579 BOOL
CHwSMTP::SendAttach()
581 int nCountAttach
= (int)m_StrAryAttach
.GetSize();
582 if ( nCountAttach
< 1 ) return TRUE
;
584 for ( int i
=0; i
<nCountAttach
; i
++ )
586 if ( !SendOnAttach ( m_StrAryAttach
.GetAt(i
) ) )
593 BOOL
CHwSMTP::SendOnAttach(LPCTSTR lpszFileName
)
595 ASSERT ( lpszFileName
);
596 CString csAttach
, csTemp
;
598 csTemp
= lpszFileName
;
599 CString csShortFileName
= csTemp
.GetBuffer(0) + csTemp
.ReverseFind ( '\\' );
600 csShortFileName
.TrimLeft ( _T("\\") );
602 csTemp
.Format ( _T("--%s\r\n"), m_csPartBoundary
);
605 csTemp
.Format ( _T("Content-Type: application/octet-stream; file=%s\r\n"), csShortFileName
);
608 csTemp
.Format ( _T("Content-Transfer-Encoding: base64\r\n") );
611 csTemp
.Format ( _T("Content-Disposition: attachment; filename=%s\r\n\r\n"), csShortFileName
);
614 DWORD dwFileSize
= hwGetFileAttr(lpszFileName
);
615 if ( dwFileSize
> 5*1024*1024 )
617 m_csLastError
.Format ( _T("File [%s] too big. File size is : %s"), lpszFileName
, FormatBytes(dwFileSize
) );
620 char *pBuf
= new char[dwFileSize
+1];
623 ::AfxThrowMemoryException ();
627 if(!Send ( csAttach
))
634 if ( !file
.Open ( lpszFileName
, CFile::modeRead
) )
636 m_csLastError
.Format ( _T("Open file [%s] failed"), lpszFileName
);
639 UINT nFileLen
= file
.Read ( pBuf
, dwFileSize
);
640 CBase64 Base64Encode
;
641 filedata
= Base64Encode
.Encode ( pBuf
, nFileLen
);
642 filedata
+= _T("\r\n\r\n");
644 catch ( CFileException e
)
647 m_csLastError
.Format ( _T("Read file [%s] failed"), lpszFileName
);
652 if(!SendBuffer( filedata
.GetBuffer() ))
659 //return Send ( csAttach );
662 CString
CHwSMTP::GetLastErrorText()
664 return m_csLastError
;
668 DWORD WINAPI
ThreadProc_SendEmail( LPVOID lpParameter
)
670 CEMailObject
*pEMailObject
= (CEMailObject
*)lpParameter
;
671 ASSERT ( pEMailObject
);
674 BOOL bRet
= HwSMTP
.SendEmail (
675 pEMailObject
->m_csSmtpSrvHost
,
676 pEMailObject
->m_csUserName
,
677 pEMailObject
->m_csPasswd
,
678 pEMailObject
->m_bMustAuth
,
679 pEMailObject
->m_csAddrFrom
,
680 pEMailObject
->m_csAddrTo
,
681 pEMailObject
->m_csSubject
,
682 pEMailObject
->m_csBody
,
683 pEMailObject
->m_csCharSet
,
684 &pEMailObject
->m_StrAryAttach
,
685 pEMailObject
->m_StrCC
,
686 pEMailObject
->m_nSmtpSrvPort
,
687 pEMailObject
->m_csSender
692 CString csError
= HwSMTP
.GetLastErrorText ();
693 csError
= FormatString ( _T("Send a email to [%s] failed."), pEMailObject
->m_csSmtpSrvHost
);
694 AfxMessageBox ( csError
);
698 m_CSFor__g_PtrAry_Threads
.Lock ();
699 int nFindPos
= FindFromArray ( g_PtrAry_Threads
, pEMailObject
->m_hThread
);
701 g_PtrAry_Threads
.RemoveAt ( nFindPos
);
702 m_CSFor__g_PtrAry_Threads
.Unlock ();
709 // Óà SMTP ·þÎñ·¢Ë͵ç×ÓÓʼþ£¬Èç¹ûÉèÖòÎÊý bViaThreadSend=TRUE£¬ÄÇÔÚ³ÌÐò½áÊøʱӦ¸ÃÔÚ ExitInstance() Öе÷Óà EndOfSMTP() º¯Êý
713 LPCTSTR lpszSmtpSrvHost
,
714 LPCTSTR lpszUserName
,
717 LPCTSTR lpszAddrFrom
,
719 LPCTSTR lpszFromName
,
720 LPCTSTR lpszReceiverName
,
723 LPCTSTR lpszCharSet
/*=NULL*/,
724 CStringArray
*pStrAryAttach
/*=NULL*/,
725 LPCTSTR pStrAryCC
/*=NULL*/,
726 UINT nSmtpSrvPort
/*=25*/,
731 if ( !lpszSmtpSrvHost
|| lstrlen(lpszSmtpSrvHost
) < 1 ||
732 !lpszSubject
|| lstrlen(lpszSubject
) < 1 ||
733 !lpszBody
|| lstrlen(lpszBody
) < 1 )
735 AfxMessageBox ( _T("Parameter error !") );
739 CEMailObject
*pEMailObject
= new CEMailObject (
757 if ( !pEMailObject
) return FALSE
;
760 if ( bViaThreadSend
)
762 DWORD dwThreadId
= 0;
763 pEMailObject
->m_hThread
= ::CreateThread ( NULL
, 0, ::ThreadProc_SendEmail
, pEMailObject
, CREATE_SUSPENDED
, &dwThreadId
);
764 bRet
= HANDLE_IS_VALID(pEMailObject
->m_hThread
);
765 m_CSFor__g_PtrAry_Threads
.Lock();
766 g_PtrAry_Threads
.Add ( pEMailObject
->m_hThread
);
767 m_CSFor__g_PtrAry_Threads
.Unlock();
768 ResumeThread ( pEMailObject
->m_hThread
);
772 bRet
= (BOOL
)ThreadProc_SendEmail ( pEMailObject
);
780 // µÈ´ýËùÓÐÏß³ÌÖ´ÐÐÍê±Ï
781 for ( int i
=0; i
<g_PtrAry_Threads
.GetSize(); i
++ )
783 HANDLE hThread
= (HANDLE
)g_PtrAry_Threads
.GetAt(i
);
784 if ( HANDLE_IS_VALID(hThread
) )
786 WaitForThreadEnd ( &hThread
, 30*1000 );
789 g_PtrAry_Threads
.RemoveAll ();
794 // ½«×Ö·û´® lpszOrg ת»»Îª¶à×Ö½ÚµÄ×Ö·û´®£¬Èç¹û»¹ÒªÊ¹Óöà×Ö·û´®µÄ³¤¶È£¬¿ÉÒÔÓÃÒÔÏ·½Ê½À´Ê¹ÓÃÕâ¸öÀࣺ
795 // CMultiByteString MultiByteString(_T("UNICODE×Ö·û´®"));
796 // printf ( "ANSI ×Ö·û´®Îª£º %s£¬ ×Ö·û¸öÊýΪ£º %d £¬ ³¤¶ÈΪ£º %d×Ö½Ú\n", MultiByteString.GetBuffer(), MultiByteString.GetLength(), MultiByteString.GetSize() );
798 CMultiByteString::CMultiByteString( LPCTSTR lpszOrg
, int nOrgStringEncodeType
/*=STRING_IS_SOFTCODE*/, OUT
char *pOutBuf
/*=NULL*/, int nOutBufSize
/*=0*/ )
800 m_bNewBuffer
= FALSE
;
803 m_nCharactersNumber
= 0;
804 if ( !lpszOrg
) return;
806 BOOL bOrgIsUnicode
= FALSE
;
807 if ( nOrgStringEncodeType
== STRING_IS_MULTICHARS
) bOrgIsUnicode
= FALSE
;
808 else if ( nOrgStringEncodeType
== STRING_IS_UNICODE
) bOrgIsUnicode
= TRUE
;
812 bOrgIsUnicode
= TRUE
;
814 bOrgIsUnicode
= FALSE
;
820 m_nCharactersNumber
= (int)wcslen((WCHAR
*)lpszOrg
);
821 m_nDataSize
= (m_nCharactersNumber
+ 1) * sizeof(WCHAR
);
825 m_nCharactersNumber
= (int)strlen((char*)lpszOrg
);
826 m_nDataSize
= (m_nCharactersNumber
+ 1) * sizeof(char);
829 if ( pOutBuf
&& nOutBufSize
> 0 )
832 m_nDataSize
= nOutBufSize
;
836 m_pszData
= (char*)new BYTE
[m_nDataSize
];
839 ::AfxThrowMemoryException ();
844 memset ( m_pszData
, 0, m_nDataSize
);
848 m_nCharactersNumber
= WideCharToMultiByte ( CP_ACP
, 0, (LPCWSTR
)lpszOrg
, m_nCharactersNumber
, (LPSTR
)m_pszData
, m_nDataSize
/sizeof(char)-1, NULL
, NULL
);
849 if ( m_nCharactersNumber
< 1 ) m_nCharactersNumber
= (int)strlen ( m_pszData
);
853 m_nCharactersNumber
= __min ( m_nCharactersNumber
, (int)(m_nDataSize
/sizeof(char)-1) );
854 strncpy ( m_pszData
, (const char*)lpszOrg
, m_nCharactersNumber
);
855 m_nCharactersNumber
= (int)strlen ( m_pszData
);
857 m_nDataSize
= ( m_nCharactersNumber
+ 1 ) * sizeof(char);
860 CMultiByteString::~CMultiByteString ()
862 if ( m_bNewBuffer
&& m_pszData
)
868 CString
GetCompatibleString ( LPVOID lpszOrg
, BOOL bOrgIsUnicode
, int nOrgLength
/*=-1*/ )
870 if ( !lpszOrg
) return _T("");
877 if ( nOrgLength
> 0 )
879 WCHAR
*szRet
= new WCHAR
[nOrgLength
+1];
880 if ( !szRet
) return _T("");
881 memset ( szRet
, 0, (nOrgLength
+1)*sizeof(WCHAR
) );
882 memcpy ( szRet
, lpszOrg
, nOrgLength
*sizeof(WCHAR
) );
883 CString csRet
= szRet
;
887 else if ( nOrgLength
== 0 )
890 return (LPCTSTR
)lpszOrg
;
893 if ( nOrgLength
< 0 )
894 nOrgLength
= (int)strlen((const char*)lpszOrg
);
895 int nWideCount
= nOrgLength
+ 1;
896 WCHAR
*wchar
= new WCHAR
[nWideCount
];
897 if ( !wchar
) return _T("");
898 memset ( wchar
, 0, nWideCount
*sizeof(WCHAR
) );
899 ::MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)lpszOrg
, nOrgLength
, wchar
, nWideCount
);
900 CString csRet
= wchar
;
904 if ( !bOrgIsUnicode
)
906 if ( nOrgLength
> 0 )
908 char *szRet
= new char[nOrgLength
+1];
909 if ( !szRet
) return _T("");
910 memset ( szRet
, 0, (nOrgLength
+1)*sizeof(char) );
911 memcpy ( szRet
, lpszOrg
, nOrgLength
*sizeof(char) );
912 CString csRet
= szRet
;
916 else if ( nOrgLength
== 0 )
919 return (LPCTSTR
)lpszOrg
;
922 if ( nOrgLength
< 0 )
923 nOrgLength
= (int)wcslen((WCHAR
*)lpszOrg
);
924 int nMultiByteCount
= nOrgLength
+ 1;
925 char *szMultiByte
= new char[nMultiByteCount
];
926 if ( !szMultiByte
) return _T("");
927 memset ( szMultiByte
, 0, nMultiByteCount
*sizeof(char) );
928 ::WideCharToMultiByte ( CP_ACP
, 0, (LPCWSTR
)lpszOrg
, nOrgLength
, (LPSTR
)szMultiByte
, nMultiByteCount
, NULL
, NULL
);
929 CString csRet
= szMultiByte
;
930 delete[] szMultiByte
;
943 CString
FormatDateTime ( COleDateTime
&DateTime
, LPCTSTR pFormat
)
945 // If null, return empty string
946 if ( DateTime
.GetStatus() == COleDateTime::null
|| DateTime
.GetStatus() == COleDateTime::invalid
)
950 if (S_OK
!= VarUdateFromDate(DateTime
.m_dt
, 0, &ud
))
955 TCHAR
*weeks
[]={_T("Sun"),_T("Mon"),_T("Tue"),_T("Wen"),_T("Thu"),_T("Fri"),_T("Sat")};
956 TCHAR
*month
[]={_T("JAN"),_T("FEB"),_T("MAR"),_T("APR"),
957 _T("MAY"),_T("JUN"),_T("JUL"),_T("AUG"),
958 _T("SEP"),_T("OCT"),_T("NOV"),_T("DEC")};
960 TIME_ZONE_INFORMATION stTimeZone
;
961 GetTimeZoneInformation(&stTimeZone
);
964 strDate
.Format(_T("%s, %d %s %02d %d:%d:%d %c%04d")
965 ,weeks
[ud
.st
.wDayOfWeek
],
966 ud
.st
.wDay
,month
[ud
.st
.wMonth
-1],ud
.st
.wYear
%100,ud
.st
.wHour
,
967 ud
.st
.wMinute
,ud
.st
.wSecond
,
968 stTimeZone
.Bias
>0?_T('-'):_T('+'),
969 abs(stTimeZone
.Bias
*10/6)
974 CString
FormatString ( LPCTSTR lpszStr
, ... )
977 for ( int nBufCount
= 1024; nBufCount
<5*1024*1024; nBufCount
+= 1024 )
979 buf
= new TCHAR
[nBufCount
];
982 ::AfxThrowMemoryException ();
985 memset ( buf
, 0, nBufCount
*sizeof(TCHAR
) );
988 va_start (va
, lpszStr
);
989 int nLen
= _vsnprintf_hw ((TCHAR
*)buf
, nBufCount
-sizeof(TCHAR
), lpszStr
, va
);
991 if ( nLen
<= (int)(nBufCount
-sizeof(TCHAR
)) )
993 delete[] buf
; buf
= NULL
;
1000 CString csMsg
= buf
;
1001 delete[] buf
; buf
= NULL
;
1005 int hwGetFileAttr ( LPCTSTR lpFileName
, OUT CFileStatus
*pFileStatus
/*=NULL*/ )
1007 if ( !lpFileName
|| lstrlen(lpFileName
) < 1 ) return -1;
1009 CFileStatus fileStatus
;
1010 fileStatus
.m_attribute
= 0;
1011 fileStatus
.m_size
= 0;
1012 memset ( fileStatus
.m_szFullName
, 0, sizeof(fileStatus
.m_szFullName
) );
1016 if ( CFile::GetStatus(lpFileName
,fileStatus
) )
1021 CATCH (CFileException
, e
)
1035 pFileStatus
->m_ctime
= fileStatus
.m_ctime
;
1036 pFileStatus
->m_mtime
= fileStatus
.m_mtime
;
1037 pFileStatus
->m_atime
= fileStatus
.m_atime
;
1038 pFileStatus
->m_size
= fileStatus
.m_size
;
1039 pFileStatus
->m_attribute
= fileStatus
.m_attribute
;
1040 pFileStatus
->_m_padding
= fileStatus
._m_padding
;
1041 lstrcpy ( pFileStatus
->m_szFullName
, fileStatus
.m_szFullName
);
1045 return (int)fileStatus
.m_size
;
1048 CString
FormatBytes ( double fBytesNum
, BOOL bShowUnit
/*=TRUE*/, int nFlag
/*=0*/ )
1053 if ( fBytesNum
>= 1024.0 && fBytesNum
< 1024.0*1024.0 )
1054 csRes
.Format ( _T("%.2f%s"), fBytesNum
/ 1024.0, bShowUnit
?_T(" K"):_T("") );
1055 else if ( fBytesNum
>= 1024.0*1024.0 && fBytesNum
< 1024.0*1024.0*1024.0 )
1056 csRes
.Format ( _T("%.2f%s"), fBytesNum
/ (1024.0*1024.0), bShowUnit
?_T(" M"):_T("") );
1057 else if ( fBytesNum
>= 1024.0*1024.0*1024.0 )
1058 csRes
.Format ( _T("%.2f%s"), fBytesNum
/ (1024.0*1024.0*1024.0), bShowUnit
?_T(" G"):_T("") );
1060 csRes
.Format ( _T("%.2f%s"), fBytesNum
, bShowUnit
?_T(" B"):_T("") );
1062 else if ( nFlag
== 1 )
1064 csRes
.Format ( _T("%.2f%s"), fBytesNum
/ 1024.0, bShowUnit
?_T(" K"):_T("") );
1066 else if ( nFlag
== 2 )
1068 csRes
.Format ( _T("%.2f%s"), fBytesNum
/ (1024.0*1024.0), bShowUnit
?_T(" M"):_T("") );
1070 else if ( nFlag
== 3 )
1072 csRes
.Format ( _T("%.2f%s"), fBytesNum
/ (1024.0*1024.0*1024.0), bShowUnit
?_T(" G"):_T("") );
1081 BOOL
WaitForThreadEnd ( HANDLE
*phThread
, DWORD dwWaitTime
/*=10*1000*/ )
1084 ASSERT ( phThread
);
1085 if ( !(*phThread
) ) return TRUE
;
1086 if ( ::WaitForSingleObject ( *phThread
, dwWaitTime
) == WAIT_TIMEOUT
)
1089 ::TerminateThread ( *phThread
, 0 );
1091 ::CloseHandle ( *phThread
);