Success Send one email to gmail server
[TortoiseGit.git] / src / Utils / HwSMTP.cpp
blob84d0b20d77745d37e573e257d0b180f49aab65b4
1 // HwSMTP.cpp: implementation of the CHwSMTP class.
2 //
3 //////////////////////////////////////////////////////////////////////
5 #include "stdafx.h"
6 #include "afxstr.h"
7 #include "HwSMTP.h"
8 #include "CBase64.h"
9 #include "SpeedPostEmail.h"
11 #include <Afxmt.h>
13 #ifdef _DEBUG
14 #undef THIS_FILE
15 static char THIS_FILE[]=__FILE__;
16 #define new DEBUG_NEW
17 #endif
19 CPtrArray g_PtrAry_Threads;
20 ::CCriticalSection m_CSFor__g_PtrAry_Threads;
22 class CEMailObject
24 public:
25 CEMailObject (
26 LPCTSTR lpszSmtpSrvHost,
27 LPCTSTR lpszUserName,
28 LPCTSTR lpszPasswd,
29 BOOL bMustAuth,
30 LPCTSTR lpszAddrFrom,
31 LPCTSTR lpszAddrTo,
32 LPCTSTR lpszSenderName,
33 LPCTSTR lpszReceiverName,
34 LPCTSTR lpszSubject,
35 LPCTSTR lpszBody,
36 LPCTSTR lpszCharSet,
37 CStringArray *pStrAryAttach,
38 CStringArray *pStrAryCC,
39 UINT nSmtpSrvPort
42 m_csSmtpSrvHost = GET_SAFE_STRING(lpszSmtpSrvHost);
43 m_csUserName = GET_SAFE_STRING(lpszUserName);
44 m_csPasswd = GET_SAFE_STRING(lpszPasswd);
45 m_bMustAuth = bMustAuth;
46 m_csAddrFrom = GET_SAFE_STRING(lpszAddrFrom);
47 m_csAddrTo = GET_SAFE_STRING(lpszAddrTo);
48 m_csSenderName = GET_SAFE_STRING(lpszSenderName);
49 m_csReceiverName = GET_SAFE_STRING(lpszReceiverName);
50 m_csSubject = GET_SAFE_STRING(lpszSubject);
51 m_csBody = GET_SAFE_STRING(lpszBody);
52 m_csCharSet = GET_SAFE_STRING(lpszCharSet);
53 if ( pStrAryAttach )
54 m_StrAryAttach.Append ( *pStrAryAttach );
55 if ( pStrAryCC )
56 m_StrAryCC.Append ( *pStrAryCC );
57 m_nSmtpSrvPort = nSmtpSrvPort;
58 m_hThread = NULL;
61 public:
62 CString m_csSmtpSrvHost;
63 CString m_csUserName;
64 CString m_csPasswd;
65 BOOL m_bMustAuth;
66 CString m_csAddrFrom;
67 CString m_csAddrTo;
68 CString m_csSenderName;
69 CString m_csReceiverName;
70 CString m_csSubject;
71 CString m_csBody;
72 CString m_csCharSet;
73 CStringArray m_StrAryAttach;
74 CStringArray m_StrAryCC;
75 UINT m_nSmtpSrvPort;
77 HANDLE m_hThread;
80 //////////////////////////////////////////////////////////////////////
81 // Construction/Destruction
82 //////////////////////////////////////////////////////////////////////
84 CHwSMTP::CHwSMTP () :
85 m_bConnected ( FALSE ),
86 m_nSmtpSrvPort ( 25 ),
87 m_bMustAuth ( TRUE )
89 m_csMIMEContentType = _T( "multipart/mixed");
90 m_csPartBoundary = _T( "WC_MAIL_PaRt_BoUnDaRy_05151998" );
91 m_csNoMIMEText = _T( "This is a multi-part message in MIME format." );
92 // m_csCharSet = _T("\r\n\tcharset=\"iso-8859-1\"\r\n");
95 CHwSMTP::~CHwSMTP()
99 BOOL CHwSMTP::SendEmail (
100 LPCTSTR lpszSmtpSrvHost,
101 LPCTSTR lpszUserName,
102 LPCTSTR lpszPasswd,
103 BOOL bMustAuth,
104 LPCTSTR lpszAddrFrom,
105 LPCTSTR lpszAddrTo,
106 LPCTSTR lpszSenderName,
107 LPCTSTR lpszReceiverName,
108 LPCTSTR lpszSubject,
109 LPCTSTR lpszBody,
110 LPCTSTR lpszCharSet, // ×Ö·û¼¯ÀàÐÍ£¬ÀýÈ磺·±ÌåÖÐÎÄÕâÀïÓ¦ÊäÈë"big5"£¬¼òÌåÖÐÎÄʱÊäÈë"gb2312"
111 CStringArray *pStrAryAttach/*=NULL*/,
112 CStringArray *pStrAryCC/*=NULL*/,
113 UINT nSmtpSrvPort/*=25*/
116 TRACE ( _T("·¢ËÍÓʼþ£º%s, %s, %s\n"), lpszAddrTo, lpszReceiverName, lpszBody );
117 m_StrAryAttach.RemoveAll();
118 m_StrAryCC.RemoveAll();
119 m_csSmtpSrvHost = GET_SAFE_STRING ( lpszSmtpSrvHost );
120 if ( m_csSmtpSrvHost.GetLength() <= 0 )
122 m_csLastError.Format ( _T("Parameter Error!") );
123 return FALSE;
125 m_csUserName = GET_SAFE_STRING ( lpszUserName );
126 m_csPasswd = GET_SAFE_STRING ( lpszPasswd );
127 m_bMustAuth = bMustAuth;
128 if ( m_bMustAuth && m_csUserName.GetLength() <= 0 )
130 m_csLastError.Format ( _T("Parameter Error!") );
131 return FALSE;
134 m_csAddrFrom = GET_SAFE_STRING ( lpszAddrFrom );
135 m_csAddrTo = GET_SAFE_STRING ( lpszAddrTo );
136 m_csSenderName = GET_SAFE_STRING ( lpszSenderName );
137 m_csReceiverName = GET_SAFE_STRING ( lpszReceiverName );
138 m_csSubject = GET_SAFE_STRING ( lpszSubject );
139 m_csBody = GET_SAFE_STRING ( lpszBody );
140 m_nSmtpSrvPort = nSmtpSrvPort;
141 if ( lpszCharSet && lstrlen(lpszCharSet) > 0 )
142 m_csCharSet.Format ( _T("\r\n\tcharset=\"%s\"\r\n"), lpszCharSet );
144 if (
145 m_csAddrFrom.GetLength() <= 0 || m_csAddrTo.GetLength() <= 0 ||
146 m_csSenderName.GetLength() <= 0 || m_csReceiverName.GetLength() <= 0 ||
147 m_csSubject.GetLength() <= 0 || m_csBody.GetLength() <= 0
150 m_csLastError.Format ( _T("Parameter Error!") );
151 return FALSE;
154 if ( pStrAryAttach )
156 m_StrAryAttach.Append ( *pStrAryAttach );
158 if ( m_StrAryAttach.GetSize() < 1 )
159 m_csMIMEContentType = _T( "text/plain");
161 if ( pStrAryCC )
163 m_StrAryCC.Append ( *pStrAryCC );
166 // ´´½¨Socket
167 if ( !m_SendSock.Create () )
169 m_csLastError.Format ( _T("Create socket failed!") );
170 return FALSE;
173 // Á¬½Óµ½·þÎñÆ÷
174 if ( !m_SendSock.Connect ( m_csSmtpSrvHost, m_nSmtpSrvPort ) )
176 m_csLastError.Format ( _T("Connect to [ %s ] failed"), m_csSmtpSrvHost );
177 TRACE ( _T("%d\n"), GetLastError() );
178 return FALSE;
180 if ( !GetResponse( _T("220") ) ) return FALSE;
182 m_bConnected = TRUE;
183 return SendEmail();
188 BOOL CHwSMTP::GetResponse ( LPCTSTR lpszVerifyCode, int *pnCode/*=NULL*/)
190 if ( !lpszVerifyCode || lstrlen(lpszVerifyCode) < 1 )
191 return FALSE;
193 char szRecvBuf[1024] = {0};
194 int nRet = 0;
195 char szStatusCode[4] = {0};
196 nRet = m_SendSock.Receive ( szRecvBuf, sizeof(szRecvBuf) );
197 TRACE ( _T("Received : %s\r\n"), szRecvBuf );
198 if ( nRet <= 0 )
200 m_csLastError.Format ( _T("Receive TCP data failed") );
201 return FALSE;
203 // TRACE ( _T("ÊÕµ½·þÎñÆ÷»ØÓ¦£º%s\n"), szRecvBuf );
205 memcpy ( szStatusCode, szRecvBuf, 3 );
206 if ( pnCode ) (*pnCode) = atoi ( szStatusCode );
208 if ( strcmp ( szStatusCode, CMultiByteString(lpszVerifyCode).GetBuffer() ) != 0 )
210 m_csLastError.Format ( _T("Received invalid response : %s"), GetCompatibleString(szRecvBuf,FALSE) );
211 return FALSE;
214 return TRUE;
217 // ÀûÓÃsocket·¢ËÍÊý¾Ý£¬Êý¾Ý³¤¶È²»Äܳ¬¹ý10M
218 BOOL CHwSMTP::Send(LPCTSTR lpszData, ... )
220 if ( !m_bConnected )
222 m_csLastError.Format ( _T("Didn't connect") );
223 return FALSE;
226 TCHAR *buf = NULL;
227 // Ñ­»·¸ñʽ»¯×Ö·û´®£¬Èç¹û»º³å²»¹»Ôò½«»º³å¼Ó´óÈ»ºóÖØÊÔÒÔ±£Ö¤»º³å¹»ÓÃͬʱÓÖ²»ÀË·Ñ
228 for ( int nBufCount = 1024; nBufCount<10*1024*1024; nBufCount += 1024 )
230 buf = new TCHAR[nBufCount];
231 if ( !buf )
233 ::AfxThrowMemoryException ();
234 return FALSE;
236 memset ( buf, 0, nBufCount*sizeof(TCHAR) );
238 va_list va;
239 va_start (va, lpszData);
240 int nLen = _vsnprintf_hw ((TCHAR*)buf, nBufCount-sizeof(TCHAR), lpszData, va);
241 va_end(va);
242 if ( nLen <= (int)(nBufCount-sizeof(TCHAR)) )
243 break;
244 delete[] buf; buf = NULL;
246 if ( !buf )
248 m_csLastError.Format ( _T("Memory too small or data too big.") );
249 return FALSE;
252 CMultiByteString cbsData ( buf );
253 delete[] buf; buf = NULL;
254 TRACE ( _T("Send : %s\r\n"), cbsData.GetBuffer() );
255 if ( m_SendSock.Send ( cbsData.GetBuffer(), cbsData.GetLength() ) != cbsData.GetLength() )
257 m_csLastError.Format ( _T("Socket send data failed") );
258 return FALSE;
261 return TRUE;
264 BOOL CHwSMTP::SendEmail()
266 BOOL bRet = TRUE;
267 char szLocalHostName[64] = {0};
268 gethostname ( (char*)szLocalHostName, sizeof(szLocalHostName) );
270 // hello£¬ÎÕÊÖ
271 if ( !Send ( _T("HELO %s\r\n"), GetCompatibleString(szLocalHostName,FALSE) ) )
273 return FALSE;
275 if ( !GetResponse ( _T("250") ) )
277 return FALSE;
279 // Éí·ÝÑéÖ¤
280 if ( m_bMustAuth && !auth() )
282 return FALSE;
284 // ·¢ËÍÓʼþÍ·
285 if ( !SendHead() )
287 return FALSE;
289 // ·¢ËÍÓʼþÖ÷Ìâ
290 if ( !SendSubject() )
292 return FALSE;
294 // ·¢ËÍÓʼþÕýÎÄ
295 if ( !SendBody() )
297 return FALSE;
299 // ·¢Ë͸½¼þ
300 if ( !SendAttach() )
302 return FALSE;
304 // ½áÊøÓʼþÕýÎÄ
305 if ( !Send ( _T(".\r\n") ) ) return FALSE;
306 if ( !GetResponse ( _T("250") ) )
307 return FALSE;
309 // Í˳ö·¢ËÍ
310 if ( HANDLE_IS_VALID(m_SendSock.m_hSocket) )
311 Send ( _T("QUIT\r\n") );
312 m_bConnected = FALSE;
314 return bRet;
317 BOOL CHwSMTP::auth()
319 int nResponseCode = 0;
320 if ( !Send ( _T("auth login\r\n") ) ) return FALSE;
321 if ( !GetResponse ( _T("334"), &nResponseCode ) ) return FALSE;
322 if ( nResponseCode != 334 ) // ²»ÐèÒªÑéÖ¤Óû§ÃûºÍÃÜÂë
323 return TRUE;
325 CBase64 Base64Encode;
326 CMultiByteString cbsUserName ( m_csUserName ), cbsPasswd ( m_csPasswd );
327 CString csBase64_UserName = GetCompatibleString ( Base64Encode.Encode ( cbsUserName.GetBuffer(), cbsUserName.GetLength() ).GetBuffer(0), FALSE );
328 CString csBase64_Passwd = GetCompatibleString ( Base64Encode.Encode ( cbsPasswd.GetBuffer(), cbsPasswd.GetLength() ).GetBuffer(0), FALSE );
330 if ( !Send ( _T("%s\r\n"), csBase64_UserName ) ) return FALSE;
331 if ( !GetResponse ( _T("334") ) )
333 m_csLastError.Format ( _T("Authentication UserName failed") );
334 return FALSE;
337 if ( !Send ( _T("%s\r\n"), csBase64_Passwd ) ) return FALSE;
338 if ( !GetResponse ( _T("235") ) )
340 m_csLastError.Format ( _T("Authentication Password failed") );
341 return FALSE;
344 return TRUE;
347 BOOL CHwSMTP::SendHead()
349 if ( !Send ( _T("MAIL From: <%s>\r\n"), m_csAddrFrom ) ) return FALSE;
350 if ( !GetResponse ( _T("250") ) ) return FALSE;
351 if ( !Send ( _T("RCPT TO: <%s>\r\n"), m_csAddrTo ) ) return FALSE;
352 if ( !GetResponse ( _T("250") ) ) return FALSE;
354 for ( int i=0; i<m_StrAryCC.GetSize(); i++ )
356 if ( !Send ( _T("RCPT TO: <%s>\r\n"), m_StrAryCC.GetAt(i) ) ) return FALSE;
357 if ( !GetResponse ( _T("250") ) ) return FALSE;
359 if ( !Send ( _T("DATA\r\n") ) ) return FALSE;
360 if ( !GetResponse ( _T("354") ) ) return FALSE;
362 return TRUE;
365 BOOL CHwSMTP::SendSubject()
367 CString csSubject;
368 csSubject += _T("Date: ");
369 COleDateTime tNow = COleDateTime::GetCurrentTime();
370 if ( tNow > 1 )
372 csSubject += GetCompatibleString(FormatDateTime (tNow, _T("%a, %d %b %y %H:%M:%S %Z")).GetBuffer(0),FALSE);
374 csSubject += _T("\r\n");
375 csSubject += FormatString ( _T("From: %s\r\nTo: %s\r\n"), m_csSenderName, m_csReceiverName );
376 csSubject += FormatString ( _T("Subject: %s\r\n"), m_csSubject );
377 csSubject += FormatString ( _T("X-Mailer: chrys\r\nMIME-Version: 1.0\r\nContent-Type: %s; %s boundary=%s\r\n\r\n") ,
378 m_csMIMEContentType, m_csCharSet, m_csPartBoundary );
380 return Send ( csSubject );
383 BOOL CHwSMTP::SendBody()
385 CString csBody, csTemp;
387 if ( m_StrAryAttach.GetSize() > 0 )
389 csTemp.Format ( _T("%s\r\n\r\n"), m_csNoMIMEText );
390 csBody += csTemp;
392 csTemp.Format ( _T("--%s\r\n"), m_csPartBoundary );
393 csBody += csTemp;
395 csTemp.Format ( _T("Content-Type: text/plain\r\n%sContent-Transfer-Encoding: 7Bit\r\n\r\n"),
396 m_csCharSet );
397 csBody += csTemp;
400 csTemp.Format ( _T("%s\r\n"), m_csBody );
401 csBody += csTemp;
403 if ( m_StrAryAttach.GetSize() > 0 )
405 csTemp.Format ( _T("--%s\r\n"), m_csPartBoundary );
406 csBody += csTemp;
409 return Send ( csBody );
412 BOOL CHwSMTP::SendAttach()
414 int nCountAttach = (int)m_StrAryAttach.GetSize();
415 if ( nCountAttach < 1 ) return TRUE;
417 for ( int i=0; i<nCountAttach; i++ )
419 if ( !SendOnAttach ( m_StrAryAttach.GetAt(i) ) )
420 return FALSE;
423 return TRUE;
426 BOOL CHwSMTP::SendOnAttach(LPCTSTR lpszFileName)
428 ASSERT ( lpszFileName );
429 CString csAttach, csTemp;
431 csTemp = lpszFileName;
432 CString csShortFileName = csTemp.GetBuffer(0) + csTemp.ReverseFind ( '\\' );
433 csShortFileName.TrimLeft ( _T("\\") );
435 csTemp.Format ( _T("Content-Type: application/octet-stream; file=%s\r\n"), csShortFileName );
436 csAttach += csTemp;
438 csTemp.Format ( _T("Content-Transfer-Encoding: base64\r\n") );
439 csAttach += csTemp;
441 csTemp.Format ( _T("Content-Disposition: attachment; filename=%s\r\n\r\n"), csShortFileName );
442 csAttach += csTemp;
444 DWORD dwFileSize = hwGetFileAttr(lpszFileName);
445 if ( dwFileSize > 5*1024*1024 )
447 m_csLastError.Format ( _T("File [%s] too big. File size is : %s"), lpszFileName, FormatBytes(dwFileSize) );
448 return FALSE;
450 char *pBuf = new char[dwFileSize+1];
451 if ( !pBuf )
453 ::AfxThrowMemoryException ();
454 return FALSE;
457 CFile file;
460 if ( !file.Open ( lpszFileName, CFile::modeRead ) )
462 m_csLastError.Format ( _T("Open file [%s] failed"), lpszFileName );
463 return FALSE;
465 UINT nFileLen = file.Read ( pBuf, dwFileSize );
466 CBase64 Base64Encode;
467 csTemp = Base64Encode.Encode ( pBuf, nFileLen );
468 csAttach += csTemp;
469 csAttach += _T("\r\n\r\n");
471 catch ( CFileException e )
473 e.Delete();
474 m_csLastError.Format ( _T("Read file [%s] failed"), lpszFileName );
475 delete[] pBuf;
476 return FALSE;
479 csTemp.Format ( _T("--%s\r\n"), m_csPartBoundary );
480 csAttach += csTemp;
482 delete[] pBuf;
484 return Send ( csAttach );
487 CString CHwSMTP::GetLastErrorText()
489 return m_csLastError;
493 DWORD WINAPI ThreadProc_SendEmail( LPVOID lpParameter )
495 CEMailObject *pEMailObject = (CEMailObject*)lpParameter;
496 ASSERT ( pEMailObject );
498 CHwSMTP HwSMTP;
499 BOOL bRet = HwSMTP.SendEmail (
500 pEMailObject->m_csSmtpSrvHost,
501 pEMailObject->m_csUserName,
502 pEMailObject->m_csPasswd,
503 pEMailObject->m_bMustAuth,
504 pEMailObject->m_csAddrFrom,
505 pEMailObject->m_csAddrTo,
506 pEMailObject->m_csSenderName,
507 pEMailObject->m_csReceiverName,
508 pEMailObject->m_csSubject,
509 pEMailObject->m_csBody,
510 pEMailObject->m_csCharSet,
511 &pEMailObject->m_StrAryAttach,
512 &pEMailObject->m_StrAryCC,
513 pEMailObject->m_nSmtpSrvPort
515 if ( !bRet)
517 #ifdef _DEBUG
518 CString csError = HwSMTP.GetLastErrorText ();
519 csError = FormatString ( _T("Send a email to [%s] failed."), pEMailObject->m_csSmtpSrvHost );
520 AfxMessageBox ( csError );
521 #endif
524 m_CSFor__g_PtrAry_Threads.Lock ();
525 int nFindPos = FindFromArray ( g_PtrAry_Threads, pEMailObject->m_hThread );
526 if ( nFindPos >= 0 )
527 g_PtrAry_Threads.RemoveAt ( nFindPos );
528 m_CSFor__g_PtrAry_Threads.Unlock ();
530 delete pEMailObject;
531 return bRet;
535 // Óà SMTP ·þÎñ·¢Ë͵ç×ÓÓʼþ£¬Èç¹ûÉèÖòÎÊý bViaThreadSend=TRUE£¬ÄÇÔÚ³ÌÐò½áÊøʱӦ¸ÃÔÚ ExitInstance() Öе÷Óà EndOfSMTP() º¯Êý
537 BOOL SendEmail (
538 BOOL bViaThreadSend,
539 LPCTSTR lpszSmtpSrvHost,
540 LPCTSTR lpszUserName,
541 LPCTSTR lpszPasswd,
542 BOOL bMustAuth,
543 LPCTSTR lpszAddrFrom,
544 LPCTSTR lpszAddrTo,
545 LPCTSTR lpszSenderName,
546 LPCTSTR lpszReceiverName,
547 LPCTSTR lpszSubject,
548 LPCTSTR lpszBody,
549 LPCTSTR lpszCharSet/*=NULL*/,
550 CStringArray *pStrAryAttach/*=NULL*/,
551 CStringArray *pStrAryCC/*=NULL*/,
552 UINT nSmtpSrvPort/*=25*/
555 if ( !lpszSmtpSrvHost || lstrlen(lpszSmtpSrvHost) < 1 ||
556 !lpszSubject || lstrlen(lpszSubject) < 1 ||
557 !lpszBody || lstrlen(lpszBody) < 1 )
559 AfxMessageBox ( _T("Parameter error !") );
560 return FALSE;
563 CEMailObject *pEMailObject = new CEMailObject (
564 lpszSmtpSrvHost,
565 lpszUserName,
566 lpszPasswd,
567 bMustAuth,
568 lpszAddrFrom,
569 lpszAddrTo,
570 lpszSenderName,
571 lpszReceiverName,
572 lpszSubject,
573 lpszBody,
574 lpszCharSet,
575 pStrAryAttach,
576 pStrAryCC,
577 nSmtpSrvPort
579 if ( !pEMailObject ) return FALSE;
581 BOOL bRet = FALSE;
582 if ( bViaThreadSend )
584 DWORD dwThreadId = 0;
585 pEMailObject->m_hThread = ::CreateThread ( NULL, 0, ::ThreadProc_SendEmail, pEMailObject, CREATE_SUSPENDED, &dwThreadId );
586 bRet = HANDLE_IS_VALID(pEMailObject->m_hThread);
587 m_CSFor__g_PtrAry_Threads.Lock();
588 g_PtrAry_Threads.Add ( pEMailObject->m_hThread );
589 m_CSFor__g_PtrAry_Threads.Unlock();
590 ResumeThread ( pEMailObject->m_hThread );
592 else
594 bRet = (BOOL)ThreadProc_SendEmail ( pEMailObject );
597 return bRet;
600 void EndOfSMTP ()
602 // µÈ´ýËùÓÐÏß³ÌÖ´ÐÐÍê±Ï
603 for ( int i=0; i<g_PtrAry_Threads.GetSize(); i++ )
605 HANDLE hThread = (HANDLE)g_PtrAry_Threads.GetAt(i);
606 if ( HANDLE_IS_VALID(hThread) )
608 WaitForThreadEnd ( &hThread, 30*1000 );
611 g_PtrAry_Threads.RemoveAll ();
616 // ½«×Ö·û´® lpszOrg ת»»Îª¶à×Ö½ÚµÄ×Ö·û´®£¬Èç¹û»¹ÒªÊ¹Óöà×Ö·û´®µÄ³¤¶È£¬¿ÉÒÔÓÃÒÔÏ·½Ê½À´Ê¹ÓÃÕâ¸öÀࣺ
617 // CMultiByteString MultiByteString(_T("UNICODE×Ö·û´®"));
618 // printf ( "ANSI ×Ö·û´®Îª£º %s£¬ ×Ö·û¸öÊýΪ£º %d £¬ ³¤¶ÈΪ£º %d×Ö½Ú\n", MultiByteString.GetBuffer(), MultiByteString.GetLength(), MultiByteString.GetSize() );
620 CMultiByteString::CMultiByteString( LPCTSTR lpszOrg, int nOrgStringEncodeType/*=STRING_IS_SOFTCODE*/, OUT char *pOutBuf/*=NULL*/, int nOutBufSize/*=0*/ )
622 m_bNewBuffer = FALSE;
623 m_pszData = NULL;
624 m_nDataSize = 0;
625 m_nCharactersNumber = 0;
626 if ( !lpszOrg ) return;
628 // ÅжÏԭʼ×Ö·û´®µÄ±àÂ뷽ʽ
629 BOOL bOrgIsUnicode = FALSE;
630 if ( nOrgStringEncodeType == STRING_IS_MULTICHARS ) bOrgIsUnicode = FALSE;
631 else if ( nOrgStringEncodeType == STRING_IS_UNICODE ) bOrgIsUnicode = TRUE;
632 else
634 #ifdef UNICODE
635 bOrgIsUnicode = TRUE;
636 #else
637 bOrgIsUnicode = FALSE;
638 #endif
641 // ¼ÆËã×Ö·û´®¸öÊýºÍÐèÒªµÄÄ¿±ê»º³å´óС
642 if ( bOrgIsUnicode )
644 m_nCharactersNumber = (int)wcslen((WCHAR*)lpszOrg);
645 m_nDataSize = (m_nCharactersNumber + 1) * sizeof(WCHAR);
647 else
649 m_nCharactersNumber = (int)strlen((char*)lpszOrg);
650 m_nDataSize = (m_nCharactersNumber + 1) * sizeof(char);
653 // ʹÓõ÷ÓÃÕß´«ÈëµÄ»º³å
654 if ( pOutBuf && nOutBufSize > 0 )
656 m_pszData = pOutBuf;
657 m_nDataSize = nOutBufSize;
659 // ×Ô¼ºÉêÇëÄڴ滺³å
660 else
662 m_pszData = (char*)new BYTE[m_nDataSize];
663 if ( !m_pszData )
665 ::AfxThrowMemoryException ();
666 return;
668 m_bNewBuffer = TRUE;
670 memset ( m_pszData, 0, m_nDataSize );
672 if ( bOrgIsUnicode )
674 m_nCharactersNumber = WideCharToMultiByte ( CP_ACP, 0, (LPCWSTR)lpszOrg, m_nCharactersNumber, (LPSTR)m_pszData, m_nDataSize/sizeof(char)-1, NULL, NULL );
675 if ( m_nCharactersNumber < 1 ) m_nCharactersNumber = (int)strlen ( m_pszData );
677 else
679 m_nCharactersNumber = __min ( m_nCharactersNumber, (int)(m_nDataSize/sizeof(char)-1) );
680 strncpy ( m_pszData, (const char*)lpszOrg, m_nCharactersNumber );
681 m_nCharactersNumber = (int)strlen ( m_pszData );
683 m_nDataSize = ( m_nCharactersNumber + 1 ) * sizeof(char);
686 CMultiByteString::~CMultiByteString ()
688 if ( m_bNewBuffer && m_pszData )
690 delete[] m_pszData;
695 // ½« lpszOrg ת»»Îª¸Ã³ÌÐòʹÓõıàÂë×Ö·û´®£¬Èç¹û¸Ã³ÌÐòÊÇ UNICODE ¾ÍתΪ UNICODE£¬Èç¹ûÊÇ ANSI ¾ÍתΪ ANSI µÄ
697 CString GetCompatibleString ( LPVOID lpszOrg, BOOL bOrgIsUnicode, int nOrgLength/*=-1*/ )
699 if ( !lpszOrg ) return _T("");
703 #ifdef UNICODE
704 if ( bOrgIsUnicode )
706 if ( nOrgLength > 0 )
708 WCHAR *szRet = new WCHAR[nOrgLength+1];
709 if ( !szRet ) return _T("");
710 memset ( szRet, 0, (nOrgLength+1)*sizeof(WCHAR) );
711 memcpy ( szRet, lpszOrg, nOrgLength*sizeof(WCHAR) );
712 CString csRet = szRet;
713 delete[] szRet;
714 return csRet;
716 else if ( nOrgLength == 0 )
717 return _T("");
718 else
719 return (LPCTSTR)lpszOrg;
722 if ( nOrgLength < 0 )
723 nOrgLength = (int)strlen((const char*)lpszOrg);
724 int nWideCount = nOrgLength + 1;
725 WCHAR *wchar = new WCHAR[nWideCount];
726 if ( !wchar ) return _T("");
727 memset ( wchar, 0, nWideCount*sizeof(WCHAR) );
728 ::MultiByteToWideChar(CP_ACP, 0, (LPCSTR)lpszOrg, nOrgLength, wchar, nWideCount);
729 CString csRet = wchar;
730 delete[] wchar;
731 return csRet;
732 #else
733 if ( !bOrgIsUnicode )
735 if ( nOrgLength > 0 )
737 char *szRet = new char[nOrgLength+1];
738 if ( !szRet ) return _T("");
739 memset ( szRet, 0, (nOrgLength+1)*sizeof(char) );
740 memcpy ( szRet, lpszOrg, nOrgLength*sizeof(char) );
741 CString csRet = szRet;
742 delete[] szRet;
743 return csRet;
745 else if ( nOrgLength == 0 )
746 return _T("");
747 else
748 return (LPCTSTR)lpszOrg;
751 if ( nOrgLength < 0 )
752 nOrgLength = (int)wcslen((WCHAR*)lpszOrg);
753 int nMultiByteCount = nOrgLength + 1;
754 char *szMultiByte = new char[nMultiByteCount];
755 if ( !szMultiByte ) return _T("");
756 memset ( szMultiByte, 0, nMultiByteCount*sizeof(char) );
757 ::WideCharToMultiByte ( CP_ACP, 0, (LPCWSTR)lpszOrg, nOrgLength, (LPSTR)szMultiByte, nMultiByteCount, NULL, NULL );
758 CString csRet = szMultiByte;
759 delete[] szMultiByte;
760 return csRet;
761 #endif
763 CATCH_ALL(e)
765 THROW_LAST ();
767 END_CATCH_ALL
769 return _T("");
772 CString FormatDateTime ( COleDateTime &DateTime, LPCTSTR pFormat )
774 // If null, return empty string
775 if ( DateTime.GetStatus() == COleDateTime::null || DateTime.GetStatus() == COleDateTime::invalid )
776 return _T("");
778 UDATE ud;
779 if (S_OK != VarUdateFromDate(DateTime.m_dt, 0, &ud))
781 return _T("");
784 struct tm tmTemp;
785 tmTemp.tm_sec = ud.st.wSecond;
786 tmTemp.tm_min = ud.st.wMinute;
787 tmTemp.tm_hour = ud.st.wHour;
788 tmTemp.tm_mday = ud.st.wDay;
789 tmTemp.tm_mon = ud.st.wMonth - 1;
790 tmTemp.tm_year = ud.st.wYear - 1900;
791 tmTemp.tm_wday = ud.st.wDayOfWeek;
792 tmTemp.tm_yday = ud.wDayOfYear - 1;
793 tmTemp.tm_isdst = 0;
795 CString strDate;
796 LPTSTR lpszTemp = strDate.GetBufferSetLength(256);
797 _tcsftime(lpszTemp, strDate.GetLength(), pFormat, &tmTemp);
798 strDate.ReleaseBuffer();
800 return strDate;
803 CString FormatString ( LPCTSTR lpszStr, ... )
805 TCHAR *buf = NULL;
806 // Ñ­»·¸ñʽ»¯×Ö·û´®£¬Èç¹û»º³å²»¹»Ôò½«»º³å¼Ó´óÈ»ºóÖØÊÔÒÔ±£Ö¤»º³å¹»ÓÃͬʱÓÖ²»ÀË·Ñ
807 for ( int nBufCount = 1024; nBufCount<5*1024*1024; nBufCount += 1024 )
809 buf = new TCHAR[nBufCount];
810 if ( !buf )
812 ::AfxThrowMemoryException ();
813 return _T("");
815 memset ( buf, 0, nBufCount*sizeof(TCHAR) );
817 va_list va;
818 va_start (va, lpszStr);
819 int nLen = _vsnprintf_hw ((TCHAR*)buf, nBufCount-sizeof(TCHAR), lpszStr, va);
820 va_end(va);
821 if ( nLen <= (int)(nBufCount-sizeof(TCHAR)) )
822 break;
823 delete[] buf; buf = NULL;
825 if ( !buf )
827 return _T("");
830 CString csMsg = buf;
831 delete[] buf; buf = NULL;
832 return csMsg;
835 /********************************************************************************
836 * Function Type : Global
837 * Parameter : lpFileName - Îļþ·¾¶
838 * Return Value : -1 - ʧ°Ü
839 * >=0 - Îļþ´óС
840 * Description : »ñÈ¡ÎļþÊôÐÔ ( Îļþ´óС¡¢´´½¨Ê±¼ä )
841 *********************************************************************************/
842 int hwGetFileAttr ( LPCTSTR lpFileName, OUT CFileStatus *pFileStatus/*=NULL*/ )
844 if ( !lpFileName || lstrlen(lpFileName) < 1 ) return -1;
846 CFileStatus fileStatus;
847 fileStatus.m_attribute = 0;
848 fileStatus.m_size = 0;
849 memset ( fileStatus.m_szFullName, 0, sizeof(fileStatus.m_szFullName) );
850 BOOL bRet = FALSE;
853 if ( CFile::GetStatus(lpFileName,fileStatus) )
855 bRet = TRUE;
858 CATCH (CFileException, e)
860 ASSERT ( FALSE );
861 bRet = FALSE;
863 CATCH_ALL(e)
865 ASSERT ( FALSE );
866 bRet = FALSE;
868 END_CATCH_ALL;
870 if ( pFileStatus )
872 pFileStatus->m_ctime = fileStatus.m_ctime;
873 pFileStatus->m_mtime = fileStatus.m_mtime;
874 pFileStatus->m_atime = fileStatus.m_atime;
875 pFileStatus->m_size = fileStatus.m_size;
876 pFileStatus->m_attribute = fileStatus.m_attribute;
877 pFileStatus->_m_padding = fileStatus._m_padding;
878 lstrcpy ( pFileStatus->m_szFullName, fileStatus.m_szFullName );
882 return (int)fileStatus.m_size;
886 // ½«Ò»¸ö±íʾ×Ö½ÚµÄÊýÓÿɶÁÐԺõÄ×Ö·û´®À´±íʾ£¬ÀýÈ罫 12345678 ×Ö½Úת»»Îª£º
887 // 11.77M
888 // nFlag - 0 : ×Ô¶¯Æ¥Å䵥λ
889 // 1 : ÒÔ Kb Ϊµ¥Î»
890 // 2 : ÒÔ Mb Ϊµ¥Î»
891 // 3 : ÒÔ Gb Ϊµ¥Î»
893 CString FormatBytes ( double fBytesNum, BOOL bShowUnit/*=TRUE*/, int nFlag/*=0*/ )
895 CString csRes;
896 if ( nFlag == 0 )
898 if ( fBytesNum >= 1024.0 && fBytesNum < 1024.0*1024.0 )
899 csRes.Format ( _T("%.2f%s"), fBytesNum / 1024.0, bShowUnit?_T(" K"):_T("") );
900 else if ( fBytesNum >= 1024.0*1024.0 && fBytesNum < 1024.0*1024.0*1024.0 )
901 csRes.Format ( _T("%.2f%s"), fBytesNum / (1024.0*1024.0), bShowUnit?_T(" M"):_T("") );
902 else if ( fBytesNum >= 1024.0*1024.0*1024.0 )
903 csRes.Format ( _T("%.2f%s"), fBytesNum / (1024.0*1024.0*1024.0), bShowUnit?_T(" G"):_T("") );
904 else
905 csRes.Format ( _T("%.2f%s"), fBytesNum, bShowUnit?_T(" B"):_T("") );
907 else if ( nFlag == 1 )
909 csRes.Format ( _T("%.2f%s"), fBytesNum / 1024.0, bShowUnit?_T(" K"):_T("") );
911 else if ( nFlag == 2 )
913 csRes.Format ( _T("%.2f%s"), fBytesNum / (1024.0*1024.0), bShowUnit?_T(" M"):_T("") );
915 else if ( nFlag == 3 )
917 csRes.Format ( _T("%.2f%s"), fBytesNum / (1024.0*1024.0*1024.0), bShowUnit?_T(" G"):_T("") );
920 return csRes;
924 // µÈ´ýÏß³ÌÍ˳ö
926 BOOL WaitForThreadEnd ( HANDLE *phThread, DWORD dwWaitTime /*=10*1000*/ )
928 BOOL bRet = TRUE;
929 ASSERT ( phThread );
930 if ( !(*phThread) ) return TRUE;
931 if ( ::WaitForSingleObject ( *phThread, dwWaitTime ) == WAIT_TIMEOUT )
933 bRet = FALSE;
934 ::TerminateThread ( *phThread, 0 );
936 ::CloseHandle ( *phThread );
937 (*phThread) = NULL;
938 return bRet;