2012-03-30 3 views
3

MAPI (Windows Mail API)에는 UTF8과 관련된 문제가 있습니다 (또는 어쩌면 내가 잘못 했음).WIndows MAPI unicode 문제

코드 샘플 :

HMODULE m_hLib = LoadLibraryA("MAPI32.DLL"); 
if (m_hLib == NULL) 
    return SEND_MAIL_CANCELED; 
LPMAPISENDMAIL SendMail; 
SendMail = (LPMAPISENDMAIL) GetProcAddress(m_hLib, "MAPISendMail"); 
if (!SendMail) 
    return; 

MapiFileDesc fileDesc; 
ZeroMemory(&fileDesc, sizeof(fileDesc)); 
fileDesc.nPosition = (ULONG) -1; 
fileDesc.lpszPathName = (LPSTR) filePath.toUtf8(); 
fileDesc.lpszFileName = (LPSTR) fileName.toUtf8(); 

MapiRecipDesc recipientData; 
ZeroMemory(&recipientData, sizeof(recipientData)); 
recipientData.lpszName = (LPSTR) recipient.toUtf8(); 
recipientData.ulRecipClass = MAPI_TO; 

MapiMessage message; 
ZeroMemory(&message, sizeof(message)); 
message.ulReserved = CP_UTF8; 
message.lpszSubject = (LPSTR) title.toUtf8(); 
message.nFileCount = 1; 
message.lpFiles = &fileDesc; 
message.nRecipCount = 1; 
message.lpRecips = &recipientData; 

int nError = SendMail(0, NULL, &message, MAPI_LOGON_UI | MAPI_DIALOG, 0); 

title, filePath, fileNamerecipient 모든 std::string들입니다. 내가 아는 한, UTF8은 아스키 (ASCII도 가능)와 호환되므로 문자열은 아무런 문제없이 그러한 값을 유지할 수 있습니다.

나는 이런 식으로 wstring을에서 UTF8로 변환 해요 :

int requiredSize = WideCharToMultiByte(CP_UTF8, 0, data.c_str(), -1, 0, 0, 0, 0); 
if(requiredSize > 0) 
{ 
    std::vector<char> buffer(requiredSize); 
    WideCharToMultiByte(CP_UTF8, 0, data.c_str(), -1, &buffer[0], requiredSize, 0, 0); 
    this->container.append(buffer.begin(), buffer.end() - 1); 
} 

containerstd::string 개체입니다.

+0

실제 질문은 무엇입니까? 당신은 무엇을 기대하고 있으며, 당신은 무엇을 얻고 있습니까? –

답변

8

MAPISendMail()은 Ansi 만 UTF-8을 지원하지 않습니다. 유니 코드 데이터를 보내야하는 경우 Windows 7 이하에서는 MAPISendMailHelper()을 사용해야하고 Windows 8 이상에서는 MAPISendMailW()을 사용해야합니다. 이것은 MAPISendMail() documentation에 분명히 명시되어 있습니다.

cchWideChar 매개 변수를 -1로 설정하면 WideCharToMultiByte()에 널 종결자가 포함됩니다. 따라서 귀하는 인코딩하여 해당 null 종결자를 container 데이터에 포함 시켰습니다. 대신 완전히 null 종결 방지하기 위해 문자열의 실제 길이에 cchWideChar을 설정해야합니다 http://msdn.microsoft.com/en-us/library/windows/desktop/dd296721.aspx

int requiredSize = WideCharToMultiByte(CP_UTF8, 0, data.c_str(), data.length(), 0, 0, 0, 0); 
if (requiredSize > 0) 
{ 
    std::vector<char> buffer(requiredSize); 
    WideCharToMultiByte(CP_UTF8, 0, data.c_str(), data.length(), &buffer[0], requiredSize, 0, 0); 
    container.append(buffer.begin(), buffer.end()); 
} 

이 상태를 "Windows 7에서 이전 : 사용 MAPISendMailHelper은 메시지를 보내"하지만 http://msdn.microsoft.com/en-us/library/windows/desktop/hh802867.aspx의 하단에 그것은 "최소 지원"은 Windows 8입니다. 모순 된 정보처럼 보이므로 MAPISendMailHelper가 실제로 Windows 7 및 이전 버전인지 여부가 불분명합니다.

+1

MAPISendMailHelper는 Windows 7 서비스 팩 1에 존재하지 않습니다. mapped.exe를 사용하여 mapi32.dll의 내 보낸 기능을 검색했습니다. MAPISendMailHelper는 mapi32.dll에서 내 보내지 않습니다. –

+4

MAPISendMailHelper는 모든 dll에서 내보낼 수 없습니다. 최신 Windows SDK에서 코드로 제공됩니다. 이 파일은 "MapiUnicodeHelp.h"파일에 있습니다. – Swythan

+0

Win7 및 이전 버전에서 MAPISendMailHelper()는 유니 코드 구조체를 ANSI 구조체로 변환하고 MapiSendMailW() 대신 MapiSendMail()을 호출합니다. 즉, 기본 MAPI 공급자 (즉, Win8 MAPI)가 아니라면 유니 코드 MAPI를 지원하지 않습니다. 유일한 목적은 클라이언트 코드를 단순화하는 것입니다. Windows 버전에 따라 다른 구조체를 작성하고 다른 함수를 호출 할 필요가 없습니다. – chrisd