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