mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-15 11:13:29 +00:00
1565 lines
41 KiB
C++
1565 lines
41 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
//
|
|
// MAPI Hooks for Communicator
|
|
// Note: THIS LIVES IN COMMUNICATOR THOUGH IT IS IN THE MAPIDLL FOR
|
|
// BUILD REASONS
|
|
// Written by: Rich Pizzarro (rhp@netscape.com)
|
|
// November 1997
|
|
|
|
#ifdef NSCPMAPIDLL // Is this part of the DLL or Communicator?
|
|
#include <windows.h>
|
|
#include <trace.h>
|
|
#else
|
|
#include "stdafx.h"
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "wfemsg.h" // for WFE_MSGGetMaster()
|
|
#include "msgmapi.h" // For enumerating messages...
|
|
#include "nsstrseq.h"
|
|
#include "mapihook.h"
|
|
#include "nscpmapi.h"
|
|
#include "mapismem.h"
|
|
#include "mapimail.h"
|
|
#include "hiddenfr.h"
|
|
#include "msgcom.h"
|
|
|
|
#define DELIMIT "-{|}-" // DON'T I18N THIS!
|
|
|
|
//
|
|
// Static defines for the MAPI support...
|
|
//
|
|
static CMAPIConnection *mapiConnections[MAX_CON] = {NULL, NULL, NULL, NULL};
|
|
|
|
//
|
|
// Forward declarations...
|
|
//
|
|
LONG ProcessMAPILogon(MAPILogonType *logonInfo);
|
|
LONG ProcessMAPILogoff(MAPILogoffType *logoffInfo);
|
|
LONG ProcessMAPISendMail(MAPISendMailType *sendMailPtr);
|
|
LONG ProcessMAPISaveMail(MAPISendMailType *sendMailPtr);
|
|
LONG ProcessMAPISendDocuments(MAPISendDocumentsType *sendDocPtr);
|
|
LONG ProcessMAPIFindNext(MAPIFindNextType *findInfo);
|
|
LONG ProcessMAPIDeleteMail(MAPIDeleteMailType *delInfo);
|
|
LONG ProcessMAPIResolveName(MAPIResolveNameType *nameInfo);
|
|
LONG ProcessMAPIDetails(MAPIDetailsType *detailInfo);
|
|
LONG ProcessMAPIReadMail(MAPIReadMailType *readInfo);
|
|
LONG ProcessMAPIAddress(MAPIAddressType *addrInfo);
|
|
|
|
//
|
|
// This will store the CFrameWnd we startup for MAPI and if we do start
|
|
// an instance of the browser, we will close it out when we leave.
|
|
//
|
|
static CFrameWnd *pMAPIFrameWnd = NULL;
|
|
|
|
void
|
|
StoreMAPIFrameWnd(CFrameWnd *pFrameWnd)
|
|
{
|
|
pMAPIFrameWnd = pFrameWnd;
|
|
}
|
|
|
|
// This is the result of a WM_COPYDATA message. This will be used to send requests
|
|
// into Communicator for Simple MAPI commands.
|
|
//
|
|
// The description of the parameters coming into this call are:
|
|
//
|
|
// wParam = (WPARAM) (HWND) hwnd; // handle of sending window
|
|
// lParam = (LPARAM) (PCOPYDATASTRUCT) pcds; // pointer to structure with data
|
|
// context= needed for the context we will use in Communicator
|
|
//
|
|
// typedef struct tagCOPYDATASTRUCT { // cds
|
|
// DWORD dwData; // the ID of the request
|
|
// DWORD cbData; // the size of the argument
|
|
// PVOID lpData; // Chunk of information defined specifically for each of the
|
|
// // Simple MAPI Calls.
|
|
// } COPYDATASTRUCT;
|
|
//
|
|
// Returns: The MAPI Return code for the operation:
|
|
//
|
|
//
|
|
LONG ProcessNetscapeMAPIHook(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
PCOPYDATASTRUCT pcds = (PCOPYDATASTRUCT) lParam;
|
|
MAPIIPCType *ipcInfo;
|
|
#ifdef WIN32
|
|
HANDLE hSharedMemory;
|
|
#endif
|
|
|
|
if (lParam == NULL)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
//
|
|
// Get shared memory info structure pointer...
|
|
//
|
|
ipcInfo = (MAPIIPCType *)pcds->lpData;
|
|
if (ipcInfo == NULL)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
//
|
|
// Now connect to shared memory...or just set the
|
|
// pointer for Win16
|
|
//
|
|
#ifdef WIN32
|
|
CSharedMem *sMem = NSOpenExistingSharedMemory((LPCTSTR) ipcInfo->smemName, &hSharedMemory);
|
|
if (!sMem)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
#else
|
|
if (!ipcInfo->lpsmem)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
#endif
|
|
|
|
TRACE("MAPI: MAPIHook Message ID = %d\n", pcds->dwData);
|
|
switch (pcds->dwData)
|
|
{
|
|
//////////////////////////////////////////////////////////////////////
|
|
// MAPILogon
|
|
//////////////////////////////////////////////////////////////////////
|
|
case NSCP_MAPILogon:
|
|
{
|
|
MAPILogonType *logonInfo;
|
|
#ifdef WIN32
|
|
logonInfo = (MAPILogonType *) &(sMem->m_buf[0]);
|
|
#else
|
|
logonInfo = (MAPILogonType *) ipcInfo->lpsmem;
|
|
#endif
|
|
|
|
if (!logonInfo)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
logonInfo->ipcWorked = 1; // Set the worked flag
|
|
return(ProcessMAPILogon(logonInfo));
|
|
break;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// MAPILogoff
|
|
//////////////////////////////////////////////////////////////////////
|
|
case NSCP_MAPILogoff:
|
|
{
|
|
MAPILogoffType *logoffInfo;
|
|
|
|
#ifdef WIN32
|
|
logoffInfo = (MAPILogoffType *) &(sMem->m_buf[0]);
|
|
#else
|
|
logoffInfo = (MAPILogoffType *) ipcInfo->lpsmem;
|
|
#endif
|
|
|
|
if (!logoffInfo)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
logoffInfo->ipcWorked = 1; // Set the worked flag
|
|
return(ProcessMAPILogoff(logoffInfo));
|
|
break;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// NSCP_MAPISendMail
|
|
//////////////////////////////////////////////////////////////////////
|
|
case NSCP_MAPISendMail:
|
|
{
|
|
MAPISendMailType *sendMailPtr;
|
|
#ifdef WIN32
|
|
sendMailPtr = (MAPISendMailType *) &(sMem->m_buf[0]);
|
|
#else
|
|
sendMailPtr = (MAPISendMailType *) ipcInfo->lpsmem;
|
|
#endif
|
|
|
|
if (!sendMailPtr)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
sendMailPtr->ipcWorked = 1; // Set the worked flag
|
|
return(ProcessMAPISendMail(sendMailPtr));
|
|
break;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// MAPISendDocuments
|
|
//////////////////////////////////////////////////////////////////////
|
|
case NSCP_MAPISendDocuments:
|
|
{
|
|
MAPISendDocumentsType *sendDocPtr;
|
|
#ifdef WIN32
|
|
sendDocPtr = (MAPISendDocumentsType *) &(sMem->m_buf[0]);
|
|
#else
|
|
sendDocPtr = (MAPISendDocumentsType *) ipcInfo->lpsmem;
|
|
#endif
|
|
|
|
if (!sendDocPtr)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
sendDocPtr->ipcWorked = 1; // Set the worked flag
|
|
return(ProcessMAPISendDocuments(sendDocPtr));
|
|
break;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// MAPIFindNext
|
|
//////////////////////////////////////////////////////////////////////
|
|
case NSCP_MAPIFindNext:
|
|
{
|
|
MAPIFindNextType *findInfo;
|
|
|
|
#ifdef WIN32
|
|
findInfo = (MAPIFindNextType *) &(sMem->m_buf[0]);
|
|
#else
|
|
findInfo = (MAPIFindNextType *) ipcInfo->lpsmem;
|
|
#endif
|
|
|
|
if (!findInfo)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
findInfo->ipcWorked = 1; // Set the worked flag
|
|
return(ProcessMAPIFindNext(findInfo));
|
|
break;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// MAPIDeleteMail
|
|
//////////////////////////////////////////////////////////////////////
|
|
case NSCP_MAPIDeleteMail:
|
|
{
|
|
MAPIDeleteMailType *delInfo;
|
|
|
|
#ifdef WIN32
|
|
delInfo = (MAPIDeleteMailType *) &(sMem->m_buf[0]);
|
|
#else
|
|
delInfo = (MAPIDeleteMailType *) ipcInfo->lpsmem;
|
|
#endif
|
|
|
|
if (!delInfo)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
delInfo->ipcWorked = 1; // Set the worked flag
|
|
return(ProcessMAPIDeleteMail(delInfo));
|
|
break;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// MAPIResolveName
|
|
//////////////////////////////////////////////////////////////////////
|
|
case NSCP_MAPIResolveName:
|
|
{
|
|
MAPIResolveNameType *nameInfo;
|
|
|
|
#ifdef WIN32
|
|
nameInfo = (MAPIResolveNameType *) &(sMem->m_buf[0]);
|
|
#else
|
|
nameInfo = (MAPIResolveNameType *) ipcInfo->lpsmem;
|
|
#endif
|
|
|
|
if (!nameInfo)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
nameInfo->ipcWorked = 1; // Set the worked flag
|
|
return(ProcessMAPIResolveName(nameInfo));
|
|
break;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// MAPIDetails
|
|
//////////////////////////////////////////////////////////////////////
|
|
case NSCP_MAPIDetails:
|
|
{
|
|
MAPIDetailsType *detailInfo;
|
|
|
|
#ifdef WIN32
|
|
detailInfo = (MAPIDetailsType *) &(sMem->m_buf[0]);
|
|
#else
|
|
detailInfo = (MAPIDetailsType *) ipcInfo->lpsmem;
|
|
#endif
|
|
|
|
if (!detailInfo)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
detailInfo->ipcWorked = 1; // Set the worked flag
|
|
return(ProcessMAPIDetails(detailInfo));
|
|
break;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// MAPIReadMail
|
|
//////////////////////////////////////////////////////////////////////
|
|
case NSCP_MAPIReadMail:
|
|
{
|
|
MAPIReadMailType *readInfo;
|
|
|
|
#ifdef WIN32
|
|
readInfo = (MAPIReadMailType *) &(sMem->m_buf[0]);
|
|
#else
|
|
readInfo = (MAPIReadMailType *) ipcInfo->lpsmem;
|
|
#endif
|
|
|
|
if (!readInfo)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
readInfo->ipcWorked = 1; // Set the worked flag
|
|
return(ProcessMAPIReadMail(readInfo));
|
|
break;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// NSCP_MAPISaveMail
|
|
//////////////////////////////////////////////////////////////////////
|
|
case NSCP_MAPISaveMail:
|
|
{
|
|
MAPISendMailType *sendMailPtr;
|
|
#ifdef WIN32
|
|
sendMailPtr = (MAPISendMailType *) &(sMem->m_buf[0]);
|
|
#else
|
|
sendMailPtr = (MAPISendMailType *) ipcInfo->lpsmem;
|
|
#endif
|
|
|
|
if (!sendMailPtr)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
sendMailPtr->ipcWorked = 1; // Set the worked flag
|
|
return(ProcessMAPISaveMail(sendMailPtr));
|
|
break;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// MAPIAddress
|
|
//////////////////////////////////////////////////////////////////////
|
|
case NSCP_MAPIAddress:
|
|
{
|
|
MAPIAddressType *addrInfo;
|
|
|
|
#ifdef WIN32
|
|
addrInfo = (MAPIAddressType *) &(sMem->m_buf[0]);
|
|
#else
|
|
addrInfo = (MAPIAddressType *) ipcInfo->lpsmem;
|
|
#endif
|
|
|
|
if (!addrInfo)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
addrInfo->ipcWorked = 1; // Set the worked flag
|
|
return(ProcessMAPIAddress(addrInfo));
|
|
}
|
|
|
|
case NSCP_MAPIFree: // This should never hit Communicator, but if it does
|
|
#ifdef WIN16
|
|
return(SUCCESS_SUCCESS); // Just return
|
|
#else
|
|
return(S_OK); // Just return
|
|
#endif
|
|
|
|
default:
|
|
return(MAPI_E_NOT_SUPPORTED); // Should never hit here!
|
|
break;
|
|
}
|
|
|
|
return(SUCCESS_SUCCESS);
|
|
}
|
|
|
|
//
|
|
// Find the default session for Communicator...
|
|
//
|
|
CMAPIConnection
|
|
*GetDefaultSession(void)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i < MAX_CON; i++)
|
|
{
|
|
if (mapiConnections[i] != NULL)
|
|
{
|
|
if (mapiConnections[i]->IsDefault())
|
|
{
|
|
return mapiConnections[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
//
|
|
// Find an open session slot...
|
|
//
|
|
LONG
|
|
GetOpenSessionSlot( void )
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i < MAX_CON; i++)
|
|
{
|
|
if (mapiConnections[i] == NULL)
|
|
{
|
|
return(i);
|
|
}
|
|
}
|
|
|
|
return(-1);
|
|
}
|
|
|
|
//
|
|
// Returns TRUE if it was reassigned and FALSE if not.
|
|
//
|
|
BOOL
|
|
TryDefaultReassignment(void)
|
|
{
|
|
int i;
|
|
int loc = -1;
|
|
|
|
// Find any sessions left?
|
|
for (i=0; i < MAX_CON; i++)
|
|
{
|
|
if (mapiConnections[i] != NULL)
|
|
{
|
|
loc = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Set default state on the object to true
|
|
if (loc >= 0)
|
|
{
|
|
mapiConnections[loc]->SetDefault(TRUE);
|
|
return(TRUE);
|
|
}
|
|
else
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
LONG
|
|
ProcessMAPILogon(MAPILogonType *logonInfo)
|
|
{
|
|
CMAPIConnection *defSession = GetDefaultSession();
|
|
NSstringSeq strSeq = (LPSTR) logonInfo + sizeof(MAPILogonType);
|
|
LPSTR lpszProfileName = NSStrSeqGet(strSeq, 0);
|
|
LPSTR lpszPassword = NSStrSeqGet(strSeq, 1);
|
|
|
|
TRACE("MAPI: ProcessMAPILogon() ProfileName = [%s] Password = [%s]\n",
|
|
lpszProfileName, lpszPassword);
|
|
//
|
|
// This is a query if lpszProfileName is NULL, lpszPassword is NULL and
|
|
// the MAPI_LOGON_UI is not set
|
|
//
|
|
if ((lpszProfileName[0] == '\0') && (lpszPassword[0] == '\0') &&
|
|
(!(logonInfo->flFlags & MAPI_LOGON_UI)) )
|
|
{
|
|
if (defSession == NULL)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
else
|
|
{
|
|
defSession->IncrementSessionCount();
|
|
logonInfo->lhSession = defSession->GetID();
|
|
return(SUCCESS_SUCCESS);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Only allow for sessions by a single profile name...
|
|
//
|
|
if ( ( defSession != NULL ) &&
|
|
(
|
|
(lstrcmp(lpszProfileName, defSession->GetProfileName() ) != 0) ||
|
|
(lstrcmp(lpszPassword, defSession->GetPassword() ) != 0)
|
|
)
|
|
)
|
|
{
|
|
return(MAPI_E_TOO_MANY_SESSIONS);
|
|
}
|
|
|
|
//
|
|
// Now create the new MAPI session if we have to...
|
|
//
|
|
BOOL createNew = FALSE;
|
|
if (
|
|
( defSession == NULL ) ||
|
|
// Indicates an attempt should be made to create a new session rather than acquire
|
|
// the environment's shared session. If the MAPI_NEW_SESSION flag is not set, MAPILogon
|
|
// uses an existing shared session.
|
|
(logonInfo->flFlags & MAPI_NEW_SESSION) ||
|
|
(defSession == NULL) // No default session exists!
|
|
)
|
|
{
|
|
createNew = TRUE;
|
|
}
|
|
|
|
//
|
|
// Make sure only 4 max are allowed...
|
|
//
|
|
LONG slot;
|
|
if ((createNew) && ((slot = GetOpenSessionSlot()) == -1))
|
|
{
|
|
return(MAPI_E_TOO_MANY_SESSIONS);
|
|
}
|
|
|
|
//
|
|
// If we don't have to create a new session, just return the ID and
|
|
// move on with life
|
|
//
|
|
if (!createNew)
|
|
{
|
|
if (defSession == NULL)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
defSession->IncrementSessionCount();
|
|
logonInfo->lhSession = defSession->GetID();
|
|
return(SUCCESS_SUCCESS);
|
|
}
|
|
|
|
//
|
|
// Finally, create a new session!
|
|
//
|
|
mapiConnections[slot] = new CMAPIConnection(slot, lpszProfileName, lpszPassword);
|
|
if (defSession == NULL)
|
|
{
|
|
mapiConnections[slot]->SetDefault(TRUE);
|
|
}
|
|
|
|
logonInfo->lhSession = mapiConnections[slot]->GetID();
|
|
|
|
//
|
|
// Process Flags...
|
|
//
|
|
// Indicates an attempt should be made to download all of the user's messages before
|
|
// returning. If the MAPI_FORCE_DOWNLOAD flag is not set, messages can be downloaded
|
|
// in the background after the function call returns.
|
|
if (logonInfo->flFlags & MAPI_FORCE_DOWNLOAD)
|
|
{
|
|
MAPIGetNewMessagesInBackground();
|
|
}
|
|
|
|
// Indicates that a logon dialog box should be displayed to prompt the user for
|
|
// logon information. If the user needs to provide a password and profile name
|
|
// to enable a successful logon, MAPI_LOGON_UI must be set.
|
|
if (logonInfo->flFlags & MAPI_LOGON_UI)
|
|
{
|
|
TRACE("MAPI: ProcessMAPILogon() MAPI_LOGON_UI Unsupported.\n");
|
|
}
|
|
|
|
#ifdef WIN32
|
|
// Indicates that MAPILogon should only prompt for a password and not allow the user
|
|
// to change the profile name. Either MAPI_PASSWORD_UI or MAPI_LOGON_UI should not be
|
|
// set, since the intent is to select between two different dialog boxes for logon.
|
|
if (logonInfo->flFlags & MAPI_PASSWORD_UI)
|
|
{
|
|
TRACE("MAPI: ProcessMAPILogon() MAPI_PASSWORD_UI Unsupported.\n");
|
|
}
|
|
#endif
|
|
|
|
return(SUCCESS_SUCCESS);
|
|
}
|
|
|
|
LONG
|
|
ProcessMAPILogoff(MAPILogoffType *logoffInfo)
|
|
{
|
|
TRACE("MAPI: ProcessMAPILogoff() Session ID = [%d]\n", logoffInfo->lhSession);
|
|
//
|
|
// Verify the session handle...
|
|
//
|
|
if (( (logoffInfo->lhSession-1) >= MAX_CON) || ( (logoffInfo->lhSession-1) < 0))
|
|
{
|
|
return(MAPI_E_INVALID_SESSION);
|
|
}
|
|
|
|
CMAPIConnection *logoffSession = mapiConnections[(logoffInfo->lhSession - 1)];
|
|
if (logoffSession == NULL)
|
|
{
|
|
return(MAPI_E_INVALID_SESSION);
|
|
}
|
|
|
|
//
|
|
// Decrement the session count, then if this is the last one
|
|
// connected to this session, then kill it...
|
|
//
|
|
logoffSession->DecrementSessionCount();
|
|
if (logoffSession->GetSessionCount() <= 0)
|
|
{
|
|
//
|
|
// If this was the default session "holder", then we need to
|
|
// assign that task to a new one if it exists, if not, then
|
|
// it is all back to null.
|
|
//
|
|
BOOL needToReassign = logoffSession->IsDefault();
|
|
|
|
delete logoffSession;
|
|
mapiConnections[logoffInfo->lhSession - 1] = NULL;
|
|
|
|
if (needToReassign)
|
|
{
|
|
TRACE("MAPI: ProcessMAPILogoff() Need to reassign default\n");
|
|
if (!TryDefaultReassignment())
|
|
{
|
|
if (pMAPIFrameWnd != NULL)
|
|
{
|
|
pMAPIFrameWnd->PostMessage(WM_CLOSE);
|
|
pMAPIFrameWnd = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return(SUCCESS_SUCCESS);
|
|
}
|
|
|
|
//
|
|
// Actually process the send mail operation...
|
|
//
|
|
LONG
|
|
ProcessMAPISendMail(MAPISendMailType *sendMailPtr)
|
|
{
|
|
CMAPIConnection *mySession;
|
|
NSstringSeq mailInfoSeq;
|
|
|
|
TRACE("MAPI: ProcessMAPISendMail() Session ID = [%d]\n", sendMailPtr->lhSession);
|
|
//
|
|
// Verify the session handle...
|
|
//
|
|
if (((sendMailPtr->lhSession-1) >= MAX_CON) || ((sendMailPtr->lhSession-1) < 0))
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
mySession = mapiConnections[(sendMailPtr->lhSession - 1)];
|
|
if (mySession == NULL)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
//
|
|
// Before we start, make sure things make sense...
|
|
//
|
|
if ( (!(sendMailPtr->flFlags & MAPI_DIALOG)) && (sendMailPtr->MSG_nRecipCount == 0) )
|
|
{
|
|
return(MAPI_E_UNKNOWN_RECIPIENT);
|
|
}
|
|
|
|
mailInfoSeq = (NSstringSeq) &(sendMailPtr->dataBuf[0]);
|
|
TRACE("MAPI: ProcessMAPISendMail() Session ID = [%d]\n", sendMailPtr->lhSession);
|
|
|
|
//
|
|
// Now set the show window flag...
|
|
//
|
|
BOOL showWindow = (( sendMailPtr->flFlags & MAPI_DIALOG ) != 0);
|
|
LONG rc = DoFullMAPIMailOperation(sendMailPtr,
|
|
NSStrSeqGet(mailInfoSeq, 1),
|
|
showWindow);
|
|
return(rc);
|
|
}
|
|
|
|
//
|
|
// Actually process the send mail operation...
|
|
//
|
|
LONG
|
|
ProcessMAPISaveMail(MAPISendMailType *sendMailPtr)
|
|
{
|
|
CMAPIConnection *mySession;
|
|
NSstringSeq mailInfoSeq;
|
|
|
|
TRACE("MAPI: ProcessMAPISaveMail() Session ID = [%d]\n", sendMailPtr->lhSession);
|
|
//
|
|
// Verify the session handle...
|
|
//
|
|
if (((sendMailPtr->lhSession-1) >= MAX_CON) || ((sendMailPtr->lhSession-1) < 0))
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
mySession = mapiConnections[(sendMailPtr->lhSession - 1)];
|
|
if (mySession == NULL)
|
|
{
|
|
return(MAPI_E_FAILURE);
|
|
}
|
|
|
|
mailInfoSeq = (NSstringSeq) &(sendMailPtr->dataBuf[0]);
|
|
TRACE("MAPI: ProcessMAPISaveMail() Session ID = [%d]\n", sendMailPtr->lhSession);
|
|
|
|
//
|
|
// Now process the save mail operation...
|
|
//
|
|
LONG rc = DoMAPISaveMailOperation(sendMailPtr,
|
|
NSStrSeqGet(mailInfoSeq, 1));
|
|
return(rc);
|
|
}
|
|
|
|
//
|
|
// Actually process the send documents operation...
|
|
//
|
|
LONG
|
|
ProcessMAPISendDocuments(MAPISendDocumentsType *sendDocPtr)
|
|
{
|
|
LONG rc = DoPartialMAPIMailOperation(sendDocPtr);
|
|
return(rc);
|
|
}
|
|
|
|
//
|
|
// This is an ENUM procedure for messages that are in the system
|
|
//
|
|
LONG
|
|
ProcessMAPIFindNext(MAPIFindNextType *findInfo)
|
|
{
|
|
CMAPIConnection *mySession;
|
|
|
|
//
|
|
// Verify the session handle...
|
|
//
|
|
if (((findInfo->lhSession-1) >= MAX_CON) || ((findInfo->lhSession-1) < 0))
|
|
{
|
|
return(MAPI_E_INVALID_SESSION);
|
|
}
|
|
|
|
mySession = mapiConnections[(findInfo->lhSession - 1)];
|
|
if (mySession == NULL)
|
|
{
|
|
return(MAPI_E_INVALID_SESSION);
|
|
}
|
|
|
|
//
|
|
// If this is true, then this is the first call to this FindNext function
|
|
// and we should start the enumeration operation.
|
|
//
|
|
MSG_FolderInfo *inboxFolder = NULL;
|
|
int32 folderRC = MSG_GetFoldersWithFlag(WFE_MSGGetMaster(),
|
|
MSG_FOLDER_FLAG_INBOX, &inboxFolder, 1);
|
|
if (folderRC <= 0)
|
|
{
|
|
return(MAPI_E_NO_MESSAGES);
|
|
}
|
|
|
|
// This is the first message
|
|
if (mySession->GetMessageIndex() < 0)
|
|
{
|
|
MSG_MapiListContext *cookie;
|
|
|
|
MessageKey keyFound = MSG_GetFirstKeyInFolder(inboxFolder, &cookie);
|
|
if (keyFound == MSG_MESSAGEKEYNONE)
|
|
{
|
|
mySession->SetMapiListContext(NULL);
|
|
mySession->SetMessageIndex(-1); // Reset to -1...
|
|
return(MAPI_E_NO_MESSAGES);
|
|
}
|
|
|
|
TRACE("MAPI: ProcessMAPIFindNext() Found message id = %d\n", keyFound);
|
|
|
|
wsprintf((LPSTR) findInfo->lpszMessageID, "%d", keyFound);
|
|
mySession->SetMapiListContext(cookie);
|
|
mySession->SetMessageIndex(keyFound); // Just set to 1 and then increment from there...
|
|
}
|
|
else
|
|
{
|
|
MSG_MapiListContext *cookie = (MSG_MapiListContext *)mySession->GetMapiListContext();
|
|
|
|
// Sanity check the cookie value...
|
|
if (cookie == NULL)
|
|
{
|
|
mySession->SetMapiListContext(NULL);
|
|
mySession->SetMessageIndex(-1); // Reset to -1...
|
|
return(MAPI_E_NO_MESSAGES);
|
|
}
|
|
|
|
MessageKey nextKey = MSG_GetNextKeyInFolder(cookie);
|
|
if (nextKey == MSG_MESSAGEKEYNONE)
|
|
{
|
|
mySession->SetMapiListContext(NULL);
|
|
mySession->SetMessageIndex(-1); // Reset to -1...
|
|
return(MAPI_E_NO_MESSAGES);
|
|
}
|
|
|
|
TRACE("MAPI: ProcessMAPIFindNext() Found message id = %d\n", nextKey);
|
|
|
|
wsprintf((LPSTR) findInfo->lpszMessageID, "%d", nextKey);
|
|
mySession->SetMessageIndex(nextKey); // Set the key to the found one and move on...
|
|
}
|
|
|
|
return(SUCCESS_SUCCESS);
|
|
}
|
|
|
|
//
|
|
// Actually process the delete mail operation!
|
|
//
|
|
LONG
|
|
ProcessMAPIDeleteMail(MAPIDeleteMailType *delInfo)
|
|
{
|
|
CMAPIConnection *mySession;
|
|
|
|
//
|
|
// Verify the session handle...
|
|
//
|
|
if (((delInfo->lhSession-1) >= MAX_CON) || ((delInfo->lhSession-1) < 0))
|
|
{
|
|
return(MAPI_E_INVALID_SESSION);
|
|
}
|
|
|
|
mySession = mapiConnections[(delInfo->lhSession - 1)];
|
|
if (mySession == NULL)
|
|
{
|
|
return(MAPI_E_INVALID_SESSION);
|
|
}
|
|
|
|
BOOL msgValid = TRUE;
|
|
|
|
TRACE("MAPI: RICHIE TODO: ProcessMAPIDeleteMail() TRY TO FIND THE MESSAGE FROM THE IDENTIFIER:\n");
|
|
TRACE("MAPI: RICHIE TODO: ProcessMAPIDeleteMail() [%s]\n", delInfo->lpszMessageID);
|
|
|
|
if (msgValid)
|
|
{
|
|
TRACE("MAPI: RICHIE TODO: ProcessMAPIDeleteMail() DELETE THE MESSAGE!!!\n");
|
|
|
|
return(SUCCESS_SUCCESS);
|
|
}
|
|
else
|
|
{
|
|
return(MAPI_E_INVALID_MESSAGE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Process the name resolution for the address passed in.
|
|
//
|
|
LONG
|
|
ProcessMAPIResolveName(MAPIResolveNameType *nameInfo)
|
|
{
|
|
CMAPIConnection *mySession;
|
|
|
|
//
|
|
// Verify the session handle...
|
|
//
|
|
if (((nameInfo->lhSession-1) >= MAX_CON) || ((nameInfo->lhSession-1) < 0))
|
|
{
|
|
return(MAPI_E_INVALID_SESSION);
|
|
}
|
|
|
|
mySession = mapiConnections[(nameInfo->lhSession - 1)];
|
|
if (mySession == NULL)
|
|
{
|
|
return(MAPI_E_INVALID_SESSION);
|
|
}
|
|
|
|
TRACE("MAPI: ProcessMAPIResolveName() TRY TO IDENTIFY THE ADDRESS INFO FOR THE NAME:\n");
|
|
TRACE("MAPI: ProcessMAPIResolveName() [%s]\n", nameInfo->lpszName);
|
|
|
|
DWORD numFound;
|
|
LPSTR retFullName = NULL;
|
|
LPSTR retAddr = NULL;
|
|
|
|
AB_ContainerInfo *ctr;
|
|
ABID id;
|
|
|
|
numFound = AB_MAPI_ResolveName (
|
|
(char *)nameInfo->lpszName, // i.e. a nickname or part of the person's name to look up. Assumes First Last
|
|
&ctr, // caller allocates the ctr ptr. BE fills Caller must close container when done with it
|
|
&id); // caller allocates the ABID, BE fills
|
|
|
|
if (numFound > 1)
|
|
{
|
|
return(MAPI_E_AMBIGUOUS_RECIPIENT);
|
|
}
|
|
else if (numFound <= 0)
|
|
{
|
|
return(MAPI_E_UNKNOWN_RECIPIENT);
|
|
}
|
|
else // Here we found a single entry!
|
|
{
|
|
// Get the full name and email address...
|
|
retFullName = AB_MAPI_GetFullName(ctr, id);
|
|
retAddr = AB_MAPI_GetEmailAddress(ctr, id);
|
|
|
|
// null out return values just in case...
|
|
nameInfo->lpszABookName[0] = '\0';
|
|
nameInfo->lpszABookAddress[0] = '\0';
|
|
|
|
// if valid, copy the strings over...
|
|
if (retFullName)
|
|
lstrcpy((LPSTR) nameInfo->lpszABookName, retFullName);
|
|
if (retAddr)
|
|
lstrcpy((LPSTR) nameInfo->lpszABookAddress, retAddr);
|
|
|
|
// Now get the string to use for an ID later on...
|
|
LPSTR abookIDString = AB_MAPI_ConvertToDescription(ctr);
|
|
|
|
// build that string ID to pass back through the MAPI API
|
|
wsprintf((LPSTR) nameInfo->lpszABookID, "%d%s", id, DELIMIT);
|
|
lstrcat((LPSTR) nameInfo->lpszABookID, abookIDString);
|
|
|
|
// Be nice and cleanup after ourselves...
|
|
if (retAddr)
|
|
XP_FREE(retAddr);
|
|
if (retFullName)
|
|
XP_FREE(retFullName);
|
|
if (abookIDString)
|
|
XP_FREE(abookIDString);
|
|
|
|
return(SUCCESS_SUCCESS);
|
|
}
|
|
}
|
|
|
|
//
|
|
// This deals with the MAPIDetails call
|
|
//
|
|
LONG
|
|
ProcessMAPIDetails(MAPIDetailsType *detailInfo)
|
|
{
|
|
CMAPIConnection *mySession;
|
|
|
|
//
|
|
// Verify the session handle...
|
|
//
|
|
if (((detailInfo->lhSession-1) >= MAX_CON) || ((detailInfo->lhSession-1) < 0))
|
|
{
|
|
return(MAPI_E_INVALID_SESSION);
|
|
}
|
|
|
|
mySession = mapiConnections[(detailInfo->lhSession - 1)];
|
|
if (mySession == NULL)
|
|
{
|
|
return(MAPI_E_INVALID_SESSION);
|
|
}
|
|
|
|
TRACE("MAPI: ProcessMAPIDetails() NEED TO LOCATE THE ENTRY FOR:\n");
|
|
TRACE("MAPI: ProcessMAPIDetails() [%s]\n", detailInfo->lpszABookID);
|
|
|
|
char workString[MAX_NAME_LEN];
|
|
char *idString;
|
|
char *containerString;
|
|
|
|
lstrcpy((LPSTR) workString, (LPSTR) detailInfo->lpszABookID);
|
|
|
|
//
|
|
// Now parse out the first and last names of the person...
|
|
//
|
|
int totLen = lstrlen((LPSTR) workString);
|
|
int loc = 0;
|
|
idString = &(workString[0]);
|
|
|
|
while ( ( lstrlen((LPSTR) DELIMIT) + loc) < totLen)
|
|
{
|
|
if (strncmp((LPSTR)(workString + loc), DELIMIT, lstrlen(DELIMIT)) == 0)
|
|
{
|
|
workString[loc] = '\0';
|
|
containerString = &(workString[loc + lstrlen(DELIMIT)]);
|
|
break;
|
|
}
|
|
|
|
++loc;
|
|
}
|
|
|
|
if ( (lstrlen((LPSTR) DELIMIT) + loc) >= totLen )
|
|
{
|
|
return(MAPI_E_INVALID_RECIPS);
|
|
}
|
|
|
|
// Now, convert the stuff to real values for the API...
|
|
ABID id = atoi((const char *) idString);
|
|
AB_ContainerInfo *container = AB_MAPI_ConvertToContainer(containerString);
|
|
MSG_Pane *personPane = NULL;
|
|
extern MWContext *GetUsableContext(void);
|
|
|
|
// Need to first create a person entry pane and then call
|
|
// FE_ShowPropertySheetAB2 on that pane - return 0 is problem
|
|
int rc = AB_MAPI_CreatePropertySheetPane(
|
|
GetUsableContext(),
|
|
WFE_MSGGetMaster(),
|
|
container,
|
|
id,
|
|
&personPane); // BE will allocate a personPane and return a ptr to it here
|
|
if (!rc)
|
|
{
|
|
return(MAPI_E_INVALID_RECIPS);
|
|
}
|
|
|
|
// Now display the address book entry for this user. If the parameter
|
|
// detailInfo->ulUIParam is NULL, just doit and return, but if it is
|
|
// not NULL, then we should do it as application modal.
|
|
|
|
// RICHIE - THIS IS NOT IN THE BUILD YET! MUST WAIT
|
|
//(void) FE_ShowPropertySheetForAB2(personPane, AB_Person);
|
|
|
|
// cleanup the container and person pane...
|
|
AB_MAPI_CloseContainer(&container);
|
|
AB_ClosePane(personPane);
|
|
|
|
return(SUCCESS_SUCCESS);
|
|
}
|
|
|
|
//
|
|
// CMAPIConnections object...should be in their own file...
|
|
//
|
|
CMAPIConnection::CMAPIConnection ( LONG id, LPSTR name, LPSTR pw)
|
|
{
|
|
m_sessionCount = 1;
|
|
m_defaultConnection = FALSE;
|
|
m_ID = (id + 1); // since zero is invalid, but have to make sure we
|
|
// decrement by one when it is passed in again.
|
|
m_messageIndex = -1; // For tracing our way through the FindNext operation
|
|
m_cookie = NULL; // For doing the enumeration of messages
|
|
m_messageFindInfo[0] = '\0';
|
|
lstrcpy((LPSTR) m_profileName, name);
|
|
lstrcpy((LPSTR) m_password, pw);
|
|
}
|
|
|
|
CMAPIConnection::~CMAPIConnection ( )
|
|
{
|
|
}
|
|
|
|
//
|
|
// This is all needed to process a MAPIReadMail operation
|
|
//
|
|
static LPSTR
|
|
CheckNull(LPSTR inStr)
|
|
{
|
|
static UCHAR str[1];
|
|
|
|
str[0] = '\0';
|
|
if (inStr == NULL)
|
|
return((LPSTR)str);
|
|
else
|
|
return(inStr);
|
|
}
|
|
|
|
LONG
|
|
WriteTheMemoryBufferToDisk(LPSTR fName, UINT bufSize, LPSTR buf)
|
|
{
|
|
if (!buf)
|
|
{
|
|
return(-1);
|
|
}
|
|
|
|
HFILE hFile = _lcreat(fName, 0);
|
|
if (hFile == HFILE_ERROR)
|
|
{
|
|
return(-1);
|
|
}
|
|
|
|
UINT writeCount = _lwrite(hFile, buf, bufSize);
|
|
_lclose(hFile);
|
|
|
|
if (writeCount != bufSize)
|
|
{
|
|
_unlink(fName);
|
|
return(-1);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
static LPSTR
|
|
GetTheTempDirectoryOnTheSystem(void)
|
|
{
|
|
static UCHAR retPath[_MAX_PATH];
|
|
|
|
if (getenv("TEMP"))
|
|
{
|
|
lstrcpy((LPSTR) retPath, getenv("TEMP")); // environmental variable
|
|
}
|
|
else if (getenv("TMP"))
|
|
{
|
|
lstrcpy((LPSTR) retPath, getenv("TMP")); // How about this environmental variable?
|
|
}
|
|
else
|
|
{
|
|
GetWindowsDirectory((LPSTR) retPath, sizeof(retPath));
|
|
}
|
|
|
|
return((LPSTR) &(retPath[0]));
|
|
}
|
|
|
|
#ifdef WIN16
|
|
static int ISGetTempFileName(LPCSTR a_pDummyPath, LPCSTR a_pPrefix, UINT a_uUnique, LPSTR a_pResultName)
|
|
{
|
|
#ifdef GetTempFileName // we need the real thing comming up next...
|
|
#undef GetTempFileName
|
|
#endif
|
|
return GetTempFileName(0, a_pPrefix, a_uUnique, a_pResultName);
|
|
}
|
|
#endif
|
|
|
|
static DWORD
|
|
ValidateFile(LPCSTR szFile)
|
|
{
|
|
struct _stat buf;
|
|
int result;
|
|
|
|
result = _stat( szFile, &buf );
|
|
if (result != 0)
|
|
return(1);
|
|
|
|
if (!(buf.st_mode & S_IREAD))
|
|
return(2);
|
|
|
|
return(0);
|
|
}
|
|
|
|
static LONG
|
|
GetTempAttachmentName(LPSTR fName)
|
|
{
|
|
UINT res;
|
|
static UINT uUnique = 1;
|
|
|
|
if (!fName)
|
|
return(-1);
|
|
|
|
LPSTR szTempPath = GetTheTempDirectoryOnTheSystem();
|
|
|
|
TRYAGAIN:
|
|
#ifdef WIN32
|
|
res = GetTempFileName(szTempPath, "MAPI", uUnique++, fName);
|
|
#else
|
|
res = ISGetTempFileName(szTempPath, "MAPI", uUnique++, fName);
|
|
#endif
|
|
|
|
if (ValidateFile(fName) != 1)
|
|
{
|
|
if (uUnique < 32000)
|
|
{
|
|
goto TRYAGAIN;
|
|
}
|
|
else
|
|
{
|
|
return(-1);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
LONG
|
|
ProcessMAPIReadMail(MAPIReadMailType *readInfo)
|
|
{
|
|
CMAPIConnection *mySession;
|
|
lpMapiMessage message; // this is the message we will receive
|
|
|
|
//
|
|
// Verify the session handle...
|
|
//
|
|
if (((readInfo->lhSession-1) >= MAX_CON) || ((readInfo->lhSession-1) < 0))
|
|
{
|
|
return(MAPI_E_INVALID_SESSION);
|
|
}
|
|
|
|
mySession = mapiConnections[(readInfo->lhSession - 1)];
|
|
if (mySession == NULL)
|
|
{
|
|
return(MAPI_E_INVALID_SESSION);
|
|
}
|
|
|
|
// First, gotta get the inbox folder!
|
|
MSG_FolderInfo *inboxFolder = NULL;
|
|
int32 folderRC = MSG_GetFoldersWithFlag(WFE_MSGGetMaster(),
|
|
MSG_FOLDER_FLAG_INBOX, &inboxFolder, 1);
|
|
if (folderRC <= 0)
|
|
{
|
|
return(MAPI_E_INVALID_MESSAGE);
|
|
}
|
|
|
|
// Convert the message id to a number!
|
|
MessageKey lookupKey = atoi((const char *)readInfo->lpszMessageID);
|
|
TRACE("MAPI: ProcessMAPIReadMail() Find this message = [%s] - [%d]\n",
|
|
readInfo->lpszMessageID, lookupKey);
|
|
|
|
// Now see if we can find this message!
|
|
BOOL msgFound = MSG_GetMapiMessageById(inboxFolder, lookupKey, &message);
|
|
|
|
// If we didn't find the message, then we need to bail!
|
|
if (!msgFound)
|
|
{
|
|
TRACE("MAPI: ProcessMAPIReadMail() MESSAGE NOT FOUND\n");
|
|
return(MAPI_E_INVALID_MESSAGE);
|
|
}
|
|
|
|
//
|
|
// Now that we have found the message, we need to populate the chunk of
|
|
// memory that we will write to disk and then move on. For now, we need
|
|
// to setup all of the variables for the information we will need for the
|
|
// message.
|
|
//
|
|
ULONG i;
|
|
DWORD arrayCount = 0; // Counter for array entries!
|
|
DWORD arrayTotal = 0; // Total for array entries!
|
|
FLAGS msgFlags; // unread, return or receipt
|
|
ULONG msgRecipCount = message->nRecipCount; // Number of recipients
|
|
ULONG msgFileAttachCount = message->nFileCount; // # of file attachments
|
|
|
|
LPSTR msgSubject = message->lpszSubject; // Message Subject
|
|
LPSTR msgNoteText = NULL; // Message Text will be
|
|
LPSTR msgDateReceived = message->lpszDateReceived;// in YYYY/MM/DD HH:MM format
|
|
LPSTR msgThreadID = message->lpszConversationID; // conversation thread ID
|
|
|
|
//
|
|
// The following are for the originator of the message. Only ONE of these.
|
|
//
|
|
LPSTR origName = NULL; // Originator name
|
|
LPSTR origAddress = NULL; // Originator address (optional)
|
|
ULONG origRecipClass = MAPI_TO; // Recipient class - MAPI_TO, MAPI_CC, MAPI_BCC, MAPI_ORIG
|
|
|
|
// Now we have to make sure there is an originator and set the vars...
|
|
if (message->lpOriginator)
|
|
{
|
|
origName = message->lpOriginator->lpszName;
|
|
origAddress = message->lpOriginator->lpszAddress;
|
|
}
|
|
|
|
if ( ! (readInfo->flFlags & MAPI_ENVELOPE_ONLY))
|
|
{
|
|
TRACE("MAPI: ProcessMAPIReadMail() GET NOTE TEXT - ONLY IF WE HAVE TO!\n");
|
|
msgNoteText = message->lpszNoteText;
|
|
}
|
|
|
|
// First, figure out how many entries we need to have in a string array...
|
|
arrayTotal = 6 + 1; // 6 for the first 6 strings and 1 for the final NULL
|
|
|
|
// Add the recipient information
|
|
arrayTotal += (msgRecipCount * 3);
|
|
|
|
// Now check to see if we are going to pass back attachments:
|
|
//
|
|
// MAPI_ENVELOPE_ONLY
|
|
// Indicates MAPIReadMail should read the message header only. File attachments are
|
|
// not copied to temporary files, and neither temporary file names nor message text
|
|
// is written. Setting this flag enhances performance.
|
|
//
|
|
// MAPI_SUPPRESS_ATTACH
|
|
// Indicates MAPIReadMail should not copy file attachments but should write message
|
|
// text into the MapiMessage structure. MAPIReadMail ignores this flag if the
|
|
// calling application has set the MAPI_ENVELOPE_ONLY flag. Setting the
|
|
// MAPI_SUPPRESS_ATTACH flag enhances performance.
|
|
//
|
|
if ((readInfo->flFlags & MAPI_SUPPRESS_ATTACH) ||
|
|
(readInfo->flFlags & MAPI_ENVELOPE_ONLY) )
|
|
{
|
|
msgFileAttachCount = 0;
|
|
}
|
|
|
|
arrayTotal += (msgFileAttachCount * 2);
|
|
|
|
// now allocate the memory for the string array
|
|
LPSTR *strArray = (LPSTR *) malloc((size_t) (sizeof(LPSTR) * arrayTotal));
|
|
if (!strArray)
|
|
{
|
|
return(MAPI_E_INSUFFICIENT_MEMORY);
|
|
}
|
|
|
|
// Now assign the easy return values to the shared memory structure
|
|
readInfo->MSG_flFlags = msgFlags; // unread, return or receipt
|
|
readInfo->MSG_nRecipCount = msgRecipCount; // Number of recipients
|
|
readInfo->MSG_nFileCount = msgFileAttachCount; // # of file attachments
|
|
readInfo->MSG_ORIG_ulRecipClass = origRecipClass; // Recipient class - MAPI_TO, MAPI_CC, MAPI_BCC, MAPI_ORIG
|
|
|
|
// Now go through and fill out the array to create the string sequence
|
|
strArray[0] = CheckNull(msgSubject);
|
|
strArray[1] = CheckNull(msgNoteText);
|
|
strArray[2] = CheckNull(msgDateReceived);
|
|
strArray[3] = CheckNull(msgThreadID);
|
|
strArray[4] = CheckNull(origName);
|
|
strArray[5] = CheckNull(origAddress);
|
|
|
|
arrayCount = 6; // counter for the rest of the needed attachments
|
|
|
|
// Now add all of the recipients
|
|
for (i=0; i<msgRecipCount; i++)
|
|
{
|
|
UCHAR tempString[128];
|
|
ULONG messageClass = message->lpRecips[i].ulRecipClass; // Get the recipient class...
|
|
|
|
// Now get the following 3 items:
|
|
// String x: LPSTR lpszName; // Recipient N name
|
|
// String x: LPSTR lpszAddress; // Recipient N address (optional)
|
|
// String x: LPSTR lpszRecipClass // recipient class - sprintf of ULONG
|
|
strArray[arrayCount++] = CheckNull(message->lpRecips[i].lpszName);
|
|
strArray[arrayCount++] = CheckNull(message->lpRecips[i].lpszAddress);
|
|
|
|
// 0 MAPI_ORIG Indicates the original sender of the message.
|
|
// 1 MAPI_TO Indicates a primary message recipient.
|
|
// 2 MAPI_CC Indicates a recipient of a message copy.
|
|
// 3 MAPI_BCC Indicates a recipient of a blind copy.
|
|
wsprintf((LPSTR) tempString, "%d", messageClass);
|
|
strArray[arrayCount++] = CheckNull((LPSTR) tempString);
|
|
}
|
|
|
|
// Now, add all of the attachments to this blob
|
|
for (i=0; i<msgFileAttachCount; i++)
|
|
{
|
|
// String x: LPSTR lpszPathName // Fully qualified path of the attached file.
|
|
// // This path should include the disk drive letter and directory name.
|
|
// String x: LPSTR lpszFileName // The display name for the attached file
|
|
//
|
|
strArray[arrayCount++] = CheckNull(message->lpFiles[i].lpszPathName);
|
|
strArray[arrayCount++] = CheckNull(message->lpFiles[i].lpszFileName);
|
|
}
|
|
|
|
strArray[arrayCount] = NULL;
|
|
|
|
// Create the string sequence
|
|
NSstringSeq strSeq = NSStrSeqNew(strArray);
|
|
|
|
// Now just cleanup the array....
|
|
free(strArray);
|
|
|
|
if (!strSeq)
|
|
{
|
|
return(MAPI_E_INSUFFICIENT_MEMORY);
|
|
}
|
|
|
|
// Now get the name of the file to write the blob to!
|
|
if (GetTempAttachmentName((LPSTR)readInfo->lpszBlob) < 0)
|
|
{
|
|
NSStrSeqDelete(strSeq);
|
|
return(MAPI_E_ATTACHMENT_WRITE_FAILURE);
|
|
}
|
|
|
|
// Now write the blob to disk and move on...
|
|
if (WriteTheMemoryBufferToDisk((LPSTR) readInfo->lpszBlob,
|
|
(UINT) NSStrSeqSize(strSeq), strSeq) != 0)
|
|
{
|
|
NSStrSeqDelete(strSeq);
|
|
return(MAPI_E_ATTACHMENT_WRITE_FAILURE);
|
|
}
|
|
|
|
//
|
|
// MAPI_PEEK
|
|
// Indicates MAPIReadMail does not mark the message as read. Marking a message as
|
|
// read affects its appearance in the user interface and generates a read receipt.
|
|
// If the messaging system does not support this flag, MAPIReadMail always marks
|
|
// the message as read. If MAPIReadMail encounters an error, it leaves the
|
|
// message unread.
|
|
if (!(readInfo->flFlags & MAPI_PEEK))
|
|
{
|
|
MSG_MarkMapiMessageRead (inboxFolder, lookupKey, TRUE);
|
|
}
|
|
|
|
// Now we have to free the message and the chunk of memory...
|
|
MSG_FreeMapiMessage(message);
|
|
NSStrSeqDelete(strSeq);
|
|
|
|
return(SUCCESS_SUCCESS);
|
|
}
|
|
|
|
// necessary variables for
|
|
int arrayCount = 0; // Counter for array entries!
|
|
int addressCount = 0; // Counter for array entries!
|
|
LPSTR *addrArray;
|
|
LPSTR toString = "1";
|
|
LPSTR ccString = "2";
|
|
LPSTR bccString = "3";
|
|
|
|
BOOL
|
|
AddressCallback(int totalCount, int currentIndex,
|
|
int addrType, LPSTR addrString)
|
|
{
|
|
LPSTR messageClass;
|
|
|
|
TRACE("TOTAL COUNT = %d\n", totalCount);
|
|
TRACE("CURRENT COUNT = %d\n", currentIndex);
|
|
TRACE("CURRENT ADDR = %s\n", addrString);
|
|
|
|
// If this is the first entry, then we need to allocate the array...
|
|
if (currentIndex == 0)
|
|
{
|
|
addressCount = totalCount;
|
|
addrArray = (LPSTR *) malloc( (size_t)
|
|
sizeof(LPSTR) * ((addressCount * 3) + 1)
|
|
);
|
|
if (!addrArray)
|
|
{
|
|
addressCount = 0;
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// if the array was not allocated...
|
|
if (!addrArray)
|
|
{
|
|
addressCount = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
// Deal with the address type...
|
|
if (addrType == MSG_CC_HEADER_MASK)
|
|
messageClass = ccString;
|
|
else if (addrType == MSG_BCC_HEADER_MASK)
|
|
messageClass = bccString;
|
|
else
|
|
messageClass = toString;
|
|
|
|
// Now get the following 3 items:
|
|
// String x: LPSTR lpszName; // Recipient N name
|
|
// String x: LPSTR lpszAddress; // Recipient N address (optional)
|
|
// String x: LPSTR lpszRecipClass // recipient class - sprintf of ULONG
|
|
|
|
char *ptr = strchr(addrString, '<');
|
|
if (ptr)
|
|
{
|
|
addrString[strlen(addrString) - 1] = '\0';
|
|
*(ptr-1) = '\0';
|
|
}
|
|
addrArray[arrayCount++] = CheckNull(addrString);
|
|
|
|
if (ptr)
|
|
{
|
|
ptr++;
|
|
}
|
|
else
|
|
{
|
|
ptr = (char *) addrString;
|
|
}
|
|
|
|
addrArray[arrayCount++] = CheckNull(ptr);
|
|
|
|
// 0 MAPI_ORIG Indicates the original sender of the message.
|
|
// 1 MAPI_TO Indicates a primary message recipient.
|
|
// 2 MAPI_CC Indicates a recipient of a message copy.
|
|
// 3 MAPI_BCC Indicates a recipient of a blindcopy.
|
|
addrArray[arrayCount++] = CheckNull(messageClass);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
int getAddressCount = 0;
|
|
MAPIAddressType *getAddressPtr = NULL;
|
|
NSstringSeq addrSeq = NULL;
|
|
|
|
// rhp - for MAPI calls...
|
|
BOOL
|
|
GetNextAddress(LPSTR *name, LPSTR *address, int *addrType)
|
|
{
|
|
if ( getAddressCount >= (getAddressPtr->nRecips * 3) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
ULONG aType = atoi(NSStrSeqGet(addrSeq, getAddressCount++));
|
|
|
|
// return which type of address this is?
|
|
if (aType == MAPI_CC)
|
|
*addrType = MSG_CC_HEADER_MASK;
|
|
else if (aType == MAPI_BCC)
|
|
*addrType = MSG_BCC_HEADER_MASK;
|
|
else
|
|
*addrType = MSG_TO_HEADER_MASK;
|
|
|
|
*name = (LPSTR) NSStrSeqGet(addrSeq, getAddressCount++);
|
|
*address = (LPSTR) NSStrSeqGet(addrSeq, getAddressCount++);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
LONG
|
|
ProcessMAPIAddress(MAPIAddressType *addrInfo)
|
|
{
|
|
CMAPIConnection *mySession;
|
|
|
|
TRACE("MAPI: ProcessMAPIAddress() Incomming Addrs = %d\nCaption = [%s]\n",
|
|
addrInfo->nRecips,
|
|
addrInfo->lpszCaption);
|
|
//
|
|
// Verify the session handle...
|
|
//
|
|
if (((addrInfo->lhSession-1) >= MAX_CON) || ((addrInfo->lhSession-1) < 0))
|
|
{
|
|
return(MAPI_E_INVALID_SESSION);
|
|
}
|
|
|
|
mySession = mapiConnections[(addrInfo->lhSession - 1)];
|
|
if (mySession == NULL)
|
|
{
|
|
return(MAPI_E_INVALID_SESSION);
|
|
}
|
|
|
|
//
|
|
// Put up the address dialog and do the right thing :-)
|
|
//
|
|
addrSeq = (NSstringSeq) &(addrInfo->dataBuf[0]);
|
|
getAddressCount = 0; // Make sure to reset the counter for address info...
|
|
getAddressPtr = addrInfo; // Address pointer for callback...
|
|
arrayCount = 0; // counter for the rest of the entries...
|
|
theApp.m_pHiddenFrame->AddressDialog((LPSTR) (addrInfo->lpszCaption),
|
|
AddressCallback, GetNextAddress);
|
|
|
|
// If the address count is zero, then we can return early...
|
|
addrInfo->nNewRecips = addressCount;
|
|
if (addressCount == 0)
|
|
{
|
|
return(SUCCESS_SUCCESS);
|
|
}
|
|
|
|
addrArray[arrayCount] = NULL;
|
|
|
|
// Create the string sequence
|
|
NSstringSeq strSeq = NSStrSeqNew(addrArray);
|
|
|
|
// Now just cleanup the array....
|
|
free(addrArray);
|
|
|
|
if (!strSeq)
|
|
{
|
|
return(MAPI_E_INSUFFICIENT_MEMORY);
|
|
}
|
|
|
|
// Now get the name of the file to write the blob to!
|
|
if (GetTempAttachmentName((LPSTR)addrInfo->lpszBlob) < 0)
|
|
{
|
|
NSStrSeqDelete(strSeq);
|
|
return(MAPI_E_INSUFFICIENT_MEMORY);
|
|
}
|
|
|
|
// Now write the blob to disk and move on...
|
|
if (WriteTheMemoryBufferToDisk((LPSTR) addrInfo->lpszBlob,
|
|
(UINT) NSStrSeqSize(strSeq), strSeq) != 0)
|
|
{
|
|
NSStrSeqDelete(strSeq);
|
|
return(MAPI_E_INSUFFICIENT_MEMORY);
|
|
}
|
|
|
|
NSStrSeqDelete(strSeq);
|
|
return(SUCCESS_SUCCESS);
|
|
}
|