OpenCPN Partial API docs
Loading...
Searching...
No Matches
smapi.cpp
Go to the documentation of this file.
1
2// Name: smapi.cpp
3// Purpose: Simple MAPI classes
4// Author: PJ Naughter <pjna@naughter.com>
5// Modified by: Julian Smart
6// Created: 2001-08-21
7// RCS-ID: $Id: smapi.cpp 35650 2005-09-23 12:56:45Z MR $
8// Copyright: (c) PJ Naughter
9// Licence: wxWindows licence
11
15// For compilers that support precompilation, includes "wx/wx.h".
16#include "wx/wxprec.h"
17
18#ifdef __BORLANDC__
19#pragma hdrstop
20#endif
21
22#ifdef __WXMSW__
23
24#ifndef WX_PRECOMP
25#include "wx/wx.h"
26#endif
27
28#include "wx/string.h"
29#include "wx/msw/private.h"
30
31// mapi.h in Cygwin's include directory isn't a full implementation and is
32// not sufficient for this lib. However recent versions of Cygwin also
33// have another mapi.h in include/w32api which can be used.
34//
35#ifdef __CYGWIN__
36#include <w32api/mapi.h>
37#else
38#include <mapi.h>
39#endif
40
41#include "smapi.h"
42
43class WXDLLIMPEXP_NETUTILS wxMapiData {
44public:
45 wxMapiData() {
46 m_hSession = 0;
47 m_nLastError = 0;
48 m_hMapi = nullptr;
49 m_lpfnMAPILogon = nullptr;
50 m_lpfnMAPILogoff = nullptr;
51 m_lpfnMAPISendMail = nullptr;
52 m_lpfnMAPIResolveName = nullptr;
53 m_lpfnMAPIFreeBuffer = nullptr;
54 }
55
56 // Data
57 LHANDLE m_hSession; // Mapi Session handle
58 long m_nLastError; // Last Mapi error value
59 HINSTANCE m_hMapi; // Instance handle of the MAPI dll
60 LPMAPILOGON m_lpfnMAPILogon; // MAPILogon function pointer
61 LPMAPILOGOFF m_lpfnMAPILogoff; // MAPILogoff function pointer
62 LPMAPISENDMAIL m_lpfnMAPISendMail; // MAPISendMail function pointer
63 LPMAPIRESOLVENAME m_lpfnMAPIResolveName; // MAPIResolveName function pointer
64 LPMAPIFREEBUFFER m_lpfnMAPIFreeBuffer; // MAPIFreeBuffer function pointer
65};
66
68
69wxMapiSession::wxMapiSession() {
70 m_data = new wxMapiData;
71
72 Initialise();
73}
74
75wxMapiSession::~wxMapiSession() {
76 // Logoff if logged on
77 Logoff();
78
79 // Unload the MAPI dll
80 Deinitialise();
81
82 delete m_data;
83}
84
85void wxMapiSession::Initialise() {
86 // First make sure the "WIN.INI" entry for MAPI is present aswell
87 // as the MAPI32 dll being present on the system
88 bool bMapiInstalled = (GetProfileInt(_T("MAIL"), _T("MAPI"), 0) != 0) &&
89 (SearchPath(nullptr, _T("MAPI32.DLL"), nullptr, 0,
90 nullptr, nullptr) != 0);
91
92 if (bMapiInstalled) {
93 // Load up the MAPI dll and get the function pointers we are interested in
94 m_data->m_hMapi = ::LoadLibrary(_T("MAPI32.DLL"));
95 if (m_data->m_hMapi) {
96 m_data->m_lpfnMAPILogon =
97 (LPMAPILOGON)GetProcAddress(m_data->m_hMapi, "MAPILogon");
98 m_data->m_lpfnMAPILogoff =
99 (LPMAPILOGOFF)GetProcAddress(m_data->m_hMapi, "MAPILogoff");
100 m_data->m_lpfnMAPISendMail =
101 (LPMAPISENDMAIL)GetProcAddress(m_data->m_hMapi, "MAPISendMail");
102 m_data->m_lpfnMAPIResolveName =
103 (LPMAPIRESOLVENAME)GetProcAddress(m_data->m_hMapi, "MAPIResolveName");
104 m_data->m_lpfnMAPIFreeBuffer =
105 (LPMAPIFREEBUFFER)GetProcAddress(m_data->m_hMapi, "MAPIFreeBuffer");
106
107 // If any of the functions are not installed then fail the load
108 if (m_data->m_lpfnMAPILogon == nullptr ||
109 m_data->m_lpfnMAPILogoff == nullptr ||
110 m_data->m_lpfnMAPISendMail == nullptr ||
111 m_data->m_lpfnMAPIResolveName == nullptr ||
112 m_data->m_lpfnMAPIFreeBuffer == nullptr) {
113 wxLogMessage(
114 _T("MAIL Error: Failed to get one of the functions pointer in ")
115 _T("MAPI32.DLL\n"));
116 Deinitialise();
117 }
118 }
119 } else {
120 wxLogMessage(
121 _("MAIL Error: MAPI32.DLL is not installed or invalid on this "
122 "computer!"));
123 }
124}
125
126void wxMapiSession::Deinitialise() {
127 if (m_data->m_hMapi) {
128 // Unload the MAPI dll and reset the function pointers to nullptr
129 FreeLibrary(m_data->m_hMapi);
130 m_data->m_hMapi = nullptr;
131 m_data->m_lpfnMAPILogon = nullptr;
132 m_data->m_lpfnMAPILogoff = nullptr;
133 m_data->m_lpfnMAPISendMail = nullptr;
134 m_data->m_lpfnMAPIResolveName = nullptr;
135 m_data->m_lpfnMAPIFreeBuffer = nullptr;
136 }
137}
138
139bool wxMapiSession::Logon(const wxString& sProfileName,
140 const wxString& sPassword, wxWindow* pParentWnd) {
141 wxASSERT(MapiInstalled()); // MAPI must be installed
142 wxASSERT(m_data->m_lpfnMAPILogon); // Function pointer must be valid
143
144 // Initialise the function return value
145 bool bSuccess = FALSE;
146
147 // Just in case we are already logged in
148 Logoff();
149
150 // Setup the ascii versions of the profile name and password
151 int nProfileLength = sProfileName.Length();
152
153 LPSTR pszProfileName = nullptr;
154 LPSTR pszPassword = nullptr;
155 wxCharBuffer cbProfile(1), cbPassword(1);
156 if (nProfileLength) {
157#ifndef UNICODE
158 pszProfileName = (LPSTR)sProfileName.c_str();
159 pszPassword = (LPSTR)sPassword.c_str();
160#else
161 cbProfile = sProfileName.mb_str();
162 cbPassword = sPassword.mb_str();
163 pszProfileName = cbProfile.data();
164 pszPassword = cbPassword.data();
165#endif
166 }
167
168 // Setup the flags & UIParam parameters used in the MapiLogon call
169 FLAGS flags = 0;
170 ULONG nUIParam = 0;
171 if (nProfileLength == 0) {
172 // No profile name given, then we must interactively request a profile name
173 if (pParentWnd) {
174 nUIParam = (ULONG_PTR)(HWND)pParentWnd->GetHWND();
175 flags |= MAPI_LOGON_UI;
176 } else {
177 // No window given, just use the main window of the app as the parent
178 // window
179 if (wxTheApp->GetTopWindow()) {
180 nUIParam = (ULONG_PTR)(HWND)wxTheApp->GetTopWindow()->GetHWND();
181 flags |= MAPI_LOGON_UI;
182 }
183 }
184 }
185
186 // First try to acquire a new MAPI session using the supplied settings using
187 // the MAPILogon functio
188 ULONG nError =
189 m_data->m_lpfnMAPILogon(nUIParam, pszProfileName, pszPassword,
190 flags | MAPI_NEW_SESSION, 0, &m_data->m_hSession);
191 if (nError != SUCCESS_SUCCESS && nError != MAPI_E_USER_ABORT) {
192 // Failed to create a create mapi session, try to acquire a shared mapi
193 // session wxLogDebug(_T("Failed to logon to MAPI using a new session,
194 // trying to acquire a shared one\n"));
195 nError = m_data->m_lpfnMAPILogon(nUIParam, nullptr, nullptr, 0, 0,
196 &m_data->m_hSession);
197 if (nError == SUCCESS_SUCCESS) {
198 m_data->m_nLastError = SUCCESS_SUCCESS;
199 bSuccess = TRUE;
200 } else {
201 wxLogMessage(
202 _T("MAIL Error: Failed to logon to MAPI using a shared session, ")
203 _T("Error:%ld\n"),
204 nError);
205 m_data->m_nLastError = nError;
206 }
207 } else if (nError == SUCCESS_SUCCESS) {
208 m_data->m_nLastError = SUCCESS_SUCCESS;
209 bSuccess = TRUE;
210 }
211
212 return bSuccess;
213}
214
215bool wxMapiSession::LoggedOn() const { return (m_data->m_hSession != 0); }
216
217bool wxMapiSession::MapiInstalled() const {
218 return (m_data->m_hMapi != nullptr);
219}
220
221bool wxMapiSession::Logoff() {
222 wxASSERT(MapiInstalled()); // MAPI must be installed
223 wxASSERT(m_data->m_lpfnMAPILogoff); // Function pointer must be valid
224
225 // Initialise the function return value
226 bool bSuccess = FALSE;
227
228 if (m_data->m_hSession) {
229 // Call the MAPILogoff function
230 ULONG nError = m_data->m_lpfnMAPILogoff(m_data->m_hSession, 0, 0, 0);
231 if (nError != SUCCESS_SUCCESS) {
232 wxLogMessage(_T("MAIL Error: Failed in call to MapiLogoff, Error:%ld"),
233 nError);
234 m_data->m_nLastError = nError;
235 bSuccess = TRUE;
236 } else {
237 m_data->m_nLastError = SUCCESS_SUCCESS;
238 bSuccess = TRUE;
239 }
240 m_data->m_hSession = 0;
241 }
242
243 return bSuccess;
244}
245
246bool wxMapiSession::Resolve(const wxString& sName, void* lppRecip1) {
247 lpMapiRecipDesc* lppRecip = (lpMapiRecipDesc*)lppRecip1;
248
249 wxASSERT(MapiInstalled()); // MAPI must be installed
250 wxASSERT(m_data->m_lpfnMAPIResolveName); // Function pointer must be valid
251 wxASSERT(LoggedOn()); // Must be logged on to MAPI
252 wxASSERT(m_data->m_hSession); // MAPI session handle must be valid
253
254 // Call the MAPIResolveName function
255#ifndef UNICODE
256 LPSTR lpszAsciiName = (LPSTR)sName.c_str();
257#else
258 wxCharBuffer cbName(1);
259 cbName = sName.mb_str();
260 LPSTR lpszAsciiName = cbName.data();
261#endif
262 ULONG nError = m_data->m_lpfnMAPIResolveName(m_data->m_hSession, 0,
263 lpszAsciiName, 0, 0, lppRecip);
264 if (nError != SUCCESS_SUCCESS) {
265 wxLogMessage(_T("MAIL Error: Failed to resolve the name: %s, Error:%ld\n"),
266 sName.c_str(), nError);
267 m_data->m_nLastError = nError;
268 }
269
270 return (nError == SUCCESS_SUCCESS);
271}
272
273bool wxMapiSession::Send(wxMailMessage& message) {
274 wxASSERT(MapiInstalled()); // MAPI must be installed
275 wxASSERT(m_data->m_lpfnMAPISendMail); // Function pointer must be valid
276 wxASSERT(m_data->m_lpfnMAPIFreeBuffer); // Function pointer must be valid
277 wxASSERT(LoggedOn()); // Must be logged on to MAPI
278 wxASSERT(m_data->m_hSession); // MAPI session handle must be valid
279
280 // Initialise the function return value
281 bool bSuccess = FALSE;
282
283 // Create the MapiMessage structure to match the message parameter send into
284 // us
285 MapiMessage mapiMessage;
286 ZeroMemory(&mapiMessage, sizeof(mapiMessage));
287#ifndef UNICODE
288 mapiMessage.lpszSubject = (LPSTR)message.m_subject.c_str();
289 mapiMessage.lpszNoteText = (LPSTR)message.m_body.c_str();
290#else
291 wxCharBuffer cbSubject(1), cbBody(1), cbOriginator(1);
292 cbSubject = message.m_subject.mb_str();
293 cbBody = message.m_body.mb_str();
294 mapiMessage.lpszSubject = cbSubject.data();
295 mapiMessage.lpszNoteText = cbBody.data();
296#endif
297 mapiMessage.nRecipCount = message.m_to.GetCount() + message.m_cc.GetCount() +
298 message.m_bcc.GetCount();
299 wxASSERT(mapiMessage.nRecipCount); // Must have at least 1 recipient!
300
301 // Allocate the recipients array
302 mapiMessage.lpRecips = new MapiRecipDesc[mapiMessage.nRecipCount];
303
304 // If we have a 'From' field, use it
305 if (!message.m_from.IsEmpty()) {
306 mapiMessage.lpOriginator = new MapiRecipDesc;
307 ZeroMemory(mapiMessage.lpOriginator, sizeof(MapiRecipDesc));
308
309 mapiMessage.lpOriginator->ulRecipClass = MAPI_ORIG;
310 // TODO Do we have to call Resolve?
311#ifndef UNICODE
312 mapiMessage.lpOriginator->lpszName = (LPSTR)message.m_from.c_str();
313#else
314 cbOriginator = message.m_from.mb_str();
315 mapiMessage.lpOriginator->lpszName = cbOriginator.data();
316#endif
317 }
318
319 // Setup the "To" recipients
320 int nRecipIndex = 0;
321 int nToSize = message.m_to.GetCount();
322 int i;
323 for (i = 0; i < nToSize; i++) {
324 MapiRecipDesc& recip = mapiMessage.lpRecips[nRecipIndex];
325 ZeroMemory(&recip, sizeof(MapiRecipDesc));
326 recip.ulRecipClass = MAPI_TO;
327 wxString& sName = message.m_to[i];
328
329 // Try to resolve the name
330 lpMapiRecipDesc lpTempRecip;
331 if (Resolve(sName, (void*)&lpTempRecip)) {
332 // Resolve worked, put the resolved name back into the sName
333 sName = wxString(lpTempRecip->lpszName, *wxConvCurrent);
334
335 // Don't forget to free up the memory MAPI allocated for us
336 m_data->m_lpfnMAPIFreeBuffer(lpTempRecip);
337 }
338#ifndef UNICODE
339 recip.lpszName = (LPSTR)sName.c_str();
340#else
341 recip.lpszName = sName.mb_str().release();
342#endif
343
344 ++nRecipIndex;
345 }
346
347 /* //Setup the "CC" recipients
348 int nCCSize = message.m_cc.GetCount();
349 for (i=0; i<nCCSize; i++)
350 {
351 MapiRecipDesc& recip = mapiMessage.lpRecips[nRecipIndex];
352 ZeroMemory(&recip, sizeof(MapiRecipDesc));
353 recip.ulRecipClass = MAPI_CC;
354 wxString& sName = message.m_cc[i];
355
356 //Try to resolve the name
357 lpMapiRecipDesc lpTempRecip;
358 if (Resolve(sName, (void*) &lpTempRecip))
359 {
360 //Resolve worked, put the resolved name back into the sName
361 sName = wxString(lpTempRecip->lpszName,*wxConvCurrent);
362
363 //Don't forget to free up the memory MAPI allocated for us
364 m_data->m_lpfnMAPIFreeBuffer(lpTempRecip);
365 }
366 #ifndef UNICODE
367 recip.lpszName = (LPSTR) sName.c_str();
368 #else
369 recip.lpszName = sName.mb_str().release();
370 #endif
371
372 ++nRecipIndex;
373 }
374
375 //Setup the "BCC" recipients
376 int nBCCSize = message.m_bcc.GetCount();
377 for (i=0; i<nBCCSize; i++)
378 {
379 MapiRecipDesc& recip = mapiMessage.lpRecips[nRecipIndex];
380 ZeroMemory(&recip, sizeof(MapiRecipDesc));
381 recip.ulRecipClass = MAPI_BCC;
382 wxString& sName = message.m_bcc[i];
383
384 //Try to resolve the name
385 lpMapiRecipDesc lpTempRecip;
386 if (Resolve(sName, (void*) &lpTempRecip))
387 {
388 //Resolve worked, put the resolved name back into the sName
389 sName = wxString(lpTempRecip->lpszName,wxConvCurrent);
390
391 //Don't forget to free up the memory MAPI allocated for us
392 m_data->m_lpfnMAPIFreeBuffer(lpTempRecip);
393 }
394 #ifndef UNICODE
395 recip.lpszName = (LPSTR) sName.c_str();
396 #else
397 recip.lpszName = sName.mb_str().release();
398 #endif
399
400 ++nRecipIndex;
401 }
402
403 //Setup the attachments
404 int nAttachmentSize = message.m_attachments.GetCount();
405 int nTitleSize = message.m_attachmentTitles.GetCount();
406 if (nTitleSize)
407 {
408 wxASSERT(nTitleSize == nAttachmentSize); //If you are going to set the
409 attachment titles then you must set
410 //the attachment title for each attachment
411 }
412 if (nAttachmentSize)
413 {
414 mapiMessage.nFileCount = nAttachmentSize;
415 mapiMessage.lpFiles = new MapiFileDesc[nAttachmentSize];
416 for (i=0; i<nAttachmentSize; i++)
417 {
418 MapiFileDesc& file = mapiMessage.lpFiles[i];
419 ZeroMemory(&file, sizeof(MapiFileDesc));
420 file.nPosition = 0xFFFFFFFF;
421 wxString& sFilename = message.m_attachments[i];
422
423 #ifndef UNICODE
424 file.lpszPathName = (LPSTR) sFilename.c_str();
425 #else
426 file.lpszPathName = sFilename.mb_str().release();
427 #endif
428 //file.lpszFileName = file.lpszPathName;
429 file.lpszFileName = nullptr;
430
431 if (nTitleSize && !message.m_attachmentTitles[i].IsEmpty())
432 {
433 wxString& sTitle = message.m_attachmentTitles[i];
434 #ifndef UNICODE
435 file.lpszFileName = (LPSTR) sTitle.c_str();
436 #else
437 file.lpszFileName = sTitle.mb_str().release();
438 #endif
439 }
440 }
441 }*/
442
443 // Do the actual send using MAPISendMail
444 ULONG nError = m_data->m_lpfnMAPISendMail(m_data->m_hSession, 0, &mapiMessage,
445 MAPI_DIALOG, 0);
446 if (nError == SUCCESS_SUCCESS) {
447 bSuccess = TRUE;
448 m_data->m_nLastError = SUCCESS_SUCCESS;
449 } else {
450 wxLogMessage(_T("MAIL Error: Failed to send mail message, Error:%ld\n"),
451 nError);
452 m_data->m_nLastError = nError;
453 }
454
455 /* //Tidy up the Attachements
456 if (nAttachmentSize)
457 {
458 #ifdef UNICODE
459 for (i = 0;i < nAttachmentSize;i++)
460 {
461 free(mapiMessage.lpFiles[i].lpszPathName);
462 free(mapiMessage.lpFiles[i].lpszFileName);
463 }
464 #endif
465 delete [] mapiMessage.lpFiles;
466 }*/
467
468 // Free up the Recipients and Originator memory
469#ifdef UNICODE
470 for (i = 0; i < nRecipIndex; i++) free(mapiMessage.lpRecips[i].lpszName);
471#endif
472 delete[] mapiMessage.lpRecips;
473
474 delete mapiMessage.lpOriginator;
475
476 return bSuccess;
477}
478
479long wxMapiSession::GetLastError() const { return m_data->m_nLastError; }
480
481#endif // __WXMSW__