home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / mapihook.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  42.7 KB  |  1,565 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. //
  19. //  MAPI Hooks for Communicator
  20. //  Note: THIS LIVES IN COMMUNICATOR THOUGH IT IS IN THE MAPIDLL FOR
  21. //        BUILD REASONS
  22. //  Written by: Rich Pizzarro (rhp@netscape.com)
  23. //  November 1997
  24.  
  25. #ifdef NSCPMAPIDLL    // Is this part of the DLL or Communicator?
  26. #include <windows.h>
  27. #include <trace.h>
  28. #else
  29. #include "stdafx.h"
  30. #endif
  31.  
  32. #include <stdio.h>    
  33. #include <string.h>
  34. #include <stdlib.h>
  35. #include <sys/stat.h>
  36.  
  37. #include "wfemsg.h"     // for WFE_MSGGetMaster()
  38. #include "msgmapi.h"    // For enumerating messages...
  39. #include "nsstrseq.h"
  40. #include "mapihook.h"
  41. #include "nscpmapi.h"
  42. #include "mapismem.h"
  43. #include "mapimail.h"
  44. #include "hiddenfr.h"
  45. #include "msgcom.h"
  46.  
  47. #define   DELIMIT         "-{|}-"    // DON'T I18N THIS!
  48.  
  49. //
  50. // Static defines for the MAPI support...
  51. //
  52. static CMAPIConnection *mapiConnections[MAX_CON] = {NULL, NULL, NULL, NULL};
  53.  
  54. //
  55. // Forward declarations...
  56. //
  57. LONG    ProcessMAPILogon(MAPILogonType *logonInfo);
  58. LONG    ProcessMAPILogoff(MAPILogoffType *logoffInfo);
  59. LONG    ProcessMAPISendMail(MAPISendMailType *sendMailPtr);
  60. LONG    ProcessMAPISaveMail(MAPISendMailType *sendMailPtr);
  61. LONG    ProcessMAPISendDocuments(MAPISendDocumentsType *sendDocPtr);
  62. LONG    ProcessMAPIFindNext(MAPIFindNextType *findInfo);
  63. LONG    ProcessMAPIDeleteMail(MAPIDeleteMailType *delInfo);
  64. LONG    ProcessMAPIResolveName(MAPIResolveNameType *nameInfo);
  65. LONG    ProcessMAPIDetails(MAPIDetailsType *detailInfo);
  66. LONG    ProcessMAPIReadMail(MAPIReadMailType *readInfo);
  67. LONG    ProcessMAPIAddress(MAPIAddressType *addrInfo);
  68.  
  69. //
  70. // This will store the CFrameWnd we startup for MAPI and if we do start
  71. // an instance of the browser, we will close it out when we leave.
  72. //
  73. static CFrameWnd  *pMAPIFrameWnd = NULL;
  74.  
  75. void 
  76. StoreMAPIFrameWnd(CFrameWnd *pFrameWnd)
  77. {
  78.   pMAPIFrameWnd = pFrameWnd;
  79. }
  80.  
  81. // This is the result of a WM_COPYDATA message. This will be used to send requests
  82. // into Communicator for Simple MAPI commands.
  83. //
  84. // The description of the parameters coming into this call are:
  85. //
  86. //    wParam = (WPARAM) (HWND) hwnd;            // handle of sending window 
  87. //    lParam = (LPARAM) (PCOPYDATASTRUCT) pcds; // pointer to structure with data 
  88. //    context= needed for the context we will use in Communicator
  89. //
  90. //        typedef struct tagCOPYDATASTRUCT {  // cds  
  91. //            DWORD dwData;            // the ID of the request
  92. //            DWORD cbData;            // the size of the argument
  93. //            PVOID lpData;            // Chunk of information defined specifically for each of the
  94. //                        // Simple MAPI Calls.
  95. //        } COPYDATASTRUCT; 
  96. //
  97. // Returns: The MAPI Return code for the operation:
  98. //
  99. //
  100. LONG ProcessNetscapeMAPIHook(WPARAM wParam, LPARAM lParam)
  101. {
  102.   PCOPYDATASTRUCT      pcds = (PCOPYDATASTRUCT) lParam;
  103.   MAPIIPCType       *ipcInfo; 
  104. #ifdef WIN32   
  105.   HANDLE            hSharedMemory;
  106. #endif
  107.  
  108.     if (lParam == NULL)
  109.     {
  110.         return(MAPI_E_FAILURE);
  111.     }
  112.  
  113.   //
  114.   // Get shared memory info structure pointer...
  115.   //
  116.   ipcInfo = (MAPIIPCType *)pcds->lpData;
  117.   if (ipcInfo == NULL)
  118.     {
  119.         return(MAPI_E_FAILURE);
  120.     }
  121.  
  122.   //
  123.   // Now connect to shared memory...or just set the
  124.   // pointer for Win16
  125.   //
  126. #ifdef WIN32
  127.   CSharedMem *sMem = NSOpenExistingSharedMemory((LPCTSTR) ipcInfo->smemName, &hSharedMemory);
  128.   if (!sMem)
  129.     {
  130.         return(MAPI_E_FAILURE);
  131.     }
  132. #else
  133.   if (!ipcInfo->lpsmem)
  134.   {
  135.     return(MAPI_E_FAILURE);
  136.   }
  137. #endif
  138.  
  139.   TRACE("MAPI: MAPIHook Message ID = %d\n", pcds->dwData);
  140.     switch (pcds->dwData) 
  141.     {
  142.   //////////////////////////////////////////////////////////////////////
  143.   // MAPILogon
  144.   //////////////////////////////////////////////////////////////////////
  145.   case NSCP_MAPILogon:
  146.     {
  147.      MAPILogonType     *logonInfo;
  148. #ifdef WIN32
  149.     logonInfo = (MAPILogonType *) &(sMem->m_buf[0]);
  150. #else    
  151.     logonInfo = (MAPILogonType *) ipcInfo->lpsmem;
  152. #endif
  153.  
  154.     if (!logonInfo)
  155.     {
  156.       return(MAPI_E_FAILURE);
  157.     }
  158.   
  159.     logonInfo->ipcWorked = 1;         // Set the worked flag
  160.     return(ProcessMAPILogon(logonInfo));
  161.     break;
  162.     }
  163.  
  164.   //////////////////////////////////////////////////////////////////////
  165.   // MAPILogoff
  166.   //////////////////////////////////////////////////////////////////////
  167.   case NSCP_MAPILogoff:
  168.     {
  169.     MAPILogoffType     *logoffInfo;
  170.  
  171. #ifdef WIN32
  172.     logoffInfo = (MAPILogoffType *) &(sMem->m_buf[0]);
  173. #else    
  174.     logoffInfo = (MAPILogoffType *) ipcInfo->lpsmem;
  175. #endif
  176.  
  177.     if (!logoffInfo)
  178.     {
  179.       return(MAPI_E_FAILURE);
  180.     }
  181.  
  182.     logoffInfo->ipcWorked = 1;         // Set the worked flag
  183.     return(ProcessMAPILogoff(logoffInfo));
  184.     break;
  185.     }
  186.  
  187.   //////////////////////////////////////////////////////////////////////
  188.   // NSCP_MAPISendMail
  189.   //////////////////////////////////////////////////////////////////////
  190.   case NSCP_MAPISendMail:
  191.      {
  192.      MAPISendMailType     *sendMailPtr;
  193. #ifdef WIN32
  194.     sendMailPtr = (MAPISendMailType *) &(sMem->m_buf[0]);
  195. #else    
  196.     sendMailPtr = (MAPISendMailType *) ipcInfo->lpsmem;
  197. #endif
  198.  
  199.     if (!sendMailPtr)
  200.     {
  201.       return(MAPI_E_FAILURE);
  202.     }
  203.  
  204.     sendMailPtr->ipcWorked = 1;         // Set the worked flag
  205.     return(ProcessMAPISendMail(sendMailPtr));
  206.     break;
  207.     }
  208.  
  209.   //////////////////////////////////////////////////////////////////////
  210.   // MAPISendDocuments
  211.   //////////////////////////////////////////////////////////////////////
  212.   case NSCP_MAPISendDocuments:
  213.      {
  214.      MAPISendDocumentsType     *sendDocPtr;
  215. #ifdef WIN32
  216.     sendDocPtr = (MAPISendDocumentsType *) &(sMem->m_buf[0]);
  217. #else    
  218.     sendDocPtr = (MAPISendDocumentsType *) ipcInfo->lpsmem;
  219. #endif
  220.  
  221.     if (!sendDocPtr)
  222.     {
  223.       return(MAPI_E_FAILURE);
  224.     }
  225.  
  226.     sendDocPtr->ipcWorked = 1;         // Set the worked flag
  227.     return(ProcessMAPISendDocuments(sendDocPtr));
  228.     break;
  229.     }
  230.  
  231.   //////////////////////////////////////////////////////////////////////
  232.   // MAPIFindNext
  233.   //////////////////////////////////////////////////////////////////////
  234.   case NSCP_MAPIFindNext:
  235.     {
  236.     MAPIFindNextType    *findInfo;
  237.  
  238. #ifdef WIN32
  239.     findInfo = (MAPIFindNextType *) &(sMem->m_buf[0]);
  240. #else    
  241.     findInfo = (MAPIFindNextType *) ipcInfo->lpsmem;
  242. #endif
  243.  
  244.     if (!findInfo)
  245.     {
  246.       return(MAPI_E_FAILURE);
  247.     }
  248.  
  249.     findInfo->ipcWorked = 1;         // Set the worked flag
  250.     return(ProcessMAPIFindNext(findInfo));
  251.     break;
  252.     }
  253.  
  254.   //////////////////////////////////////////////////////////////////////
  255.   // MAPIDeleteMail
  256.   //////////////////////////////////////////////////////////////////////
  257.   case NSCP_MAPIDeleteMail:
  258.     {
  259.     MAPIDeleteMailType    *delInfo;
  260.  
  261. #ifdef WIN32
  262.     delInfo = (MAPIDeleteMailType *) &(sMem->m_buf[0]);
  263. #else    
  264.     delInfo = (MAPIDeleteMailType *) ipcInfo->lpsmem;
  265. #endif
  266.  
  267.     if (!delInfo)
  268.     {
  269.       return(MAPI_E_FAILURE);
  270.     }
  271.  
  272.     delInfo->ipcWorked = 1;         // Set the worked flag
  273.     return(ProcessMAPIDeleteMail(delInfo));
  274.     break;
  275.     }
  276.  
  277.   //////////////////////////////////////////////////////////////////////
  278.   // MAPIResolveName
  279.   //////////////////////////////////////////////////////////////////////
  280.   case NSCP_MAPIResolveName:
  281.     {
  282.     MAPIResolveNameType    *nameInfo;
  283.  
  284. #ifdef WIN32
  285.     nameInfo = (MAPIResolveNameType *) &(sMem->m_buf[0]);
  286. #else    
  287.     nameInfo = (MAPIResolveNameType *) ipcInfo->lpsmem;
  288. #endif
  289.  
  290.     if (!nameInfo)
  291.     {
  292.       return(MAPI_E_FAILURE);
  293.     }
  294.  
  295.     nameInfo->ipcWorked = 1;         // Set the worked flag
  296.     return(ProcessMAPIResolveName(nameInfo));
  297.     break;
  298.     }
  299.  
  300.   //////////////////////////////////////////////////////////////////////
  301.   // MAPIDetails
  302.   //////////////////////////////////////////////////////////////////////
  303.   case NSCP_MAPIDetails:
  304.     {
  305.     MAPIDetailsType    *detailInfo;
  306.  
  307. #ifdef WIN32
  308.     detailInfo = (MAPIDetailsType *) &(sMem->m_buf[0]);
  309. #else    
  310.     detailInfo = (MAPIDetailsType *) ipcInfo->lpsmem;
  311. #endif
  312.  
  313.     if (!detailInfo)
  314.     {
  315.       return(MAPI_E_FAILURE);
  316.     }
  317.  
  318.     detailInfo->ipcWorked = 1;         // Set the worked flag
  319.     return(ProcessMAPIDetails(detailInfo));
  320.     break;
  321.     }
  322.  
  323.   //////////////////////////////////////////////////////////////////////
  324.   // MAPIReadMail
  325.   //////////////////////////////////////////////////////////////////////  
  326.   case NSCP_MAPIReadMail:
  327.     {
  328.     MAPIReadMailType    *readInfo;
  329.  
  330. #ifdef WIN32
  331.     readInfo = (MAPIReadMailType *) &(sMem->m_buf[0]);
  332. #else    
  333.     readInfo = (MAPIReadMailType *) ipcInfo->lpsmem;
  334. #endif
  335.  
  336.     if (!readInfo)
  337.     {
  338.       return(MAPI_E_FAILURE);
  339.     }
  340.  
  341.     readInfo->ipcWorked = 1;         // Set the worked flag
  342.     return(ProcessMAPIReadMail(readInfo));
  343.     break;
  344.     }
  345.  
  346.   //////////////////////////////////////////////////////////////////////
  347.   // NSCP_MAPISaveMail
  348.   //////////////////////////////////////////////////////////////////////
  349.   case NSCP_MAPISaveMail:
  350.      {
  351.      MAPISendMailType     *sendMailPtr;
  352. #ifdef WIN32
  353.     sendMailPtr = (MAPISendMailType *) &(sMem->m_buf[0]);
  354. #else    
  355.     sendMailPtr = (MAPISendMailType *) ipcInfo->lpsmem;
  356. #endif
  357.  
  358.     if (!sendMailPtr)
  359.     {
  360.       return(MAPI_E_FAILURE);
  361.     }
  362.  
  363.     sendMailPtr->ipcWorked = 1;         // Set the worked flag
  364.     return(ProcessMAPISaveMail(sendMailPtr));
  365.     break;
  366.     }
  367.  
  368.   //////////////////////////////////////////////////////////////////////
  369.   // MAPIAddress
  370.   //////////////////////////////////////////////////////////////////////
  371.   case NSCP_MAPIAddress:
  372.     {
  373.     MAPIAddressType    *addrInfo;
  374.  
  375. #ifdef WIN32
  376.     addrInfo = (MAPIAddressType *) &(sMem->m_buf[0]);
  377. #else    
  378.     addrInfo = (MAPIAddressType *) ipcInfo->lpsmem;
  379. #endif
  380.  
  381.     if (!addrInfo)
  382.     {
  383.       return(MAPI_E_FAILURE);
  384.     }
  385.  
  386.     addrInfo->ipcWorked = 1;         // Set the worked flag
  387.     return(ProcessMAPIAddress(addrInfo));
  388.     }
  389.   
  390.   case NSCP_MAPIFree:   // This should never hit Communicator, but if it does
  391. #ifdef WIN16
  392.     return(SUCCESS_SUCCESS);       // Just return
  393. #else
  394.     return(S_OK);       // Just return 
  395. #endif
  396.  
  397.     default:
  398.     return(MAPI_E_NOT_SUPPORTED);     // Should never hit here!
  399.         break;
  400.     }
  401.  
  402.     return(SUCCESS_SUCCESS);
  403. }
  404.  
  405. //
  406. // Find the default session for Communicator...
  407. //
  408. CMAPIConnection 
  409. *GetDefaultSession(void)
  410. {
  411.   int i;
  412.   
  413.   for (i=0; i < MAX_CON; i++)
  414.   {
  415.     if (mapiConnections[i] != NULL)
  416.     {
  417.       if (mapiConnections[i]->IsDefault())
  418.       {
  419.         return mapiConnections[i];
  420.       }
  421.     }
  422.   }
  423.  
  424.   return(NULL);
  425. }
  426.  
  427. //
  428. // Find an open session slot...
  429. //
  430. LONG
  431. GetOpenSessionSlot( void )
  432. {
  433.   int i;
  434.   
  435.   for (i=0; i < MAX_CON; i++)
  436.   {
  437.     if (mapiConnections[i] == NULL)
  438.     {
  439.       return(i);
  440.     }
  441.   }
  442.  
  443.   return(-1);
  444. }
  445.  
  446. //
  447. // Returns TRUE if it was reassigned and FALSE if not.
  448. //
  449. BOOL
  450. TryDefaultReassignment(void)
  451. {
  452.   int   i;
  453.   int   loc = -1;
  454.  
  455.   // Find any sessions left?
  456.   for (i=0; i < MAX_CON; i++)
  457.   {
  458.     if (mapiConnections[i] != NULL)
  459.     {
  460.       loc = i;
  461.       break;
  462.     }
  463.   }
  464.  
  465.   // Set default state on the object to true
  466.   if (loc >= 0)
  467.   {
  468.     mapiConnections[loc]->SetDefault(TRUE);
  469.     return(TRUE);
  470.   }
  471.   else    
  472.   {
  473.     return(FALSE);
  474.   }
  475. }
  476.  
  477. LONG
  478. ProcessMAPILogon(MAPILogonType *logonInfo)
  479. {
  480.   CMAPIConnection *defSession = GetDefaultSession();
  481.   NSstringSeq strSeq = (LPSTR) logonInfo + sizeof(MAPILogonType);
  482.   LPSTR lpszProfileName = NSStrSeqGet(strSeq, 0);
  483.   LPSTR lpszPassword    = NSStrSeqGet(strSeq, 1);
  484.  
  485.   TRACE("MAPI: ProcessMAPILogon() ProfileName = [%s] Password = [%s]\n", 
  486.                             lpszProfileName, lpszPassword);
  487.   //
  488.   // This is a query if lpszProfileName is NULL, lpszPassword is NULL and 
  489.   // the MAPI_LOGON_UI is not set 
  490.   //
  491.   if ((lpszProfileName[0] == '\0') && (lpszPassword[0] == '\0') && 
  492.     (!(logonInfo->flFlags & MAPI_LOGON_UI)) )
  493.   {
  494.     if (defSession == NULL)
  495.     {
  496.       return(MAPI_E_FAILURE);
  497.     }
  498.     else
  499.     {
  500.       defSession->IncrementSessionCount();
  501.       logonInfo->lhSession = defSession->GetID();
  502.       return(SUCCESS_SUCCESS);
  503.     }
  504.   }
  505.  
  506.   //
  507.   // Only allow for sessions by a single profile name...
  508.   //
  509.   if ( ( defSession != NULL ) &&
  510.        (
  511.         (lstrcmp(lpszProfileName, defSession->GetProfileName() ) != 0) ||
  512.         (lstrcmp(lpszPassword, defSession->GetPassword() ) != 0)
  513.        )
  514.      )
  515.   {
  516.     return(MAPI_E_TOO_MANY_SESSIONS);
  517.   }
  518.  
  519.   //
  520.   // Now create the new MAPI session if we have to...
  521.   //
  522.   BOOL createNew = FALSE;
  523.   if ( 
  524.       ( defSession == NULL ) ||
  525.       // Indicates an attempt should be made to create a new session rather than acquire 
  526.       // the environment's shared session. If the MAPI_NEW_SESSION flag is not set, MAPILogon 
  527.       // uses an existing shared session.
  528.       (logonInfo->flFlags & MAPI_NEW_SESSION) ||
  529.       (defSession == NULL)      // No default session exists!
  530.      ) 
  531.   {
  532.     createNew = TRUE;
  533.   }
  534.  
  535.   //
  536.   // Make sure only 4 max are allowed...
  537.   //
  538.   LONG  slot; 
  539.   if ((createNew) && ((slot = GetOpenSessionSlot()) == -1))
  540.   {
  541.     return(MAPI_E_TOO_MANY_SESSIONS);
  542.   }
  543.  
  544.   //
  545.   // If we don't have to create a new session, just return the ID and
  546.   // move on with life
  547.   //
  548.   if (!createNew)
  549.   {
  550.     if (defSession == NULL)
  551.     {
  552.       return(MAPI_E_FAILURE);
  553.     }
  554.  
  555.     defSession->IncrementSessionCount();
  556.     logonInfo->lhSession = defSession->GetID();
  557.     return(SUCCESS_SUCCESS);
  558.   }
  559.  
  560.   //
  561.   // Finally, create a new session!
  562.   //
  563.   mapiConnections[slot] = new CMAPIConnection(slot, lpszProfileName, lpszPassword);
  564.   if (defSession == NULL)
  565.   {
  566.     mapiConnections[slot]->SetDefault(TRUE);
  567.   }
  568.  
  569.   logonInfo->lhSession = mapiConnections[slot]->GetID();
  570.  
  571.   //
  572.   // Process Flags...
  573.   //
  574.   // Indicates an attempt should be made to download all of the user's messages before 
  575.   // returning. If the MAPI_FORCE_DOWNLOAD flag is not set, messages can be downloaded 
  576.   // in the background after the function call returns.
  577.   if (logonInfo->flFlags & MAPI_FORCE_DOWNLOAD) 
  578.   {
  579.     MAPIGetNewMessagesInBackground();
  580.   }
  581.  
  582.   // Indicates that a logon dialog box should be displayed to prompt the user for 
  583.   // logon information. If the user needs to provide a password and profile name 
  584.   // to enable a successful logon, MAPI_LOGON_UI must be set.
  585.   if (logonInfo->flFlags & MAPI_LOGON_UI) 
  586.   {
  587.     TRACE("MAPI: ProcessMAPILogon() MAPI_LOGON_UI Unsupported.\n");
  588.   }
  589.  
  590. #ifdef WIN32
  591.   // Indicates that MAPILogon should only prompt for a password and not allow the user 
  592.   // to change the profile name. Either MAPI_PASSWORD_UI or MAPI_LOGON_UI should not be 
  593.   // set, since the intent is to select between two different dialog boxes for logon.
  594.   if (logonInfo->flFlags & MAPI_PASSWORD_UI)
  595.   {
  596.     TRACE("MAPI: ProcessMAPILogon() MAPI_PASSWORD_UI Unsupported.\n");
  597.   }         
  598. #endif  
  599.   
  600.   return(SUCCESS_SUCCESS);
  601. }
  602.  
  603. LONG    
  604. ProcessMAPILogoff(MAPILogoffType *logoffInfo)
  605. {
  606.   TRACE("MAPI: ProcessMAPILogoff() Session ID = [%d]\n", logoffInfo->lhSession);
  607.   //
  608.   // Verify the session handle...
  609.   //
  610.   if (( (logoffInfo->lhSession-1) >= MAX_CON) || ( (logoffInfo->lhSession-1) < 0))
  611.   {
  612.     return(MAPI_E_INVALID_SESSION);
  613.   }
  614.  
  615.   CMAPIConnection *logoffSession = mapiConnections[(logoffInfo->lhSession - 1)];
  616.   if (logoffSession == NULL)
  617.   {
  618.     return(MAPI_E_INVALID_SESSION);
  619.   }
  620.   
  621.   //
  622.   // Decrement the session count, then if this is the last one 
  623.   // connected to this session, then kill it...
  624.   //
  625.   logoffSession->DecrementSessionCount();
  626.   if (logoffSession->GetSessionCount() <= 0)
  627.   {
  628.     //
  629.     // If this was the default session "holder", then we need to 
  630.     // assign that task to a new one if it exists, if not, then
  631.     // it is all back to null.
  632.     //
  633.     BOOL needToReassign = logoffSession->IsDefault();
  634.  
  635.     delete logoffSession;
  636.     mapiConnections[logoffInfo->lhSession - 1] = NULL;
  637.  
  638.     if (needToReassign)
  639.     {
  640.       TRACE("MAPI: ProcessMAPILogoff() Need to reassign default\n");
  641.       if (!TryDefaultReassignment())
  642.       {
  643.         if (pMAPIFrameWnd != NULL)
  644.         {
  645.           pMAPIFrameWnd->PostMessage(WM_CLOSE);
  646.           pMAPIFrameWnd = NULL;
  647.         }
  648.       }
  649.     }
  650.   }
  651.  
  652.   return(SUCCESS_SUCCESS);
  653. }
  654.  
  655. //
  656. // Actually process the send mail operation...
  657. //
  658. LONG    
  659. ProcessMAPISendMail(MAPISendMailType *sendMailPtr)
  660. {
  661.   CMAPIConnection *mySession;
  662.   NSstringSeq     mailInfoSeq;
  663.  
  664.   TRACE("MAPI: ProcessMAPISendMail() Session ID = [%d]\n", sendMailPtr->lhSession);
  665.   //
  666.   // Verify the session handle...
  667.   //
  668.   if (((sendMailPtr->lhSession-1) >= MAX_CON) || ((sendMailPtr->lhSession-1) < 0))
  669.   {
  670.     return(MAPI_E_FAILURE);
  671.   }
  672.  
  673.   mySession = mapiConnections[(sendMailPtr->lhSession - 1)];
  674.   if (mySession == NULL)
  675.   {
  676.     return(MAPI_E_FAILURE);
  677.   }
  678.  
  679.   //
  680.   // Before we start, make sure things make sense...
  681.   //
  682.   if ( (!(sendMailPtr->flFlags & MAPI_DIALOG)) && (sendMailPtr->MSG_nRecipCount == 0) )
  683.   {
  684.     return(MAPI_E_UNKNOWN_RECIPIENT);
  685.   }
  686.  
  687.   mailInfoSeq = (NSstringSeq) &(sendMailPtr->dataBuf[0]);
  688.   TRACE("MAPI: ProcessMAPISendMail() Session ID = [%d]\n", sendMailPtr->lhSession);
  689.  
  690.   //
  691.   // Now set the show window flag...
  692.   //
  693.   BOOL showWindow = (( sendMailPtr->flFlags & MAPI_DIALOG ) != 0);
  694.   LONG rc = DoFullMAPIMailOperation(sendMailPtr, 
  695.                                     NSStrSeqGet(mailInfoSeq, 1),
  696.                                     showWindow);
  697.   return(rc);
  698. }
  699.  
  700. //
  701. // Actually process the send mail operation...
  702. //
  703. LONG    
  704. ProcessMAPISaveMail(MAPISendMailType *sendMailPtr)
  705. {
  706.   CMAPIConnection *mySession;
  707.   NSstringSeq     mailInfoSeq;
  708.  
  709.   TRACE("MAPI: ProcessMAPISaveMail() Session ID = [%d]\n", sendMailPtr->lhSession);
  710.   //
  711.   // Verify the session handle...
  712.   //
  713.   if (((sendMailPtr->lhSession-1) >= MAX_CON) || ((sendMailPtr->lhSession-1) < 0))
  714.   {
  715.     return(MAPI_E_FAILURE);
  716.   }
  717.  
  718.   mySession = mapiConnections[(sendMailPtr->lhSession - 1)];
  719.   if (mySession == NULL)
  720.   {
  721.     return(MAPI_E_FAILURE);
  722.   }
  723.  
  724.   mailInfoSeq = (NSstringSeq) &(sendMailPtr->dataBuf[0]);
  725.   TRACE("MAPI: ProcessMAPISaveMail() Session ID = [%d]\n", sendMailPtr->lhSession);
  726.  
  727.   //
  728.   // Now process the save mail operation...
  729.   //
  730.   LONG rc = DoMAPISaveMailOperation(sendMailPtr, 
  731.                                     NSStrSeqGet(mailInfoSeq, 1));
  732.   return(rc);
  733. }
  734.  
  735. //
  736. // Actually process the send documents operation...
  737. //
  738. LONG    
  739. ProcessMAPISendDocuments(MAPISendDocumentsType *sendDocPtr)
  740. {
  741.   LONG rc = DoPartialMAPIMailOperation(sendDocPtr);    
  742.   return(rc);
  743. }
  744.  
  745. //
  746. // This is an ENUM procedure for messages that are in the system
  747. //
  748. LONG    
  749. ProcessMAPIFindNext(MAPIFindNextType *findInfo)
  750. {
  751.   CMAPIConnection *mySession;
  752.  
  753.   //
  754.   // Verify the session handle...
  755.   //
  756.   if (((findInfo->lhSession-1) >= MAX_CON) || ((findInfo->lhSession-1) < 0))
  757.   {
  758.     return(MAPI_E_INVALID_SESSION);
  759.   }
  760.  
  761.   mySession = mapiConnections[(findInfo->lhSession - 1)];
  762.   if (mySession == NULL)
  763.   {
  764.     return(MAPI_E_INVALID_SESSION);
  765.   }
  766.  
  767.   //
  768.   // If this is true, then this is the first call to this FindNext function
  769.   // and we should start the enumeration operation.
  770.   //
  771.     MSG_FolderInfo  *inboxFolder = NULL;
  772.     int32           folderRC = MSG_GetFoldersWithFlag(WFE_MSGGetMaster(),
  773.                                                 MSG_FOLDER_FLAG_INBOX, &inboxFolder, 1);
  774.   if (folderRC <= 0)
  775.   {
  776.     return(MAPI_E_NO_MESSAGES);
  777.   }
  778.  
  779.   // This is the first message
  780.   if (mySession->GetMessageIndex() < 0)
  781.   {
  782.     MSG_MapiListContext *cookie;
  783.  
  784.     MessageKey keyFound = MSG_GetFirstKeyInFolder(inboxFolder, &cookie);
  785.     if (keyFound == MSG_MESSAGEKEYNONE)
  786.     {
  787.       mySession->SetMapiListContext(NULL);
  788.       mySession->SetMessageIndex(-1); // Reset to -1...
  789.       return(MAPI_E_NO_MESSAGES);
  790.     }
  791.  
  792.     TRACE("MAPI: ProcessMAPIFindNext() Found message id = %d\n", keyFound);
  793.  
  794.     wsprintf((LPSTR) findInfo->lpszMessageID, "%d", keyFound);
  795.     mySession->SetMapiListContext(cookie);
  796.     mySession->SetMessageIndex(keyFound); // Just set to 1 and then increment from there...
  797.   }
  798.   else
  799.   {
  800.     MSG_MapiListContext *cookie = (MSG_MapiListContext *)mySession->GetMapiListContext();
  801.     
  802.     // Sanity check the cookie value...
  803.     if (cookie == NULL)
  804.     {
  805.       mySession->SetMapiListContext(NULL);
  806.       mySession->SetMessageIndex(-1); // Reset to -1...
  807.       return(MAPI_E_NO_MESSAGES);
  808.     }
  809.  
  810.     MessageKey nextKey = MSG_GetNextKeyInFolder(cookie);
  811.     if (nextKey == MSG_MESSAGEKEYNONE)
  812.     {
  813.       mySession->SetMapiListContext(NULL);
  814.       mySession->SetMessageIndex(-1); // Reset to -1...
  815.       return(MAPI_E_NO_MESSAGES);
  816.     }
  817.  
  818.     TRACE("MAPI: ProcessMAPIFindNext() Found message id = %d\n", nextKey);
  819.  
  820.     wsprintf((LPSTR) findInfo->lpszMessageID, "%d", nextKey);
  821.     mySession->SetMessageIndex(nextKey); // Set the key to the found one and move on...
  822.   }
  823.  
  824.   return(SUCCESS_SUCCESS);
  825. }
  826.  
  827. //
  828. // Actually process the delete mail operation!
  829. //
  830. LONG    
  831. ProcessMAPIDeleteMail(MAPIDeleteMailType *delInfo)
  832. {
  833.   CMAPIConnection *mySession;
  834.  
  835.   //
  836.   // Verify the session handle...
  837.   //
  838.   if (((delInfo->lhSession-1) >= MAX_CON) || ((delInfo->lhSession-1) < 0))
  839.   {
  840.     return(MAPI_E_INVALID_SESSION);
  841.   }
  842.  
  843.   mySession = mapiConnections[(delInfo->lhSession - 1)];
  844.   if (mySession == NULL)
  845.   {
  846.     return(MAPI_E_INVALID_SESSION);
  847.   }
  848.  
  849.   BOOL    msgValid = TRUE;
  850.  
  851.   TRACE("MAPI: RICHIE TODO: ProcessMAPIDeleteMail() TRY TO FIND THE MESSAGE FROM THE IDENTIFIER:\n");
  852.   TRACE("MAPI: RICHIE TODO: ProcessMAPIDeleteMail() [%s]\n", delInfo->lpszMessageID);
  853.  
  854.   if (msgValid)
  855.   {
  856.     TRACE("MAPI: RICHIE TODO: ProcessMAPIDeleteMail() DELETE THE MESSAGE!!!\n");
  857.  
  858.     return(SUCCESS_SUCCESS);
  859.   }
  860.   else
  861.   {
  862.     return(MAPI_E_INVALID_MESSAGE);
  863.   }
  864. }
  865.  
  866. // 
  867. // Process the name resolution for the address passed in.
  868. //
  869. LONG    
  870. ProcessMAPIResolveName(MAPIResolveNameType *nameInfo)
  871. {
  872.   CMAPIConnection *mySession;
  873.  
  874.   //
  875.   // Verify the session handle...
  876.   //
  877.   if (((nameInfo->lhSession-1) >= MAX_CON) || ((nameInfo->lhSession-1) < 0))
  878.   {
  879.     return(MAPI_E_INVALID_SESSION);
  880.   }
  881.  
  882.   mySession = mapiConnections[(nameInfo->lhSession - 1)];
  883.   if (mySession == NULL)
  884.   {
  885.     return(MAPI_E_INVALID_SESSION);
  886.   }
  887.  
  888.   TRACE("MAPI: ProcessMAPIResolveName() TRY TO IDENTIFY THE ADDRESS INFO FOR THE NAME:\n");
  889.   TRACE("MAPI: ProcessMAPIResolveName() [%s]\n", nameInfo->lpszName);
  890.  
  891.   DWORD numFound;
  892.   LPSTR retFullName = NULL;
  893.   LPSTR retAddr = NULL;
  894.   
  895.   AB_ContainerInfo  *ctr;
  896.   ABID              id;
  897.  
  898.   numFound = AB_MAPI_ResolveName ( 
  899.                 (char *)nameInfo->lpszName, // i.e. a nickname or part of the person's name to look up. Assumes First Last 
  900.                 &ctr,                       // caller allocates the ctr ptr. BE fills Caller must close container when done with it
  901.                 &id);                       // caller allocates the ABID, BE fills 
  902.  
  903.   if (numFound > 1)
  904.   {
  905.     return(MAPI_E_AMBIGUOUS_RECIPIENT);
  906.   }
  907.   else if (numFound <= 0)
  908.   {
  909.     return(MAPI_E_UNKNOWN_RECIPIENT);
  910.   }
  911.   else    // Here we found a single entry!
  912.   {
  913.     // Get the full name and email address...
  914.     retFullName = AB_MAPI_GetFullName(ctr, id);
  915.     retAddr = AB_MAPI_GetEmailAddress(ctr, id);
  916.  
  917.     // null out return values just in case...
  918.     nameInfo->lpszABookName[0] = '\0';
  919.     nameInfo->lpszABookAddress[0] = '\0';
  920.  
  921.     // if valid, copy the strings over...
  922.     if (retFullName)
  923.       lstrcpy((LPSTR) nameInfo->lpszABookName, retFullName);
  924.     if (retAddr)
  925.       lstrcpy((LPSTR) nameInfo->lpszABookAddress, retAddr);
  926.  
  927.     // Now get the string to use for an ID later on...
  928.     LPSTR  abookIDString =  AB_MAPI_ConvertToDescription(ctr); 
  929.  
  930.     // build that string ID to pass back through the MAPI API
  931.     wsprintf((LPSTR) nameInfo->lpszABookID, "%d%s", id, DELIMIT);
  932.     lstrcat((LPSTR) nameInfo->lpszABookID, abookIDString);
  933.     
  934.     // Be nice and cleanup after ourselves...
  935.     if (retAddr)
  936.       XP_FREE(retAddr);
  937.     if (retFullName)
  938.       XP_FREE(retFullName);
  939.     if (abookIDString)
  940.       XP_FREE(abookIDString);
  941.  
  942.     return(SUCCESS_SUCCESS);
  943.   }
  944. }
  945.  
  946. //
  947. // This deals with the MAPIDetails call
  948. //
  949. LONG    
  950. ProcessMAPIDetails(MAPIDetailsType *detailInfo)
  951. {
  952.   CMAPIConnection *mySession;
  953.  
  954.   //
  955.   // Verify the session handle...
  956.   //
  957.   if (((detailInfo->lhSession-1) >= MAX_CON) || ((detailInfo->lhSession-1) < 0))
  958.   {
  959.     return(MAPI_E_INVALID_SESSION);
  960.   }
  961.  
  962.   mySession = mapiConnections[(detailInfo->lhSession - 1)];
  963.   if (mySession == NULL)
  964.   {
  965.     return(MAPI_E_INVALID_SESSION);
  966.   }
  967.  
  968.   TRACE("MAPI: ProcessMAPIDetails() NEED TO LOCATE THE ENTRY FOR:\n");
  969.   TRACE("MAPI: ProcessMAPIDetails() [%s]\n", detailInfo->lpszABookID);
  970.  
  971.   char    workString[MAX_NAME_LEN];
  972.   char    *idString;
  973.   char    *containerString;
  974.  
  975.   lstrcpy((LPSTR) workString, (LPSTR) detailInfo->lpszABookID);
  976.  
  977.   //
  978.   // Now parse out the first and last names of the person...
  979.   //
  980.   int       totLen = lstrlen((LPSTR) workString);
  981.   int       loc = 0;
  982.   idString = &(workString[0]);
  983.  
  984.   while ( ( lstrlen((LPSTR) DELIMIT) + loc) < totLen)
  985.   {
  986.     if (strncmp((LPSTR)(workString + loc), DELIMIT, lstrlen(DELIMIT)) == 0)
  987.     {
  988.       workString[loc] = '\0';
  989.       containerString = &(workString[loc + lstrlen(DELIMIT)]);
  990.       break;
  991.     }
  992.  
  993.     ++loc;
  994.   }
  995.     
  996.   if ( (lstrlen((LPSTR) DELIMIT) + loc) >= totLen )
  997.   {
  998.     return(MAPI_E_INVALID_RECIPS);
  999.   }
  1000.  
  1001.   // Now, convert the stuff to real values for the API...
  1002.   ABID              id = atoi((const char *) idString);
  1003.   AB_ContainerInfo  *container = AB_MAPI_ConvertToContainer(containerString);
  1004.   MSG_Pane          *personPane = NULL;
  1005.   extern MWContext         *GetUsableContext(void);
  1006.  
  1007.   // Need to first create a person entry pane and then call
  1008.   // FE_ShowPropertySheetAB2 on that pane - return 0 is problem
  1009.   int rc = AB_MAPI_CreatePropertySheetPane( 
  1010.             GetUsableContext(),
  1011.             WFE_MSGGetMaster(), 
  1012.             container, 
  1013.             id, 
  1014.             &personPane);  // BE will allocate a personPane and return a ptr to it here 
  1015.   if (!rc)
  1016.   {
  1017.     return(MAPI_E_INVALID_RECIPS);
  1018.   }
  1019.  
  1020.   // Now display the address book entry for this user. If the parameter
  1021.   // detailInfo->ulUIParam  is NULL, just doit and return, but if it is
  1022.   // not NULL, then we should do it as application modal.
  1023.   
  1024.   // RICHIE - THIS IS NOT IN THE BUILD YET! MUST WAIT
  1025.   //(void) FE_ShowPropertySheetForAB2(personPane, AB_Person);
  1026.  
  1027.   // cleanup the container and person pane...
  1028.   AB_MAPI_CloseContainer(&container);
  1029.   AB_ClosePane(personPane); 
  1030.  
  1031.   return(SUCCESS_SUCCESS);
  1032. }
  1033.  
  1034. //
  1035. // CMAPIConnections object...should be in their own file...
  1036. //
  1037. CMAPIConnection::CMAPIConnection  ( LONG id, LPSTR name, LPSTR pw)
  1038. {
  1039.   m_sessionCount = 1;
  1040.   m_defaultConnection = FALSE;
  1041.   m_ID = (id + 1);      // since zero is invalid, but have to make sure we 
  1042.                         // decrement by one when it is passed in again.
  1043.   m_messageIndex = -1;  // For tracing our way through the FindNext operation
  1044.   m_cookie = NULL;      // For doing the enumeration of messages
  1045.   m_messageFindInfo[0] = '\0';
  1046.   lstrcpy((LPSTR) m_profileName, name);
  1047.   lstrcpy((LPSTR) m_password, pw);  
  1048. }
  1049.  
  1050. CMAPIConnection::~CMAPIConnection ( )
  1051. {
  1052. }
  1053.  
  1054. //
  1055. // This is all needed to process a MAPIReadMail operation
  1056. //
  1057. static LPSTR
  1058. CheckNull(LPSTR inStr)
  1059. {
  1060.   static UCHAR  str[1];
  1061.  
  1062.   str[0] = '\0';
  1063.   if (inStr == NULL)
  1064.     return((LPSTR)str);
  1065.   else
  1066.     return(inStr);
  1067. }
  1068.  
  1069. LONG
  1070. WriteTheMemoryBufferToDisk(LPSTR fName, UINT bufSize, LPSTR buf)
  1071. {
  1072.   if (!buf)
  1073.   {
  1074.     return(-1);
  1075.   }
  1076.  
  1077.   HFILE hFile = _lcreat(fName, 0);
  1078.   if (hFile == HFILE_ERROR)
  1079.   {
  1080.     return(-1);
  1081.   }
  1082.  
  1083.   UINT writeCount = _lwrite(hFile, buf, bufSize);
  1084.   _lclose(hFile);
  1085.  
  1086.   if (writeCount != bufSize)
  1087.   {
  1088.     _unlink(fName);
  1089.     return(-1);
  1090.   }
  1091.  
  1092.   return(0);
  1093. }
  1094.  
  1095. static LPSTR
  1096. GetTheTempDirectoryOnTheSystem(void)
  1097. {
  1098.  static UCHAR retPath[_MAX_PATH];
  1099.   
  1100.   if (getenv("TEMP"))
  1101.   {
  1102.     lstrcpy((LPSTR) retPath, getenv("TEMP"));  // environmental variable
  1103.   } 
  1104.   else if (getenv("TMP"))
  1105.   {
  1106.     lstrcpy((LPSTR) retPath, getenv("TMP"));  // How about this environmental variable?
  1107.   }
  1108.   else
  1109.   {
  1110.     GetWindowsDirectory((LPSTR) retPath, sizeof(retPath));
  1111.   }
  1112.  
  1113.   return((LPSTR) &(retPath[0]));
  1114. }
  1115.  
  1116. #ifdef WIN16
  1117. static int ISGetTempFileName(LPCSTR a_pDummyPath,  LPCSTR a_pPrefix, UINT a_uUnique, LPSTR a_pResultName)
  1118. {
  1119. #ifdef GetTempFileName    // we need the real thing comming up next...
  1120. #undef GetTempFileName
  1121. #endif
  1122.     return GetTempFileName(0, a_pPrefix, a_uUnique, a_pResultName);
  1123. }
  1124. #endif
  1125.  
  1126. static DWORD 
  1127. ValidateFile(LPCSTR szFile) 
  1128. {
  1129.       struct _stat buf;
  1130.     int result;
  1131.  
  1132.     result = _stat( szFile, &buf );
  1133.     if (result != 0)
  1134.       return(1);
  1135.  
  1136.     if (!(buf.st_mode & S_IREAD))
  1137.       return(2);
  1138.  
  1139.     return(0);
  1140. }
  1141.  
  1142. static LONG
  1143. GetTempAttachmentName(LPSTR fName) 
  1144. {
  1145.   UINT        res;
  1146.   static UINT uUnique = 1;
  1147.  
  1148.   if (!fName)
  1149.     return(-1);
  1150.  
  1151.   LPSTR szTempPath = GetTheTempDirectoryOnTheSystem();
  1152.  
  1153. TRYAGAIN:
  1154. #ifdef WIN32
  1155.   res = GetTempFileName(szTempPath, "MAPI", uUnique++, fName);
  1156. #else
  1157.   res = ISGetTempFileName(szTempPath, "MAPI", uUnique++, fName);
  1158. #endif
  1159.  
  1160.   if (ValidateFile(fName) != 1) 
  1161.   {
  1162.     if (uUnique < 32000)
  1163.     {
  1164.       goto TRYAGAIN;
  1165.     }
  1166.     else
  1167.     {
  1168.       return(-1);
  1169.     }
  1170.   }
  1171.  
  1172.   return 0;
  1173. }
  1174.  
  1175. LONG    
  1176. ProcessMAPIReadMail(MAPIReadMailType *readInfo)
  1177. {
  1178.   CMAPIConnection *mySession;
  1179.   lpMapiMessage   message;      // this is the message we will receive
  1180.  
  1181.   //
  1182.   // Verify the session handle...
  1183.   //
  1184.   if (((readInfo->lhSession-1) >= MAX_CON) || ((readInfo->lhSession-1) < 0))
  1185.   {
  1186.     return(MAPI_E_INVALID_SESSION);
  1187.   }
  1188.  
  1189.   mySession = mapiConnections[(readInfo->lhSession - 1)];
  1190.   if (mySession == NULL)
  1191.   {
  1192.     return(MAPI_E_INVALID_SESSION);
  1193.   }
  1194.  
  1195.   // First, gotta get the inbox folder!
  1196.   MSG_FolderInfo  *inboxFolder = NULL;
  1197.     int32           folderRC = MSG_GetFoldersWithFlag(WFE_MSGGetMaster(),
  1198.                                                 MSG_FOLDER_FLAG_INBOX, &inboxFolder, 1);
  1199.   if (folderRC <= 0)
  1200.   {
  1201.     return(MAPI_E_INVALID_MESSAGE);
  1202.   }
  1203.  
  1204.   // Convert the message id to a number!
  1205.   MessageKey lookupKey = atoi((const char *)readInfo->lpszMessageID);
  1206.   TRACE("MAPI: ProcessMAPIReadMail() Find this message = [%s] - [%d]\n", 
  1207.                           readInfo->lpszMessageID, lookupKey);
  1208.  
  1209.   // Now see if we can find this message!
  1210.   BOOL msgFound = MSG_GetMapiMessageById(inboxFolder, lookupKey, &message);
  1211.  
  1212.   // If we didn't find the message, then we need to bail!
  1213.   if (!msgFound)
  1214.   {
  1215.     TRACE("MAPI: ProcessMAPIReadMail() MESSAGE NOT FOUND\n");
  1216.     return(MAPI_E_INVALID_MESSAGE);
  1217.   }
  1218.  
  1219.   //
  1220.   // Now that we have found the message, we need to populate the chunk of
  1221.   // memory that we will write to disk and then move on. For now, we need
  1222.   // to setup all of the variables for the information we will need for the
  1223.   // message.
  1224.   //
  1225.   ULONG     i;
  1226.   DWORD     arrayCount = 0;         // Counter for array entries!
  1227.   DWORD     arrayTotal = 0;         // Total for array entries!
  1228.   FLAGS     msgFlags;               // unread, return or receipt                  
  1229.   ULONG     msgRecipCount = message->nRecipCount; // Number of recipients                   
  1230.   ULONG     msgFileAttachCount = message->nFileCount; // # of file attachments                  
  1231.  
  1232.   LPSTR     msgSubject = message->lpszSubject;          // Message Subject
  1233.   LPSTR     msgNoteText = NULL;                         // Message Text will be
  1234.   LPSTR     msgDateReceived = message->lpszDateReceived;// in YYYY/MM/DD HH:MM format
  1235.   LPSTR     msgThreadID = message->lpszConversationID;  // conversation thread ID
  1236.  
  1237.   //
  1238.   // The following are for the originator of the message. Only ONE of these.
  1239.   //
  1240.   LPSTR     origName = NULL;    // Originator name                           
  1241.   LPSTR     origAddress = NULL; // Originator address (optional)             
  1242.   ULONG     origRecipClass = MAPI_TO;               // Recipient class - MAPI_TO, MAPI_CC, MAPI_BCC, MAPI_ORIG
  1243.  
  1244.   // Now we have to make sure there is an originator and set the vars...
  1245.   if (message->lpOriginator)
  1246.   {
  1247.     origName    = message->lpOriginator->lpszName;
  1248.     origAddress = message->lpOriginator->lpszAddress;
  1249.   }
  1250.  
  1251.   if ( ! (readInfo->flFlags & MAPI_ENVELOPE_ONLY))
  1252.   {
  1253.       TRACE("MAPI: ProcessMAPIReadMail() GET NOTE TEXT - ONLY IF WE HAVE TO!\n"); 
  1254.       msgNoteText = message->lpszNoteText;
  1255.   }
  1256.  
  1257.   // First, figure out how many entries we need to have in a string array...
  1258.   arrayTotal = 6 + 1; // 6 for the first 6 strings and 1 for the final NULL    
  1259.  
  1260.   // Add the recipient information
  1261.   arrayTotal += (msgRecipCount * 3);
  1262.  
  1263.   // Now check to see if we are going to pass back attachments:
  1264.   //
  1265.   // MAPI_ENVELOPE_ONLY 
  1266.   // Indicates MAPIReadMail should read the message header only. File attachments are 
  1267.   // not copied to temporary files, and neither temporary file names nor message text 
  1268.   // is written. Setting this flag enhances performance. 
  1269.   //
  1270.   // MAPI_SUPPRESS_ATTACH 
  1271.   // Indicates MAPIReadMail should not copy file attachments but should write message 
  1272.   // text into the MapiMessage structure. MAPIReadMail ignores this flag if the 
  1273.   // calling application has set the MAPI_ENVELOPE_ONLY flag. Setting the 
  1274.   // MAPI_SUPPRESS_ATTACH flag enhances performance. 
  1275.   //
  1276.   if ((readInfo->flFlags & MAPI_SUPPRESS_ATTACH) ||
  1277.       (readInfo->flFlags & MAPI_ENVELOPE_ONLY) )
  1278.   {
  1279.     msgFileAttachCount = 0;
  1280.   }
  1281.  
  1282.   arrayTotal += (msgFileAttachCount * 2);
  1283.   
  1284.   // now allocate the memory for the string array 
  1285.   LPSTR *strArray = (LPSTR *) malloc((size_t) (sizeof(LPSTR) * arrayTotal));
  1286.   if (!strArray)
  1287.   {
  1288.     return(MAPI_E_INSUFFICIENT_MEMORY);
  1289.   }
  1290.  
  1291.   // Now assign the easy return values to the shared memory structure
  1292.   readInfo->MSG_flFlags     = msgFlags;           // unread, return or receipt                  
  1293.   readInfo->MSG_nRecipCount = msgRecipCount;      // Number of recipients                   
  1294.   readInfo->MSG_nFileCount  = msgFileAttachCount; // # of file attachments                  
  1295.   readInfo->MSG_ORIG_ulRecipClass = origRecipClass; //  Recipient class - MAPI_TO, MAPI_CC, MAPI_BCC, MAPI_ORIG
  1296.  
  1297.   // Now go through and fill out the array to create the string sequence
  1298.   strArray[0] = CheckNull(msgSubject);
  1299.   strArray[1] = CheckNull(msgNoteText);
  1300.   strArray[2] = CheckNull(msgDateReceived);
  1301.   strArray[3] = CheckNull(msgThreadID);
  1302.   strArray[4] = CheckNull(origName);
  1303.   strArray[5] = CheckNull(origAddress);
  1304.  
  1305.   arrayCount = 6;   // counter for the rest of the needed attachments
  1306.  
  1307.   // Now add all of the recipients
  1308.   for (i=0; i<msgRecipCount; i++)
  1309.   {
  1310.     UCHAR     tempString[128];
  1311.     ULONG     messageClass = message->lpRecips[i].ulRecipClass; // Get the recipient class...
  1312.  
  1313.     // Now get the following 3 items:
  1314.     //      String x: LPSTR lpszName;             // Recipient N name                           
  1315.     //      String x: LPSTR lpszAddress;          // Recipient N address (optional)             
  1316.     //      String x: LPSTR lpszRecipClass        // recipient class - sprintf of ULONG
  1317.     strArray[arrayCount++] = CheckNull(message->lpRecips[i].lpszName);
  1318.     strArray[arrayCount++] = CheckNull(message->lpRecips[i].lpszAddress);
  1319.  
  1320.     // 0    MAPI_ORIG    Indicates the original sender of the message. 
  1321.     // 1    MAPI_TO    Indicates a primary message recipient. 
  1322.     // 2    MAPI_CC    Indicates a recipient of a message copy. 
  1323.     // 3    MAPI_BCC    Indicates a recipient of a blind copy. 
  1324.     wsprintf((LPSTR) tempString, "%d", messageClass);
  1325.     strArray[arrayCount++] = CheckNull((LPSTR) tempString);
  1326.   }
  1327.  
  1328.   // Now, add all of the attachments to this blob
  1329.   for (i=0; i<msgFileAttachCount; i++)
  1330.   {
  1331.     //      String x: LPSTR lpszPathName // Fully qualified path of the attached file. 
  1332.     //                                   // This path should include the disk drive letter and directory name.
  1333.     //      String x: LPSTR lpszFileName // The display name for the attached file
  1334.     //
  1335.     strArray[arrayCount++] = CheckNull(message->lpFiles[i].lpszPathName);
  1336.     strArray[arrayCount++] = CheckNull(message->lpFiles[i].lpszFileName);
  1337.   }
  1338.  
  1339.   strArray[arrayCount] = NULL;
  1340.  
  1341.   // Create the string sequence
  1342.   NSstringSeq strSeq = NSStrSeqNew(strArray);
  1343.  
  1344.   // Now just cleanup the array....
  1345.   free(strArray);
  1346.  
  1347.   if (!strSeq)
  1348.   {
  1349.     return(MAPI_E_INSUFFICIENT_MEMORY);
  1350.   }
  1351.   
  1352.   // Now get the name of the file to write the blob to!
  1353.   if (GetTempAttachmentName((LPSTR)readInfo->lpszBlob) < 0)
  1354.   {
  1355.     NSStrSeqDelete(strSeq);
  1356.     return(MAPI_E_ATTACHMENT_WRITE_FAILURE);
  1357.   }
  1358.  
  1359.   // Now write the blob to disk and move on...
  1360.   if (WriteTheMemoryBufferToDisk((LPSTR) readInfo->lpszBlob, 
  1361.                       (UINT) NSStrSeqSize(strSeq), strSeq) != 0)
  1362.   {
  1363.     NSStrSeqDelete(strSeq);
  1364.     return(MAPI_E_ATTACHMENT_WRITE_FAILURE);
  1365.   }
  1366.  
  1367.   //
  1368.   // MAPI_PEEK 
  1369.   // Indicates MAPIReadMail does not mark the message as read. Marking a message as 
  1370.   // read affects its appearance in the user interface and generates a read receipt. 
  1371.   // If the messaging system does not support this flag, MAPIReadMail always marks 
  1372.   // the message as read. If MAPIReadMail encounters an error, it leaves the 
  1373.   // message unread.  
  1374.   if (!(readInfo->flFlags & MAPI_PEEK))
  1375.   {
  1376.     MSG_MarkMapiMessageRead (inboxFolder, lookupKey, TRUE);
  1377.   }
  1378.  
  1379.   // Now we have to free the message and the chunk of memory...
  1380.   MSG_FreeMapiMessage(message);
  1381.   NSStrSeqDelete(strSeq);
  1382.  
  1383.   return(SUCCESS_SUCCESS);
  1384. }
  1385.  
  1386. // necessary variables for 
  1387. int           arrayCount   = 0;         // Counter for array entries!
  1388. int           addressCount = 0;         // Counter for array entries!
  1389. LPSTR         *addrArray;
  1390. LPSTR         toString  = "1";
  1391. LPSTR         ccString  = "2";
  1392. LPSTR         bccString = "3";
  1393.  
  1394. BOOL 
  1395. AddressCallback(int totalCount, int currentIndex, 
  1396.                 int addrType, LPSTR addrString)
  1397. {
  1398.   LPSTR     messageClass; 
  1399.  
  1400.   TRACE("TOTAL COUNT   = %d\n", totalCount);
  1401.   TRACE("CURRENT COUNT = %d\n", currentIndex);
  1402.   TRACE("CURRENT ADDR  = %s\n", addrString);
  1403.  
  1404.   // If this is the first entry, then we need to allocate the array...
  1405.   if (currentIndex == 0)
  1406.   {
  1407.     addressCount = totalCount;
  1408.     addrArray = (LPSTR *) malloc( (size_t) 
  1409.                             sizeof(LPSTR) * ((addressCount * 3) + 1) 
  1410.                           );
  1411.     if (!addrArray)
  1412.     {
  1413.       addressCount = 0;
  1414.       return FALSE;
  1415.     }
  1416.   }
  1417.  
  1418.   // if the array was not allocated...
  1419.   if (!addrArray)
  1420.   {
  1421.     addressCount = 0;
  1422.     return FALSE;
  1423.   }
  1424.  
  1425.   // Deal with the address type...
  1426.   if (addrType == MSG_CC_HEADER_MASK)
  1427.     messageClass = ccString;
  1428.   else if (addrType == MSG_BCC_HEADER_MASK)
  1429.     messageClass = bccString;
  1430.   else 
  1431.     messageClass = toString;
  1432.  
  1433.   // Now get the following 3 items:
  1434.   //      String x: LPSTR lpszName;             // Recipient N name                           
  1435.   //      String x: LPSTR lpszAddress;          // Recipient N address (optional)             
  1436.   //      String x: LPSTR lpszRecipClass        // recipient class - sprintf of ULONG
  1437.  
  1438.   char *ptr = strchr(addrString, '<');
  1439.   if (ptr)
  1440.   {
  1441.     addrString[strlen(addrString) - 1] = '\0';
  1442.     *(ptr-1) = '\0';
  1443.   }
  1444.   addrArray[arrayCount++] = CheckNull(addrString);
  1445.  
  1446.   if (ptr)
  1447.   {
  1448.     ptr++;
  1449.   }
  1450.   else
  1451.   {
  1452.     ptr = (char *) addrString;
  1453.   }
  1454.  
  1455.   addrArray[arrayCount++] = CheckNull(ptr);
  1456.  
  1457.   // 0    MAPI_ORIG    Indicates the original sender of the message. 
  1458.   // 1    MAPI_TO    Indicates a primary message recipient. 
  1459.   // 2    MAPI_CC    Indicates a recipient of a message copy. 
  1460.   // 3    MAPI_BCC    Indicates a recipient of a blindcopy. 
  1461.   addrArray[arrayCount++] = CheckNull(messageClass);
  1462.  
  1463.   return(TRUE);
  1464. }
  1465.  
  1466. int               getAddressCount = 0;
  1467. MAPIAddressType   *getAddressPtr = NULL;
  1468. NSstringSeq       addrSeq = NULL;
  1469.  
  1470. // rhp - for MAPI calls...
  1471. BOOL
  1472. GetNextAddress(LPSTR *name, LPSTR *address, int *addrType)
  1473. {
  1474.   if ( getAddressCount >= (getAddressPtr->nRecips * 3) )
  1475.   {
  1476.     return FALSE;
  1477.   }
  1478.  
  1479.   ULONG   aType = atoi(NSStrSeqGet(addrSeq, getAddressCount++));
  1480.  
  1481.   // return which type of address this is?
  1482.   if (aType == MAPI_CC)
  1483.     *addrType = MSG_CC_HEADER_MASK;
  1484.   else if (aType == MAPI_BCC)
  1485.     *addrType = MSG_BCC_HEADER_MASK;
  1486.   else
  1487.     *addrType = MSG_TO_HEADER_MASK;
  1488.       
  1489.   *name    = (LPSTR) NSStrSeqGet(addrSeq, getAddressCount++);
  1490.   *address = (LPSTR) NSStrSeqGet(addrSeq, getAddressCount++);
  1491.  
  1492.   return TRUE;
  1493. }
  1494.  
  1495. LONG
  1496. ProcessMAPIAddress(MAPIAddressType *addrInfo)
  1497. {
  1498.   CMAPIConnection *mySession;
  1499.  
  1500.   TRACE("MAPI: ProcessMAPIAddress() Incomming Addrs = %d\nCaption = [%s]\n",
  1501.                     addrInfo->nRecips,
  1502.                     addrInfo->lpszCaption);
  1503.   //
  1504.   // Verify the session handle...
  1505.   //
  1506.   if (((addrInfo->lhSession-1) >= MAX_CON) || ((addrInfo->lhSession-1) < 0))
  1507.   {
  1508.     return(MAPI_E_INVALID_SESSION);
  1509.   }
  1510.  
  1511.   mySession = mapiConnections[(addrInfo->lhSession - 1)];
  1512.   if (mySession == NULL)
  1513.   {
  1514.     return(MAPI_E_INVALID_SESSION);
  1515.   }
  1516.  
  1517.   // 
  1518.   // Put up the address dialog and do the right thing :-)
  1519.   // 
  1520.   addrSeq = (NSstringSeq) &(addrInfo->dataBuf[0]);
  1521.   getAddressCount = 0;  // Make sure to reset the counter for address info...
  1522.   getAddressPtr = addrInfo; // Address pointer for callback...
  1523.   arrayCount = 0;       // counter for the rest of the entries...
  1524.   theApp.m_pHiddenFrame->AddressDialog((LPSTR) (addrInfo->lpszCaption), 
  1525.                                             AddressCallback, GetNextAddress);
  1526.  
  1527.   // If the address count is zero, then we can return early...
  1528.   addrInfo->nNewRecips = addressCount;
  1529.   if (addressCount == 0)
  1530.   {
  1531.     return(SUCCESS_SUCCESS);
  1532.   }
  1533.  
  1534.   addrArray[arrayCount] = NULL;  
  1535.  
  1536.   // Create the string sequence
  1537.   NSstringSeq strSeq = NSStrSeqNew(addrArray);
  1538.   
  1539.   // Now just cleanup the array....
  1540.   free(addrArray);
  1541.   
  1542.   if (!strSeq)
  1543.   {
  1544.     return(MAPI_E_INSUFFICIENT_MEMORY);
  1545.   }
  1546.   
  1547.   // Now get the name of the file to write the blob to!
  1548.   if (GetTempAttachmentName((LPSTR)addrInfo->lpszBlob) < 0)
  1549.   {
  1550.     NSStrSeqDelete(strSeq);
  1551.     return(MAPI_E_INSUFFICIENT_MEMORY);
  1552.   }
  1553.  
  1554.   // Now write the blob to disk and move on...
  1555.   if (WriteTheMemoryBufferToDisk((LPSTR) addrInfo->lpszBlob, 
  1556.                       (UINT) NSStrSeqSize(strSeq), strSeq) != 0)
  1557.   {
  1558.     NSStrSeqDelete(strSeq);
  1559.     return(MAPI_E_INSUFFICIENT_MEMORY);
  1560.   }
  1561.  
  1562.   NSStrSeqDelete(strSeq);
  1563.   return(SUCCESS_SUCCESS);
  1564. }
  1565.