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