Back to index

lightning-sunbird  0.9+nobinonly
mapi32.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 //
00038 //  Simple MAPI API
00039 //  Written by: Rich Pizzarro (rhp@netscape.com)
00040 //  November 1997
00041 //
00042 #include <windows.h>  
00043 #include <string.h> 
00044 
00045 #include "xpapi.h"
00046 #include "trace.h"
00047 #include "mapiipc.h"
00048 #include "mapiutl.h"
00049 #include "nsstrseq.h"
00050 #include "mapismem.h"
00051 #include "mapimem.h"
00052 
00053 #include "nscpmapi.h"
00054 
00055 #ifndef MAPI_OLE     // Because MSFT doesn't do this for us :-(
00056 #include "mapi.h"
00057 #endif
00058 
00059 //
00060 // Necessary variables...
00061 //
00062 memTrackerType    memArray[MAX_POINTERS];
00063 
00064 //
00065 // For remembering memory...how ironic.
00066 //
00067 void
00068 SetPointerArray(LPVOID ptr, BYTE type)
00069 {
00070 int i;
00071   
00072   for (i=0; i<MAX_POINTERS; i++)
00073   {
00074     if (memArray[i].lpMem == NULL)
00075     {
00076       memArray[i].lpMem = ptr;
00077       memArray[i].memType = type;
00078       break;
00079     }
00080   }
00081 }
00082 
00083 //
00084 // To have MAPI work in MS-Word on Win95, you must have 
00085 // this in win.ini:
00086 //
00087 // [Mail]
00088 // MAPIX=1
00089 //
00090 // To turn logging of errors on, set:
00091 // HKEY_LOCAL_MACHINE\Software\Netscape\Netscape Navigator\MAPI\Logging = 1
00092 
00093 // 
00094 // The MAPILogon function begins a Simple MAPI session, loading 
00095 // the default message store and address book providers. 
00096 //
00097 MAPI_IMPLEMENT(ULONG) 
00098 MAPILogon(
00099     ULONG ulUIParam,
00100     LPSTR lpszProfileName,
00101     LPSTR lpszPassword,
00102     FLAGS flFlags,
00103     ULONG ulReserved,
00104     LPLHANDLE lplhSession)
00105 {
00106 LRESULT       result;
00107 HWND          hWndIPC;
00108 MAPIIPCType   ipcInfo;
00109 static BOOL   firstTime = TRUE;
00110 
00111        TRACE_FN("MAPILogon");
00112        TRACE("  lpszProfileName=%s, lpszPassword=%s\n", lpszProfileName, lpszPassword);  
00113 #ifndef WIN16
00114        TRACE("  threadID = %ld\n", GetCurrentThreadId()); 
00115 #endif
00116 
00117   // Init before we start...
00118   *lplhSession = 0;
00119 
00120   TRACE("MAPILogon: SET RETURN SESSION TO NULL\n"); 
00121 
00122   //
00123   // Check if diags should be turned on or off...
00124   //
00125   DWORD val = 0;
00126   if (GetConfigInfoNum(szMapiSection, "Logging", &val, HKEY_LOCAL_MACHINE))
00127   {
00128               SetLoggingEnabled((BOOL)val);
00129   }
00130   
00131   //
00132   // Init the stuff we will need for WM_COPYDATA calls and anything else
00133   //
00134   if (!nsMAPI_OpenAPI())
00135   {
00136     TRACE("MAPILogon: Can't open API\n"); 
00137     return(MAPI_E_FAILURE);
00138   }
00139 
00140   //
00141   // This call locates a Communicator Window, if one is not running,
00142   // it will start up an instance of Communicator and grab that window.
00143   //
00144   hWndIPC = GetCommunicatorIPCWindow();
00145   if (NULL == hWndIPC)
00146   {
00147     TRACE("MAPILogon: Can't get Window\n"); 
00148     return(MAPI_E_FAILURE);
00149   }
00150 
00151   //
00152   // Reset the pointer arrary for future use.
00153   //
00154   if (firstTime)
00155   {
00156     TRACE("MAPILogon: Reset Pointer\n"); 
00157     memset(memArray, 0, sizeof(memTrackerType) * MAX_POINTERS);
00158     firstTime = FALSE;
00159   }
00160 
00161   // 
00162   // Build the IPC structure of information that needs to be provided
00163   // to get information into Communicator
00164   //
00165   BuildMemName((LPSTR)ipcInfo.smemName, ulUIParam);
00166 
00167   //
00168   // Build the shared memory segment of information to pass into 
00169   // Communicator for the login call.
00170   //
00171   LPSTR       strings[3];
00172   NSstringSeq strSeq;
00173   CSharedMem  *sMem;
00174   DWORD       memSize;
00175   LONG        strSize;
00176   HANDLE      hSharedMemory;
00177   MAPILogonType   logonInfo;
00178 
00179   strings[0] = CheckNullString(lpszProfileName);
00180   strings[1] = CheckNullString(lpszPassword);
00181   strings[2] = NULL;
00182   strSeq     = NSStrSeqNew(strings);
00183   strSize    = NSStrSeqSize(strSeq);
00184   memSize = sizeof(MAPILogonType) + strSize;
00185 
00186   //
00187   // Create the shared memory...
00188   //
00189   sMem = NSCreateSharedMemory(memSize, (LPSTR) ipcInfo.smemName, &hSharedMemory);
00190   if (!sMem)
00191   {
00192       TRACE("MAPILogon: SMEM Failure\n"); 
00193       NSStrSeqDelete(strSeq);
00194       return(MAPI_E_INSUFFICIENT_MEMORY);
00195   }
00196 
00197   //
00198   // Now populate a Logon structure with the passed in information
00199   //
00200   logonInfo.ulUIParam = ulUIParam;
00201   logonInfo.flFlags = flFlags;
00202   logonInfo.lhSession = 0;
00203   logonInfo.ipcWorked = 0;
00204 
00205   //
00206   // Now copy the information into the memory segment.
00207   //
00208   sMem->m_dwSize = memSize;
00209   memcpy(sMem->m_buf, &(logonInfo), sizeof(MAPILogonType));
00210   memcpy(sMem->m_buf + sizeof(MAPILogonType), strSeq, (size_t) strSize);
00211 
00212   //
00213   // Now set the size of the shared memory segment for the 
00214   // WM_COPYDATA argument that will be sent across.
00215   //
00216   ipcInfo.smemSize = memSize;
00217 
00218   // For Win16, we actually pass in the pointer to the structure,
00219   // so just assign the variable here.
00220 #ifdef WIN16
00221   ipcInfo.lpsmem = sMem;
00222 #else
00223   ipcInfo.lpsmem = NULL;
00224 #endif
00225 
00226   //
00227   // Ok, time to do the SendMessage() to Communicator...
00228   //
00229   result = SendMAPIRequest(hWndIPC, NSCP_MAPILogon, &ipcInfo);
00230 
00231   // Check for IPC completion
00232   MAPILogonType *logInfo = (MAPILogonType *) &(sMem->m_buf[0]);  
00233   if (!logInfo->ipcWorked)
00234   {
00235     result = MAPI_E_FAILURE;
00236   }
00237 
00238   // 
00239   // If successfull, then we need to get the information
00240   if (result == SUCCESS_SUCCESS)
00241   {
00242     *lplhSession = logInfo->lhSession;
00243   }
00244 
00245   //
00246   // Now time to do some cleanup...
00247   //
00248   NSStrSeqDelete(strSeq);
00249   NSCloseSharedMemory(sMem, hSharedMemory);
00250 
00251   CleanupMAPITempFiles();
00252        TRACE("  Returning lhSession=%lu\n", *lplhSession);
00253        LogString("--MAPILogon complete\r\n");
00254 
00255        return(result);
00256 }
00257 
00258 //
00259 // The MAPILogoff function ends a session with the messaging system. 
00260 //
00261 MAPI_IMPLEMENT(ULONG) 
00262 MAPILogoff(
00263     LHANDLE lhSession,
00264     ULONG ulUIParam,
00265     FLAGS flFlags,
00266     ULONG ulReserved)
00267 {
00268 LRESULT       result;
00269 HWND          hWndIPC;
00270 MAPIIPCType   ipcInfo;
00271 
00272        TRACE_FN("MAPILogoff");
00273        TRACE("lhSession Session ID = %lu\n", lhSession);
00274        LogString("--MAPILogoff\r\n");
00275 
00276   //
00277   // This call locates a Communicator Window, if one is not running,
00278   // it will start up an instance of Communicator and grab that window.
00279   //
00280   hWndIPC = GetCommunicatorIPCWindow();
00281   if (NULL == hWndIPC)
00282   {
00283     return(MAPI_E_FAILURE);
00284   }
00285 
00286   // 
00287   // Build the IPC structure of information that needs to be provided
00288   // to get information into Communicator
00289   //
00290   BuildMemName((LPSTR)ipcInfo.smemName, ulUIParam);
00291 
00292   //
00293   // Build the shared memory segment of information to pass into 
00294   // Communicator for the login call.
00295   //
00296   CSharedMem      *sMem;
00297   DWORD           memSize;
00298   HANDLE          hSharedMemory;
00299   MAPILogoffType  logoffInfo;
00300    
00301   memSize = sizeof(MAPILogoffType);
00302 
00303   //
00304   // Create the shared memory...
00305   //
00306   sMem = NSCreateSharedMemory(memSize, (LPSTR) ipcInfo.smemName, &hSharedMemory);
00307   if (!sMem)
00308   {
00309       return(MAPI_E_INSUFFICIENT_MEMORY);
00310   }
00311 
00312   //
00313   // Now populate a Logon structure with the passed in information
00314   //
00315   logoffInfo.lhSession  = lhSession;
00316   logoffInfo.ulUIParam  = ulUIParam;
00317   logoffInfo.flFlags    = flFlags;
00318   logoffInfo.ipcWorked  = 0;
00319 
00320   //
00321   // Now copy the information into the memory segment.
00322   //
00323   sMem->m_dwSize = memSize;
00324   memcpy(sMem->m_buf, &(logoffInfo), sizeof(MAPILogoffType));
00325 
00326   //
00327   // Now set the size of the shared memory segment for the 
00328   // WM_COPYDATA argument that will be sent across.
00329   //
00330   ipcInfo.smemSize = memSize;
00331 
00332   // For Win16, we actually pass in the pointer to the structure,
00333   // so just assign the variable here.
00334 #ifdef WIN16
00335   ipcInfo.lpsmem = sMem;
00336 #else
00337   ipcInfo.lpsmem = NULL;
00338 #endif
00339 
00340   //
00341   // Ok, time to do the SendMessage() to Communicator...
00342   //
00343   result = SendMAPIRequest(hWndIPC, NSCP_MAPILogoff, &ipcInfo);
00344 
00345   // Check for IPC completion
00346   MAPILogoffType *logInfo = (MAPILogoffType *) &(sMem->m_buf[0]);
00347   if (!logInfo->ipcWorked)
00348   {
00349       result = MAPI_E_FAILURE;
00350   }
00351 
00352   //
00353   // Now do cleanup on the way out...
00354   //
00355   NSCloseSharedMemory(sMem, hSharedMemory);
00356 
00357   //
00358   // Close the stuff for WM_COPYDATA calls and anything else
00359   //
00360   nsMAPI_CloseAPI();
00361 
00362        LogString("--MAPILogoff complete\r\n");
00363 
00364   CleanupMAPITempFiles();
00365 
00366   // Now just return!
00367   return(result);
00368 }
00369 
00370 //
00371 // The MAPIFreeBuffer function frees a memory buffer allocated with a call to 
00372 // the MAPIAllocateBuffer function or the MAPIAllocateMore function. 
00373 //
00374 MAPI_IMPLEMENT(ULONG) 
00375 MAPIFreeBuffer(LPVOID pv)
00376 {
00377 int   i;
00378 
00379   TRACE_FN("MAPIFreeBuffer");
00380 
00381   if (!pv)
00382 #ifdef WIN16     
00383        return(SUCCESS_SUCCESS);
00384 #else
00385        return(S_OK);
00386 #endif
00387 
00388   for (i=0; i<MAX_POINTERS; i++)
00389   {
00390     if (pv == memArray[i].lpMem)
00391     {
00392       if (memArray[i].memType == MAPI_MESSAGE_TYPE)
00393       {
00394         FreeMAPIMessage((MapiMessage *)pv);
00395         memArray[i].lpMem = NULL;
00396       }
00397       else if (memArray[i].memType == MAPI_RECIPIENT_TYPE)
00398       {
00399         FreeMAPIRecipient((MapiRecipDesc *)pv);
00400         memArray[i].lpMem = NULL;
00401       }
00402     }
00403   }
00404 
00405   pv = NULL;
00406 #ifdef WIN16     
00407        return(SUCCESS_SUCCESS);
00408 #else
00409        return(S_OK);
00410 #endif
00411 }
00412 
00413 //
00414 // The MAPISendMail function sends a message. This function differs 
00415 // from the MAPISendDocuments function in that it allows greater 
00416 // flexibility in message generation. 
00417 //
00418 MAPI_IMPLEMENT(ULONG) 
00419 MAPISendMail(
00420              LHANDLE lhSession, 
00421              ULONG UIParam, 
00422              lpMapiMessage lpMessage, 
00423              FLAGS flags, 
00424              ULONG ulReserved)
00425 {  
00426 #ifdef _DEBUG
00427        TRACE_FN("MapiSendMail");
00428        TRACE("  lhSession=%lu\n", lhSession);
00429        if (lpMessage)
00430        {
00431               TRACE("  lpMessage->lpszSubject = '%s'\n", lpMessage->lpszSubject);
00432               TRACE("  lpMessage->nRecipCount = %lu\n  lpMessage->nFileCount=%lu\n", lpMessage->nRecipCount, lpMessage->nFileCount);
00433               lpMapiFileDesc pFiles = lpMessage->lpFiles;
00434               for (ULONG i = 0; i < lpMessage->nFileCount; i++)
00435               {
00436                      TRACE("    lpszPathName='%s', lpszFileName='%s'\n", pFiles[i].lpszPathName, pFiles[i].lpszFileName);
00437               }
00438        }
00439 #endif
00440   CleanupMAPITempFiles();
00441 
00442   //
00443   // Needed variables...
00444   //
00445   BOOL          isTempSession = FALSE;
00446   LONG          result = SUCCESS_SUCCESS;
00447   HWND          hWndIPC;
00448   MAPIIPCType   ipcInfo;
00449 
00450        if (!lpMessage)
00451        {
00452               return(MAPI_E_FAILURE);
00453        }
00454 
00455   //
00456   // Sanity Check the attachments if any here...
00457   //
00458   if (lpMessage->nFileCount > 0)
00459   {
00460     DWORD rc = SanityCheckAttachmentFiles(lpMessage);  // return of zero is ok
00461     if (rc == 1)
00462     {
00463       return(MAPI_E_ATTACHMENT_NOT_FOUND);
00464     }
00465     else if (rc == 2)
00466     {
00467       return(MAPI_E_ATTACHMENT_OPEN_FAILURE);
00468     }
00469   }
00470 
00471   //
00472   // If lhSession is ZERO, then we have to get a temporary session and
00473   // go from there.
00474   //
00475   if (lhSession == 0)
00476   {
00477     LHANDLE    lhTempSession;
00478     if (MAPILogon(0, NULL, NULL, 0, 0, &lhTempSession) != SUCCESS_SUCCESS)
00479     {
00480       isTempSession = TRUE;
00481       if (MAPILogon(0, "dummy", "dummy", 0, 0, &lhTempSession) != SUCCESS_SUCCESS)
00482       {
00483         return(MAPI_E_LOGIN_FAILURE);
00484       }
00485     }
00486 
00487     lhSession = lhTempSession;
00488   }
00489 
00490   //
00491   // Now create the big chunk of memory that we will pass across which
00492   // represents the message
00493   //
00494   DWORD               totalSize;
00495   MAPISendMailType    *memToPass = NULL;
00496 
00497   memToPass = (MAPISendMailType *) FlattenMAPIMessageStructure(lpMessage, &totalSize);
00498   if (!memToPass)
00499   {
00500       if (isTempSession)
00501       {
00502         MAPILogoff(lhSession, 0, 0, 0);
00503       }
00504       
00505       return(MAPI_E_INSUFFICIENT_MEMORY);
00506   }
00507 
00508   memToPass->lhSession = lhSession;
00509   memToPass->ulUIParam = UIParam;
00510   memToPass->flFlags = flags;
00511   memToPass->ipcWorked = 0;
00512 
00513   //
00514   // This call locates a Communicator Window, if one is not running,
00515   // it will start up an instance of Communicator and grab that window.
00516   //
00517   hWndIPC = GetCommunicatorIPCWindow();
00518   if (NULL == hWndIPC)
00519   {
00520     free(memToPass);
00521     if (isTempSession)
00522     {
00523       MAPILogoff(lhSession, 0, 0, 0);
00524     }
00525     return(MAPI_E_FAILURE);
00526   }
00527 
00528   // 
00529   // Build the IPC structure of information that needs to be provided
00530   // to get information into Communicator
00531   //
00532   BuildMemName((LPSTR)ipcInfo.smemName, UIParam);
00533 
00534   //
00535   // Build the shared memory segment of information to pass into 
00536   // Communicator for send message call.
00537   //
00538   CSharedMem      *sMem;
00539   HANDLE          hSharedMemory;
00540 
00541   //
00542   // Create the shared memory...
00543   //
00544   sMem = NSCreateSharedMemory(totalSize, (LPSTR) ipcInfo.smemName, &hSharedMemory);
00545   if (!sMem)
00546   {
00547       free(memToPass);
00548       if (isTempSession)
00549       {
00550         MAPILogoff(lhSession, 0, 0, 0);
00551       }
00552       return(MAPI_E_INSUFFICIENT_MEMORY);
00553   }
00554 
00555   //
00556   // Now copy the information into the memory segment.
00557   //
00558   sMem->m_dwSize = totalSize;
00559   memcpy(sMem->m_buf, memToPass, (size_t) totalSize);
00560 
00561   //
00562   // Now set the size of the shared memory segment for the 
00563   // WM_COPYDATA argument that will be sent across.
00564   //
00565   ipcInfo.smemSize = totalSize;
00566 
00567   // For Win16, we actually pass in the pointer to the structure,
00568   // so just assign the variable here.
00569 #ifdef WIN16
00570   ipcInfo.lpsmem = sMem;
00571 #else
00572   ipcInfo.lpsmem = NULL;
00573 #endif
00574 
00575   //
00576   // Ok, time to do the SendMessage() to Communicator...
00577   //
00578   result = SendMAPIRequest(hWndIPC, NSCP_MAPISendMail, &ipcInfo);
00579 
00580   // Check for IPC completion
00581   MAPISendMailType *ptr = (MAPISendMailType *) &(sMem->m_buf[0]);
00582   if (!ptr->ipcWorked)
00583   {
00584     result = MAPI_E_FAILURE;
00585   }
00586 
00587   //
00588   // Now time to do some cleanup...
00589   //
00590   NSCloseSharedMemory(sMem, hSharedMemory);
00591   free(memToPass);
00592 
00593        LogString("--MAPISendMail complete\r\n");
00594 
00595   //
00596   // If we created a temp session, then we need to trash it...
00597   //
00598   if (isTempSession)
00599   {
00600     MAPILogoff(lhSession, 0, 0, 0);
00601   }
00602 
00603   return(result);
00604 }
00605 
00606 //
00607 // The MAPISendDocuments function sends a standard message with one or more attached 
00608 // files and a cover note. The cover note is a dialog box that allows the user to 
00609 // enter a list of recipients and an optional message. MAPISendDocuments differs 
00610 // from the MAPISendMail function in that it allows less flexibility in message generation. 
00611 //
00612 void
00613 CleanupStringArray(LPSTR *strArray, DWORD arraySize)
00614 {
00615   DWORD   i;
00616 
00617   if (strArray == NULL)
00618     return;
00619 
00620   for (i=0; i<arraySize; i++)
00621   {
00622     if (strArray[i] != NULL)
00623     {
00624       free(strArray[i]);
00625       strArray[i] = NULL;
00626     }
00627   }
00628   
00629   free(strArray);
00630   strArray = NULL;
00631 }
00632 
00633 MAPI_IMPLEMENT(ULONG) MAPISendDocuments(
00634     ULONG ulUIParam,
00635     LPSTR lpszDelimChar,
00636     LPSTR lpszFilePaths,
00637     LPSTR lpszFileNames,
00638     ULONG ulReserved)
00639 {
00640   TRACE_FN("MAPISendDocuments");
00641   TRACE("MAPI: MAPISendDocuments() FilePaths: %s\n", lpszFilePaths);
00642   TRACE("MAPI: MAPISendDocuments() FileNames: %s\n", lpszFileNames);
00643   TRACE("MAPI: MAPISendDocuments() Delim    : [%s]\n", lpszDelimChar);
00644 
00645   CleanupMAPITempFiles();
00646 
00647   //
00648   // Needed variables...
00649   //
00650   LONG          result = SUCCESS_SUCCESS;
00651   HWND          hWndIPC;
00652 
00653        if (!lpszFilePaths) 
00654        {
00655               return(MAPI_E_FAILURE);
00656        }
00657 
00658   //
00659   // Sanity Check the attachments here...
00660   //
00661   DWORD aCount = GetFileCount(lpszFilePaths, lpszDelimChar);
00662   DWORD reallyFound = 0;
00663   DWORD i;
00664   BYTE  szFileName[_MAX_PATH];
00665   BYTE  szNewFileName[_MAX_PATH];
00666   BYTE  szReadableName[_MAX_PATH];
00667 
00668   LPSTR *strArray = (LPSTR *) malloc((size_t) (sizeof(LPSTR) * ((aCount * 2) + 1)));
00669   if (!strArray)
00670   {
00671     return(MAPI_E_INSUFFICIENT_MEMORY);
00672   }
00673 
00674   memset(strArray, 0, (size_t) (sizeof(LPSTR) * ((aCount * 2) + 1)));
00675   for (i=0; i<aCount; i++)
00676   {
00677     if (ExtractFile(lpszFilePaths, lpszDelimChar, i, (LPSTR)szFileName))  // true=found
00678     {
00679       if (ValidateFile((LPSTR)szFileName) != 0)
00680       {
00681         CleanupStringArray(strArray, reallyFound);
00682         return(MAPI_E_ATTACHMENT_OPEN_FAILURE);
00683       }
00684 
00685       //
00686       // Now get the matching name for this file!
00687       //
00688       if (!ExtractFile(lpszFileNames, lpszDelimChar, i, (LPSTR)szReadableName))  // true=found
00689       {
00690         lstrcpy((char *)szReadableName, (char *)szFileName);
00691       }
00692 
00693       if (GetTempMailNameWithExtension((char *)szNewFileName, (char *)szReadableName) == 0)
00694       {
00695         CleanupStringArray(strArray, reallyFound);
00696         return(MAPI_E_ATTACHMENT_OPEN_FAILURE);
00697       }
00698 
00699       if (!XP_CopyFile((char *)szFileName, (char *)szNewFileName, TRUE))
00700       {
00701         CleanupStringArray(strArray, reallyFound);
00702         return(MAPI_E_ATTACHMENT_WRITE_FAILURE);
00703       }
00704 
00705       AddTempFile((LPSTR) szNewFileName);
00706 
00707       strArray[reallyFound++] = strdup((LPSTR)szNewFileName);
00708       strArray[reallyFound++] = strdup((LPSTR)szReadableName);
00709     }
00710   }
00711 
00712   // Set last entry to null...again
00713   strArray[reallyFound] = NULL;
00714 
00715   // Check that we created an even matching pair, otherwise bail!
00716   if ((reallyFound % 2) != 0)
00717   {
00718     CleanupStringArray(strArray, reallyFound);
00719     return(MAPI_E_ATTACHMENT_OPEN_FAILURE);
00720   }
00721 
00722   MAPISendDocumentsType   docType;
00723   MAPISendDocumentsType   *memToPass = NULL;
00724   NSstringSeq             strSeq;
00725   DWORD                   memSize;
00726   LONG                    strSize;
00727   MAPIIPCType             ipcInfo;
00728 
00729   // Start setting up the MAPISendDocumentsType structure to pass to communicator
00730   docType.nFileCount   = reallyFound/2;
00731   docType.ulUIParam    = ulUIParam;
00732   docType.ipcWorked     = 0;
00733   strSeq               = NSStrSeqNew(strArray);
00734   if (!strSeq)
00735   {
00736     CleanupStringArray(strArray, reallyFound);
00737     return(MAPI_E_INSUFFICIENT_MEMORY);
00738   }
00739 
00740   // Cleanup strArray... 
00741   CleanupStringArray(strArray, reallyFound);
00742 
00743   strSize = NSStrSeqSize(strSeq);
00744   memSize = sizeof(MAPISendDocumentsType) + strSize; 
00745  
00746   //
00747   // Now create the big chunk of memory that we will pass across which
00748   // represents attached files...
00749   //
00750   memToPass = (MAPISendDocumentsType *)malloc((size_t) memSize);
00751   if (!memToPass)
00752   {
00753     NSStrSeqDelete(strSeq);
00754     return(MAPI_E_INSUFFICIENT_MEMORY);
00755   }
00756             
00757   // Null out the new memory...
00758   memset(memToPass, 0, (size_t) memSize);
00759             
00760   // Copy in the actual data to the real chunk of memory...
00761   memcpy(memToPass, &docType, sizeof(MAPISendDocumentsType));
00762   memcpy(&(memToPass->dataBuf[0]), strSeq, (size_t) strSize);
00763 
00764   // Cleanup sequence...
00765   NSStrSeqDelete(strSeq);
00766 
00767   //
00768   // This call locates a Communicator Window, if one is not running,
00769   // it will start up an instance of Communicator and grab that window.
00770   //
00771   hWndIPC = GetCommunicatorIPCWindow();
00772   if (NULL == hWndIPC)
00773   {
00774     free(memToPass);
00775     return(MAPI_E_FAILURE);
00776   }
00777 
00778   // 
00779   // Build the IPC structure of information that needs to be provided
00780   // to get information into Communicator
00781   //
00782   BuildMemName((LPSTR)ipcInfo.smemName, ulUIParam);
00783 
00784   //
00785   // Build the shared memory segment of information to pass into 
00786   // Communicator for send message call.
00787   //
00788   CSharedMem      *sMem;
00789   HANDLE          hSharedMemory;
00790 
00791   //
00792   // Create the shared memory...
00793   //
00794   sMem = NSCreateSharedMemory(memSize, (LPSTR) ipcInfo.smemName, &hSharedMemory);
00795   if (!sMem)
00796   {
00797       free(memToPass);
00798       return(MAPI_E_INSUFFICIENT_MEMORY);
00799   }
00800 
00801   //
00802   // Now copy the information into the memory segment.
00803   //
00804   sMem->m_dwSize = memSize;
00805   memcpy(sMem->m_buf, memToPass, (size_t) memSize);
00806 
00807   //
00808   // Now set the size of the shared memory segment for the 
00809   // WM_COPYDATA argument that will be sent across.
00810   //
00811   ipcInfo.smemSize = memSize;
00812 
00813   // For Win16, we actually pass in the pointer to the structure,
00814   // so just assign the variable here.
00815 #ifdef WIN16
00816   ipcInfo.lpsmem = sMem;
00817 #else
00818   ipcInfo.lpsmem = NULL;
00819 #endif
00820 
00821   //
00822   // Ok, time to do the SendMessage() to Communicator...
00823   //
00824   result = SendMAPIRequest(hWndIPC, NSCP_MAPISendDocuments, &ipcInfo);
00825 
00826   MAPISendDocumentsType *ptr = (MAPISendDocumentsType *) &(sMem->m_buf[0]);
00827   if (!ptr->ipcWorked)
00828   {
00829     result = MAPI_E_FAILURE;
00830   }
00831 
00832   //
00833   // Now time to do some cleanup...
00834   //
00835   NSCloseSharedMemory(sMem, hSharedMemory);
00836   free(memToPass);
00837 
00838        LogString("--MAPISendDocuments() complete\r\n");
00839   return(result);
00840 }
00841 
00842 MAPI_IMPLEMENT(ULONG) 
00843 MAPIFindNext(
00844     LHANDLE lhSession,
00845     ULONG ulUIParam,
00846     LPSTR lpszMessageType,
00847     LPSTR lpszSeedMessageID,
00848     FLAGS flFlags,
00849     ULONG ulReserved,
00850     LPSTR lpszMessageID)
00851 {
00852 LRESULT       result;
00853 HWND          hWndIPC;
00854 MAPIIPCType   ipcInfo;
00855 LPSTR         tempSeedString = "";
00856 
00857        TRACE_FN("MAPIFindNext");
00858   if (lhSession == 0)
00859   {
00860     return(MAPI_E_INVALID_SESSION);
00861   }
00862 
00863   if (lpszSeedMessageID)
00864   {
00865     if (strlen(lpszSeedMessageID) > 511)
00866     {
00867       return(MAPI_E_INSUFFICIENT_MEMORY);
00868     }
00869   }
00870   else
00871   {
00872     lpszSeedMessageID = tempSeedString;
00873   }
00874 
00875        TRACE("MAPIFindNext lhSession Session ID = %lu\n", lhSession);
00876 
00877   //
00878   // This call locates a Communicator Window, if one is not running,
00879   // it will start up an instance of Communicator and grab that window.
00880   //
00881   hWndIPC = GetCommunicatorIPCWindow();
00882   if (NULL == hWndIPC)
00883   {
00884     return(MAPI_E_FAILURE);
00885   }
00886 
00887   // 
00888   // Build the IPC structure of information that needs to be provided
00889   // to get information into Communicator
00890   //
00891   BuildMemName((LPSTR)ipcInfo.smemName, ulUIParam);
00892 
00893   //
00894   // Build the shared memory segment of information to pass into 
00895   // Communicator for the login call.
00896   //
00897   CSharedMem        *sMem;
00898   DWORD             memSize;
00899   HANDLE            hSharedMemory;
00900   MAPIFindNextType  findInfo;
00901    
00902   memSize = sizeof(MAPIFindNextType);
00903 
00904   //
00905   // Create the shared memory...
00906   //
00907   sMem = NSCreateSharedMemory(memSize, (LPSTR) ipcInfo.smemName, &hSharedMemory);
00908   if (!sMem)
00909   {
00910       return(MAPI_E_INSUFFICIENT_MEMORY);
00911   }
00912 
00913   //
00914   // Now populate a Logon structure with the passed in information
00915   //
00916   findInfo.lhSession  = lhSession;
00917   findInfo.ulUIParam  = ulUIParam;
00918   findInfo.flFlags    = flFlags;
00919   findInfo.ipcWorked  = 0;
00920 
00921   //
00922   // Copy the seed value in the structure
00923   //
00924   strcpy((LPSTR) findInfo.lpszSeedMessageID, lpszSeedMessageID);
00925 
00926   //
00927   // Now copy the information into the memory segment.
00928   //
00929   sMem->m_dwSize = memSize;
00930   memcpy(sMem->m_buf, &(findInfo), sizeof(MAPIFindNextType));
00931 
00932   //
00933   // Now set the size of the shared memory segment for the 
00934   // WM_COPYDATA argument that will be sent across.
00935   //
00936   ipcInfo.smemSize = memSize;
00937 
00938   // For Win16, we actually pass in the pointer to the structure,
00939   // so just assign the variable here.
00940 #ifdef WIN16
00941   ipcInfo.lpsmem = sMem;
00942 #else
00943   ipcInfo.lpsmem = NULL;
00944 #endif
00945 
00946   //
00947   // Ok, time to do the SendMessage() to Communicator...
00948   //
00949   result = SendMAPIRequest(hWndIPC, NSCP_MAPIFindNext, &ipcInfo);
00950 
00951   // Check for IPC completion
00952   MAPIFindNextType *findNextInfo = (MAPIFindNextType *) &(sMem->m_buf[0]);
00953   if (!findNextInfo->ipcWorked)
00954   {
00955     result = MAPI_E_FAILURE;
00956   }
00957 
00958   //
00959   // Now return the value to the caller...
00960   //
00961   if (result == SUCCESS_SUCCESS)
00962   {
00963     strcpy(lpszMessageID, (LPSTR) findNextInfo->lpszMessageID);
00964   }
00965 
00966   //
00967   // Now do cleanup on the way out...
00968   //
00969   NSCloseSharedMemory(sMem, hSharedMemory);
00970        LogString("--MAPIFindNext complete\r\n");
00971        return(result);
00972 }
00973 
00974 MAPI_IMPLEMENT(ULONG) 
00975 MAPIReadMail(
00976     LHANDLE lhSession,
00977     ULONG ulUIParam,
00978     LPSTR lpszMessageID,
00979     FLAGS flFlags,
00980     ULONG ulReserved,
00981     lpMapiMessage FAR *lppMessage)
00982 {
00983 LRESULT       result;
00984 HWND          hWndIPC;
00985 MAPIIPCType   ipcInfo;
00986 
00987        TRACE_FN("MAPIReadMail");
00988   //
00989   // This one has to have a valid session handle, or we bail!
00990   // 
00991   if (lhSession == 0)
00992   {
00993     return(MAPI_E_INVALID_SESSION);
00994   }
00995 
00996   if (strlen(lpszMessageID) > 511)
00997   {
00998     return(MAPI_E_INSUFFICIENT_MEMORY);
00999   }
01000 
01001   //
01002   // This call locates a Communicator Window, if one is not running,
01003   // it will start up an instance of Communicator and grab that window.
01004   //
01005   hWndIPC = GetCommunicatorIPCWindow();
01006   if (NULL == hWndIPC)
01007   {
01008     return(MAPI_E_FAILURE);
01009   }
01010 
01011   // 
01012   // Build the IPC structure of information that needs to be provided
01013   // to get information into Communicator
01014   //
01015   BuildMemName((LPSTR)ipcInfo.smemName, ulUIParam);
01016 
01017   //
01018   // Build the shared memory segment of information to pass into 
01019   // Communicator for the login call.
01020   //
01021   CSharedMem        *sMem;
01022   DWORD             memSize;
01023   HANDLE            hSharedMemory;
01024   MAPIReadMailType  readMailInfo;
01025    
01026   memSize = sizeof(MAPIReadMailType);
01027   memset(&readMailInfo, 0, (size_t) memSize);
01028 
01029   //
01030   // Create the shared memory...
01031   //
01032   sMem = NSCreateSharedMemory(memSize, (LPSTR) ipcInfo.smemName, &hSharedMemory);
01033   if (!sMem)
01034   {
01035       return(MAPI_E_INSUFFICIENT_MEMORY);
01036   }
01037 
01038   //
01039   // Now populate a Logon structure with the passed in information
01040   //
01041   readMailInfo.lhSession  = lhSession;
01042   readMailInfo.ulUIParam  = ulUIParam;
01043   readMailInfo.flFlags    = flFlags;
01044   readMailInfo.ipcWorked  = 0;
01045 
01046   //
01047   // Copy the seed value in the structure
01048   //
01049   strcpy((LPSTR) readMailInfo.lpszMessageID, lpszMessageID);
01050 
01051   //
01052   // Now copy the information into the memory segment.
01053   //
01054   sMem->m_dwSize = memSize;
01055   memcpy(sMem->m_buf, &(readMailInfo), sizeof(MAPIReadMailType));
01056 
01057   //
01058   // Now set the size of the shared memory segment for the 
01059   // WM_COPYDATA argument that will be sent across.
01060   //
01061   ipcInfo.smemSize = memSize;
01062 
01063   // For Win16, we actually pass in the pointer to the structure,
01064   // so just assign the variable here.
01065 #ifdef WIN16
01066   ipcInfo.lpsmem = sMem;
01067 #else
01068   ipcInfo.lpsmem = NULL;
01069 #endif
01070 
01071   //
01072   // Ok, time to do the SendMessage() to Communicator...
01073   //
01074   result = SendMAPIRequest(hWndIPC, NSCP_MAPIReadMail, &ipcInfo);
01075 
01076   // Check the IPC status...
01077   MAPIReadMailType *rMailPtr = (MAPIReadMailType *) &(sMem->m_buf[0]);
01078 
01079   //
01080   // Now return the value to the caller if we bombed...
01081   //
01082   if ((result != SUCCESS_SUCCESS) || (!(rMailPtr->ipcWorked)))
01083   {
01084     NSCloseSharedMemory(sMem, hSharedMemory);
01085          LogString("--MAPIReadMail failed\r\n");
01086          return(result);
01087   }
01088 
01089   // Now get a hold of the various values for the message we need to 
01090   // return in the lpMapiMessage structure
01091 
01092   if (rMailPtr->MSG_nRecipCount == 0)
01093   {
01094     NSCloseSharedMemory(sMem, hSharedMemory);
01095          LogString("--MAPIReadMail failed - ZERO recipients\r\n");
01096          return(MAPI_E_FAILURE);
01097   }
01098 
01099   //
01100   // Get the blob loaded into memory...
01101   // 
01102   NSstringSeq blobSequence = (NSstringSeq) LoadBlobToMemory((LPSTR) rMailPtr->lpszBlob);
01103 
01104   // Now check on the blob
01105   if (!blobSequence)
01106   {      
01107     // Cleanup the shared memory...
01108     NSCloseSharedMemory(sMem, hSharedMemory);
01109     return(MAPI_E_INSUFFICIENT_MEMORY);
01110   }
01111 
01112   lpMapiMessage  msgPtr = (MapiMessage *)malloc(sizeof(MapiMessage));
01113   if (msgPtr == NULL)
01114   {
01115     // Cleanup the shared memory...
01116     NSCloseSharedMemory(sMem, hSharedMemory);
01117     NSStrSeqDelete(blobSequence);
01118          LogString("--MAPIReadMail failed\r\n");
01119          return(MAPI_E_INSUFFICIENT_MEMORY);
01120   }
01121   
01122   memset(msgPtr, 0, sizeof(MapiMessage)); 
01123 
01124   //
01125   // At this point, we need to populate the structure of information
01126   // we are passing back via the *lppMessage and then start parsing through the
01127   // String sequence for each of needed fields. After populating the entire 
01128   // structure, return this pointer and our job on this side is done!
01129   //
01130   LPSTR   subject = NSStrSeqGet(blobSequence, 0);
01131   LPSTR   noteText = NSStrSeqGet(blobSequence, 1);
01132   LPSTR   dateReceived = NSStrSeqGet(blobSequence, 2);
01133   LPSTR   threadID = NSStrSeqGet(blobSequence, 3);
01134   LPSTR   origName = NSStrSeqGet(blobSequence, 4);
01135   LPSTR   origAddress = NSStrSeqGet(blobSequence, 5);
01136 
01137   UINT    i;
01138   ULONG   stringCount = 6;      // This is to start with the rest of the string seq
01139 
01140   // Set all of the general header information first!
01141   msgPtr->lpszSubject = strdup(CheckNullString(subject));
01142   msgPtr->lpszDateReceived = strdup(CheckNullString(dateReceived));
01143   msgPtr->lpszConversationID = strdup(CheckNullString(threadID));
01144   msgPtr->flFlags = rMailPtr->MSG_flFlags;
01145   
01146   // Setup the originator information!
01147   msgPtr->lpOriginator = (lpMapiRecipDesc) malloc(sizeof(MapiRecipDesc));
01148   if (!msgPtr->lpOriginator)
01149   {
01150     // Cleanup the shared memory...
01151     NSCloseSharedMemory(sMem, hSharedMemory);
01152 
01153     FreeMAPIMessage(msgPtr);
01154     NSStrSeqDelete(blobSequence);
01155          LogString("--MAPIReadMail failed\r\n");
01156          return(MAPI_E_INSUFFICIENT_MEMORY);
01157   }
01158 
01159   // memset the area just allocated to null
01160   memset(msgPtr->lpOriginator, 0, sizeof(MapiRecipDesc));
01161 
01162   msgPtr->lpOriginator->lpszName = strdup(CheckNullString(origName));
01163   msgPtr->lpOriginator->lpszAddress = strdup(CheckNullString(origAddress));
01164   msgPtr->lpOriginator->ulRecipClass = rMailPtr->MSG_ORIG_ulRecipClass;
01165 
01166   // Now deal with the recipients of this message
01167   msgPtr->lpRecips = (lpMapiRecipDesc) malloc((size_t) (sizeof(MapiRecipDesc) * 
01168                                                     rMailPtr->MSG_nRecipCount));
01169   if (!msgPtr->lpRecips)
01170   {
01171     // Cleanup the shared memory...
01172     NSCloseSharedMemory(sMem, hSharedMemory);
01173 
01174     FreeMAPIMessage(msgPtr);
01175     NSStrSeqDelete(blobSequence);
01176          LogString("--MAPIReadMail failed\r\n");
01177          return(MAPI_E_INSUFFICIENT_MEMORY);
01178   }
01179 
01180   msgPtr->nRecipCount = rMailPtr->MSG_nRecipCount;
01181   memset(msgPtr->lpRecips, 0, (size_t) (sizeof(MapiRecipDesc) * msgPtr->nRecipCount));
01182 
01183   for (i=0; i<msgPtr->nRecipCount; i++)
01184   {
01185   //      String x: LPSTR lpszName;             // Recipient N name                           
01186   //      String x: LPSTR lpszAddress;          // Recipient N address (optional)             
01187   //      String x: LPSTR lpszRecipClass        // recipient class - sprintf of ULONG
01188 
01189     msgPtr->lpRecips[i].lpszName = 
01190         strdup( CheckNullString(NSStrSeqGet(blobSequence, stringCount++)) );
01191 
01192     msgPtr->lpRecips[i].lpszAddress = 
01193         strdup( CheckNullString(NSStrSeqGet(blobSequence, stringCount++)) );
01194       
01195     msgPtr->lpRecips[i].ulRecipClass = 
01196         (ULONG) atoi( CheckNullString(NSStrSeqGet(blobSequence, stringCount++)) );
01197   }
01198 
01199   //
01200   // MAPI_ENVELOPE_ONLY 
01201   // Indicates MAPIReadMail should read the message header only. File attachments are 
01202   // not copied to temporary files, and neither temporary file names nor message text 
01203   // is written. Setting this flag enhances performance. 
01204   //
01205   // MAPI_SUPPRESS_ATTACH 
01206   // Indicates MAPIReadMail should not copy file attachments but should write message 
01207   // text into the MapiMessage structure. MAPIReadMail ignores this flag if the 
01208   // calling application has set the MAPI_ENVELOPE_ONLY flag. Setting the 
01209   // MAPI_SUPPRESS_ATTACH flag enhances performance. 
01210   //
01211   if (flFlags & MAPI_ENVELOPE_ONLY)
01212   {
01213     noteText = NULL;
01214     rMailPtr->MSG_nFileCount = 0;
01215   }
01216   else if ( (flFlags & MAPI_BODY_AS_FILE) &&
01217             (flFlags & MAPI_SUPPRESS_ATTACH))
01218   {
01219     rMailPtr->MSG_nFileCount = 1;
01220   }
01221   else if (flFlags & MAPI_BODY_AS_FILE) 
01222   {
01223     ++(rMailPtr->MSG_nFileCount);
01224   }
01225 
01226   // Now deal with the list of attachments! Since the nFileCount should be set
01227   // correctly, this loop will automagically be correct
01228   //
01229   if (rMailPtr->MSG_nFileCount > 0)
01230   {
01231     msgPtr->lpFiles = (lpMapiFileDesc) malloc((size_t)  (sizeof(MapiFileDesc) * 
01232                                                     rMailPtr->MSG_nFileCount) );
01233     if (!msgPtr->lpFiles)
01234     {
01235       // Cleanup the shared memory...
01236       NSCloseSharedMemory(sMem, hSharedMemory);
01237 
01238       FreeMAPIMessage(msgPtr);
01239       NSStrSeqDelete(blobSequence);
01240       LogString("--MAPIReadMail failed\r\n");
01241       return(MAPI_E_INSUFFICIENT_MEMORY);
01242     }
01243 
01244     memset(msgPtr->lpFiles, 0, (size_t) (sizeof(MapiFileDesc) * rMailPtr->MSG_nFileCount));
01245   }
01246 
01247   UCHAR   fNameBody[_MAX_PATH];
01248 
01249   // Now do body and attachment stuff only if we haven't been told
01250   // not to do it by the user.
01251   if (!(flFlags & MAPI_ENVELOPE_ONLY))
01252   {
01253     if (flFlags & MAPI_BODY_AS_FILE)
01254     {
01255       LPSTR tempNoteText = CheckNullString(noteText);
01256       
01257       if (GetTempAttachmentName((LPSTR) fNameBody) != 0)
01258       {
01259         // Cleanup the shared memory...
01260         NSCloseSharedMemory(sMem, hSharedMemory);
01261         
01262         FreeMAPIMessage(msgPtr);
01263         NSStrSeqDelete(blobSequence);
01264         LogString("--MAPIReadMail failed\r\n");
01265         return(MAPI_E_ATTACHMENT_WRITE_FAILURE);
01266       }
01267       
01268       if (WriteMemoryBufferToDisk((LPSTR) fNameBody, 
01269         (strlen(tempNoteText) + 1), tempNoteText) != 0)
01270       {
01271         // Cleanup the shared memory...
01272         NSCloseSharedMemory(sMem, hSharedMemory);
01273         
01274         FreeMAPIMessage(msgPtr);
01275         NSStrSeqDelete(blobSequence);
01276         LogString("--MAPIReadMail failed\r\n");
01277         return(MAPI_E_ATTACHMENT_WRITE_FAILURE);
01278       }
01279     }
01280     else
01281     {
01282       msgPtr->lpszNoteText = strdup(noteText);
01283     }
01284     
01285     msgPtr->nFileCount = rMailPtr->MSG_nFileCount;
01286     for (i=0; i<msgPtr->nFileCount; i++)
01287     {
01288       //
01289       // MAPI_BODY_AS_FILE 
01290       // Indicates MAPIReadMail should write the message text to a temporary file 
01291       // and add it as the first attachment in the attachment list. 
01292       if ( (i == 0) && (flFlags & MAPI_BODY_AS_FILE))
01293       {
01294         msgPtr->lpFiles[i].lpszPathName = strdup((LPSTR)fNameBody);
01295         msgPtr->lpFiles[i].lpszFileName = strdup((LPSTR)fNameBody);
01296         continue;
01297       }
01298       
01299       msgPtr->lpFiles[i].lpszPathName = 
01300         strdup( CheckNullString(NSStrSeqGet(blobSequence, stringCount++)) );
01301       msgPtr->lpFiles[i].lpszFileName =
01302         strdup( CheckNullString(NSStrSeqGet(blobSequence, stringCount++)) );
01303     }
01304   }
01305 
01306   //
01307   // RICHIE - For now, let's do a little cleanup on the message itself
01308   // and strip the following inline tags:
01309   //
01310   // &nbsp; &lt; 
01311   //
01312   msgPtr->lpszNoteText = StripHTML(msgPtr->lpszNoteText);
01313 
01314   //
01315   // Now that we are here, set the pointer array and move on with life...
01316   //
01317   *lppMessage = msgPtr;
01318   SetPointerArray(msgPtr, MAPI_MESSAGE_TYPE);
01319 
01320   // Cleanup the shared memory...
01321   NSCloseSharedMemory(sMem, hSharedMemory);
01322   if (blobSequence)
01323     NSStrSeqDelete(blobSequence);
01324 
01325   //
01326   // Now, get out...
01327   //
01328        LogString("--MAPIReadMail complete\r\n");
01329        return(result);
01330 }
01331 
01332 MAPI_IMPLEMENT(ULONG) 
01333 MAPISaveMail(
01334     LHANDLE lhSession,
01335     ULONG ulUIParam,
01336     lpMapiMessage lpMessage,
01337     FLAGS flFlags,
01338     ULONG ulReserved,
01339     LPSTR lpszMessageID
01340 )
01341 {
01342 #ifdef _DEBUG
01343        TRACE_FN("MapiSaveMail");
01344        TRACE("  lhSession=%lu\n", lhSession);
01345        if (lpMessage)
01346        {
01347               TRACE("  lpMessage->lpszSubject = '%s'\n  lpMessage->lpszNoteText='%s'\n", lpMessage->lpszSubject, lpMessage->lpszNoteText);
01348               TRACE("  lpMessage->nRecipCount = %lu\n  lpMessage->nFileCount=%lu\n", lpMessage->nRecipCount, lpMessage->nFileCount);
01349               lpMapiFileDesc pFiles = lpMessage->lpFiles;
01350               for (ULONG i = 0; i < lpMessage->nFileCount; i++)
01351               {
01352                      TRACE("    lpszPathName='%s', lpszFileName='%s'\n", pFiles[i].lpszPathName, pFiles[i].lpszFileName);
01353               }
01354        }
01355 #endif
01356 
01357   CleanupMAPITempFiles();
01358 
01359   //
01360   // Needed variables...
01361   //
01362   BOOL          isTempSession = FALSE;
01363   LONG          result = SUCCESS_SUCCESS;
01364   HWND          hWndIPC;
01365   MAPIIPCType   ipcInfo;
01366 
01367        if (!lpMessage)
01368        {
01369               return(MAPI_E_FAILURE);
01370        }
01371 
01372   //
01373   // Sanity Check the attachments if any here...
01374   //
01375   if (lpMessage->nFileCount > 0)
01376   {
01377     DWORD rc = SanityCheckAttachmentFiles(lpMessage);  // return of zero is ok
01378     if (rc == 1)
01379     {
01380       return(MAPI_E_ATTACHMENT_NOT_FOUND);
01381     }
01382     else if (rc == 2)
01383     {
01384       return(MAPI_E_ATTACHMENT_OPEN_FAILURE);
01385     }
01386   }
01387 
01388   //
01389   // If lhSession is ZERO, then we have to get a temporary session and
01390   // go from there.
01391   //
01392   if ( (lhSession == 0) || (flFlags & MAPI_NEW_SESSION))
01393   {
01394     LHANDLE    lhTempSession;
01395     if (MAPILogon(0, NULL, NULL, 0, 0, &lhTempSession) != SUCCESS_SUCCESS)
01396     {
01397       isTempSession = TRUE;
01398       if (MAPILogon(0, "dummy", "dummy", 0, 0, &lhTempSession) != SUCCESS_SUCCESS)
01399       {
01400         return(MAPI_E_LOGIN_FAILURE);
01401       }
01402     }
01403 
01404     lhSession = lhTempSession;
01405   }
01406 
01407   //
01408   // Now create the big chunk of memory that we will pass across which
01409   // represents the message
01410   //
01411   DWORD               totalSize;
01412   MAPISendMailType    *memToPass = NULL;
01413 
01414   memToPass = (MAPISendMailType *) FlattenMAPIMessageStructure(lpMessage, &totalSize);
01415   if (!memToPass)
01416   {
01417       if (isTempSession)
01418       {
01419         MAPILogoff(lhSession, 0, 0, 0);
01420       }
01421       
01422       return(MAPI_E_INSUFFICIENT_MEMORY);
01423   }
01424 
01425   memToPass->lhSession = lhSession;
01426   memToPass->ulUIParam = ulUIParam;
01427   memToPass->flFlags = flFlags;
01428   memToPass->ipcWorked = 0;
01429 
01430   //
01431   // This call locates a Communicator Window, if one is not running,
01432   // it will start up an instance of Communicator and grab that window.
01433   //
01434   hWndIPC = GetCommunicatorIPCWindow();
01435   if (NULL == hWndIPC)
01436   {
01437     free(memToPass);
01438     if (isTempSession)
01439     {
01440       MAPILogoff(lhSession, 0, 0, 0);
01441     }
01442     return(MAPI_E_FAILURE);
01443   }
01444 
01445   // 
01446   // Build the IPC structure of information that needs to be provided
01447   // to get information into Communicator
01448   //
01449   BuildMemName((LPSTR)ipcInfo.smemName, ulUIParam);
01450 
01451   //
01452   // Build the shared memory segment of information to pass into 
01453   // Communicator for send message call.
01454   //
01455   CSharedMem      *sMem;
01456   HANDLE          hSharedMemory;
01457 
01458   //
01459   // Create the shared memory...
01460   //
01461   sMem = NSCreateSharedMemory(totalSize, (LPSTR) ipcInfo.smemName, &hSharedMemory);
01462   if (!sMem)
01463   {
01464       free(memToPass);
01465       if (isTempSession)
01466       {
01467         MAPILogoff(lhSession, 0, 0, 0);
01468       }
01469       return(MAPI_E_INSUFFICIENT_MEMORY);
01470   }
01471 
01472   //
01473   // Now copy the information into the memory segment.
01474   //
01475   sMem->m_dwSize = totalSize;
01476   memcpy(sMem->m_buf, memToPass, (size_t) totalSize);
01477 
01478   //
01479   // Now set the size of the shared memory segment for the 
01480   // WM_COPYDATA argument that will be sent across.
01481   //
01482   ipcInfo.smemSize = totalSize;
01483 
01484   // For Win16, we actually pass in the pointer to the structure,
01485   // so just assign the variable here.
01486 #ifdef WIN16
01487   ipcInfo.lpsmem = sMem;
01488 #else
01489   ipcInfo.lpsmem = NULL;
01490 #endif
01491 
01492   //
01493   // Ok, time to do the SendMessage() to Communicator...
01494   //
01495   result = SendMAPIRequest(hWndIPC, NSCP_MAPISaveMail, &ipcInfo);
01496 
01497   // Check for IPC completion
01498   MAPISendMailType *ptr = (MAPISendMailType *) &(sMem->m_buf[0]);
01499   if (!ptr->ipcWorked)
01500   {
01501     result = MAPI_E_FAILURE;
01502   }
01503 
01504   //
01505   // Now time to do some cleanup...
01506   //
01507   NSCloseSharedMemory(sMem, hSharedMemory);
01508   free(memToPass);
01509 
01510        LogString("--MAPISaveMail complete\r\n");
01511 
01512   //
01513   // If we created a temp session, then we need to trash it...
01514   //
01515   if (isTempSession)
01516   {
01517     MAPILogoff(lhSession, 0, 0, 0);
01518   }
01519 
01520   return(result);
01521 }
01522 
01523 //
01524 // The MAPIDeleteMail function deletes a message. 
01525 //
01526 MAPI_IMPLEMENT(ULONG) 
01527 MAPIDeleteMail(
01528     LHANDLE lhSession,
01529     ULONG ulUIParam,
01530     LPSTR lpszMessageID,
01531     FLAGS flFlags,
01532     ULONG ulReserved)
01533 {
01534 LRESULT       result;
01535 HWND          hWndIPC;
01536 MAPIIPCType   ipcInfo;
01537 
01538        TRACE_FN("MAPIDeleteMail");
01539   if (lhSession == 0)
01540   {
01541     return(MAPI_E_INVALID_SESSION);
01542   }
01543 
01544   // Make sure we have something valid on the message ID front!
01545   if ((!lpszMessageID) || (!*lpszMessageID))
01546   {
01547     return(MAPI_E_INVALID_MESSAGE);
01548   }
01549 
01550   if (strlen(lpszMessageID) > 511)
01551   {
01552     return(MAPI_E_INSUFFICIENT_MEMORY);
01553   }
01554 
01555        TRACE("MAPIDeleteMail lhSession Session ID = %lu\n", lhSession);
01556 
01557   //
01558   // This call locates a Communicator Window, if one is not running,
01559   // it will start up an instance of Communicator and grab that window.
01560   //
01561   hWndIPC = GetCommunicatorIPCWindow();
01562   if (NULL == hWndIPC)
01563   {
01564     return(MAPI_E_FAILURE);
01565   }
01566 
01567   // 
01568   // Build the IPC structure of information that needs to be provided
01569   // to get information into Communicator
01570   //
01571   BuildMemName((LPSTR)ipcInfo.smemName, ulUIParam);
01572 
01573   //
01574   // Build the shared memory segment of information to pass into 
01575   // Communicator for the login call.
01576   //
01577   CSharedMem          *sMem;
01578   DWORD               memSize;
01579   HANDLE              hSharedMemory;
01580   MAPIDeleteMailType  delInfo;
01581    
01582   memSize = sizeof(MAPIDeleteMailType);
01583   lstrcpy((LPSTR)delInfo.lpszMessageID, lpszMessageID);
01584 
01585   //
01586   // Create the shared memory...
01587   //
01588   sMem = NSCreateSharedMemory(memSize, (LPSTR) ipcInfo.smemName, &hSharedMemory);
01589   if (!sMem)
01590   {
01591       return(MAPI_E_INSUFFICIENT_MEMORY);
01592   }
01593 
01594   //
01595   // Now populate a Logon structure with the passed in information
01596   //
01597   delInfo.lhSession   = lhSession;
01598   delInfo.ulUIParam   = ulUIParam;
01599   delInfo.ipcWorked   = 0;
01600 
01601   //
01602   // Now copy the information into the memory segment.
01603   //
01604   sMem->m_dwSize = memSize;
01605   memcpy(sMem->m_buf, &(delInfo), sizeof(MAPIDeleteMailType));
01606 
01607   //
01608   // Now set the size of the shared memory segment for the 
01609   // WM_COPYDATA argument that will be sent across.
01610   //
01611   ipcInfo.smemSize = memSize;
01612 
01613   // For Win16, we actually pass in the pointer to the structure,
01614   // so just assign the variable here.
01615 #ifdef WIN16
01616   ipcInfo.lpsmem = sMem;
01617 #else
01618   ipcInfo.lpsmem = NULL;
01619 #endif
01620 
01621   //
01622   // Ok, time to do the SendMessage() to Communicator...
01623   //
01624   result = SendMAPIRequest(hWndIPC, NSCP_MAPIDeleteMail, &ipcInfo);
01625 
01626   // Check for IPC completion
01627   MAPIDeleteMailType *ptr = (MAPIDeleteMailType *) &(sMem->m_buf[0]);
01628   if (!ptr->ipcWorked)
01629   {
01630     result = MAPI_E_FAILURE;
01631   }
01632 
01633   //
01634   // Now do cleanup on the way out and return the value to the caller...
01635   //
01636   NSCloseSharedMemory(sMem, hSharedMemory);
01637        LogString("--MAPIDeleteMail complete\r\n");
01638        return(result);
01639 }
01640 
01641 // RICHIE - MAPI ADDRESS HERE
01642 
01643 //
01644 // The MAPIDetails function displays a dialog box containing the details 
01645 // of a selected address list entry
01646 //
01647 MAPI_IMPLEMENT(ULONG) 
01648 MAPIDetails(
01649     LHANDLE lhSession,
01650     ULONG ulUIParam,
01651     lpMapiRecipDesc lpRecip,
01652     FLAGS flFlags,
01653     ULONG ulReserved)
01654 {
01655        TRACE_FN("MAPIDetails");
01656   //
01657   // Needed variables...
01658   //
01659   BOOL          isTempSession = FALSE;
01660   LONG          result = SUCCESS_SUCCESS;
01661   HWND          hWndIPC;
01662   MAPIIPCType   ipcInfo;
01663 
01664   // Make sure we have something valid on the query name front!
01665   if (!lpRecip) 
01666   {
01667     return(MAPI_E_AMBIGUOUS_RECIPIENT);
01668   }
01669 
01670   if ((lpRecip->ulEIDSize == 0) || (lpRecip->ulEIDSize > MAX_NAME_LEN))
01671   {
01672     return(MAPI_E_AMBIGUOUS_RECIPIENT);
01673   }
01674 
01675   //
01676   // If lhSession is ZERO, then we have to get a temporary session and
01677   // go from there.
01678   //
01679   if (lhSession == 0)
01680   {
01681     LHANDLE    lhTempSession;
01682     if (MAPILogon(0, NULL, NULL, 0, 0, &lhTempSession) != SUCCESS_SUCCESS)
01683     {
01684       isTempSession = TRUE;
01685       if (MAPILogon(0, "dummy", "dummy", 0, 0, &lhTempSession) != SUCCESS_SUCCESS)
01686       {
01687         return(MAPI_E_LOGIN_FAILURE);
01688       }
01689     }
01690 
01691     lhSession = lhTempSession;
01692   }
01693 
01694   //
01695   // Now create the big chunk of memory that we will pass across which
01696   // represents the message
01697   //
01698   MAPIDetailsType        detailInfo;
01699 
01700   memset(&detailInfo, 0, sizeof(MAPIDetailsType));
01701   detailInfo.lhSession = lhSession;
01702   detailInfo.ulUIParam = ulUIParam;
01703   detailInfo.flFlags   = flFlags;
01704   detailInfo.ipcWorked = 0;
01705   memcpy(detailInfo.lpszABookID, lpRecip->lpEntryID, (size_t) lpRecip->ulEIDSize);
01706 
01707   //
01708   // This call locates a Communicator Window, if one is not running,
01709   // it will start up an instance of Communicator and grab that window.
01710   //
01711   hWndIPC = GetCommunicatorIPCWindow();
01712   if (NULL == hWndIPC)
01713   {
01714     if (isTempSession)
01715     {
01716       MAPILogoff(lhSession, 0, 0, 0);
01717     }
01718     return(MAPI_E_FAILURE);
01719   }
01720 
01721   // 
01722   // Build the IPC structure of information that needs to be provided
01723   // to get information into Communicator
01724   //
01725   BuildMemName((LPSTR)ipcInfo.smemName, ulUIParam);
01726 
01727   //
01728   // Build the shared memory segment of information to pass into 
01729   // Communicator for send message call.
01730   //
01731   CSharedMem      *sMem;
01732   HANDLE          hSharedMemory;
01733   
01734   //
01735   // Create the shared memory...
01736   //
01737   sMem = NSCreateSharedMemory(sizeof(MAPIDetailsType), (LPSTR) ipcInfo.smemName, &hSharedMemory);
01738   if (!sMem)
01739   {
01740       if (isTempSession)
01741       {
01742         MAPILogoff(lhSession, 0, 0, 0);
01743       }
01744       return(MAPI_E_INSUFFICIENT_MEMORY);
01745   }
01746 
01747   //
01748   // Now copy the information into the memory segment.
01749   //
01750   sMem->m_dwSize = sizeof(MAPIDetailsType);
01751   memcpy(sMem->m_buf, &detailInfo, sizeof(MAPIDetailsType));
01752 
01753   //
01754   // Now set the size of the shared memory segment for the 
01755   // WM_COPYDATA argument that will be sent across.
01756   //
01757   ipcInfo.smemSize = sizeof(MAPIDetailsType);
01758 
01759   // For Win16, we actually pass in the pointer to the structure,
01760   // so just assign the variable here.
01761 #ifdef WIN16
01762   ipcInfo.lpsmem = sMem;
01763 #else
01764   ipcInfo.lpsmem = NULL;
01765 #endif
01766 
01767   //
01768   // Ok, time to do the SendMessage() to Communicator...
01769   //
01770   result = SendMAPIRequest(hWndIPC, NSCP_MAPIDetails, &ipcInfo);
01771 
01772   // Check for IPC completion
01773   MAPIDetailsType *ptr = (MAPIDetailsType *) &(sMem->m_buf[0]);
01774   if (!ptr->ipcWorked)
01775   {
01776     result = MAPI_E_FAILURE;
01777   }
01778 
01779   //
01780   // Now time to do some real cleanup...
01781   //
01782   NSCloseSharedMemory(sMem, hSharedMemory);
01783 
01784   //
01785   // If we created a temp session, then we need to trash it...
01786   //
01787   if (isTempSession)
01788   {
01789     MAPILogoff(lhSession, 0, 0, 0);
01790   }
01791 
01792   LogString("--MAPIDetails complete\r\n");
01793   return(result);
01794 }
01795 
01796 //
01797 // The MAPIResolveName function transforms a message recipient's name as entered by a 
01798 // user to an unambiguous address list entry. 
01799 //
01800 MAPI_IMPLEMENT(ULONG) 
01801 MAPIResolveName(
01802     LHANDLE lhSession,
01803     ULONG ulUIParam,
01804     LPSTR lpszName,
01805     FLAGS flFlags,
01806     ULONG ulReserved,
01807     lpMapiRecipDesc FAR *lppRecip)
01808 {
01809        TRACE_FN("MAPIResolveName");
01810   //
01811   // Needed variables...
01812   //
01813   BOOL          isTempSession = FALSE;
01814   LONG          result = SUCCESS_SUCCESS;
01815   HWND          hWndIPC;
01816   MAPIIPCType   ipcInfo;
01817 
01818   // Make sure we have something valid on the query name front!
01819   if ((!lpszName) || (!*lpszName))
01820   {
01821     return(MAPI_E_UNKNOWN_RECIPIENT);
01822   }
01823 
01824   if (strlen(lpszName) > 255)
01825   {
01826     return(MAPI_E_INSUFFICIENT_MEMORY);
01827   }
01828 
01829   //
01830   // If lhSession is ZERO, then we have to get a temporary session and
01831   // go from there.
01832   //
01833   if (lhSession == 0)
01834   {
01835     LHANDLE    lhTempSession;
01836     if (MAPILogon(0, NULL, NULL, 0, 0, &lhTempSession) != SUCCESS_SUCCESS)
01837     {
01838       isTempSession = TRUE;
01839       if (MAPILogon(0, "dummy", "dummy", 0, 0, &lhTempSession) != SUCCESS_SUCCESS)
01840       {
01841         return(MAPI_E_LOGIN_FAILURE);
01842       }
01843     }
01844 
01845     lhSession = lhTempSession;
01846   }
01847 
01848   //
01849   // Now create the big chunk of memory that we will pass across which
01850   // represents the message
01851   //
01852   MAPIResolveNameType   nameInfo;
01853 
01854   nameInfo.lhSession = lhSession;
01855   nameInfo.ulUIParam = ulUIParam;
01856   nameInfo.flFlags   = flFlags;
01857   nameInfo.ipcWorked = 0;
01858   lstrcpy((LPSTR) nameInfo.lpszName, lpszName);
01859 
01860   //
01861   // This call locates a Communicator Window, if one is not running,
01862   // it will start up an instance of Communicator and grab that window.
01863   //
01864   hWndIPC = GetCommunicatorIPCWindow();
01865   if (NULL == hWndIPC)
01866   {
01867     if (isTempSession)
01868     {
01869       MAPILogoff(lhSession, 0, 0, 0);
01870     }
01871     return(MAPI_E_FAILURE);
01872   }
01873 
01874   // 
01875   // Build the IPC structure of information that needs to be provided
01876   // to get information into Communicator
01877   //
01878   BuildMemName((LPSTR)ipcInfo.smemName, ulUIParam);
01879 
01880   //
01881   // Build the shared memory segment of information to pass into 
01882   // Communicator for send message call.
01883   //
01884   CSharedMem      *sMem;
01885   HANDLE          hSharedMemory;
01886 
01887   //
01888   // Create the shared memory...
01889   //
01890   sMem = NSCreateSharedMemory(sizeof(MAPIResolveNameType), (LPSTR) ipcInfo.smemName, &hSharedMemory);
01891   if (!sMem)
01892   {
01893       if (isTempSession)
01894       {
01895         MAPILogoff(lhSession, 0, 0, 0);
01896       }
01897       return(MAPI_E_INSUFFICIENT_MEMORY);
01898   }
01899 
01900   //
01901   // Now copy the information into the memory segment.
01902   //
01903   sMem->m_dwSize = sizeof(MAPIResolveNameType);
01904   memcpy(sMem->m_buf, &nameInfo, sizeof(MAPIResolveNameType));
01905 
01906   //
01907   // Now set the size of the shared memory segment for the 
01908   // WM_COPYDATA argument that will be sent across.
01909   //
01910   ipcInfo.smemSize = sizeof(MAPIResolveNameType);
01911 
01912   // For Win16, we actually pass in the pointer to the structure,
01913   // so just assign the variable here.
01914 #ifdef WIN16
01915   ipcInfo.lpsmem = sMem;
01916 #else
01917   ipcInfo.lpsmem = NULL;
01918 #endif
01919 
01920   //
01921   // Ok, time to do the SendMessage() to Communicator...
01922   //
01923   result = SendMAPIRequest(hWndIPC, NSCP_MAPIResolveName, &ipcInfo);
01924 
01925   // Check for IPC completion
01926   MAPIResolveNameType *ptr = (MAPIResolveNameType *) &(sMem->m_buf[0]);
01927   if (!ptr->ipcWorked)
01928   {
01929     result = MAPI_E_FAILURE;
01930   }
01931 
01932   //
01933   // IF FOUND: create the new structure for the matched address info and set the
01934   // memory tracking array correctly for cleanup later down the road.
01935   // 
01936   if (result == SUCCESS_SUCCESS)
01937   {
01938     *lppRecip = (MapiRecipDesc FAR *)malloc(sizeof(MapiRecipDesc));
01939     if (lppRecip == NULL)
01940     {
01941         if (isTempSession)
01942         {
01943           MAPILogoff(lhSession, 0, 0, 0);
01944         }
01945 
01946         return(MAPI_E_INSUFFICIENT_MEMORY);
01947     }
01948 
01949     // Null out the new memory...
01950     memset((*lppRecip), 0, sizeof(MapiRecipDesc));
01951     MAPIResolveNameType *resultInfo = (MAPIResolveNameType *) &(sMem->m_buf[0]);
01952 
01953     (*lppRecip)->ulRecipClass = 0;   // This field is meaningless in this call
01954     (*lppRecip)->lpszName = strdup((LPSTR) resultInfo->lpszABookName);
01955     (*lppRecip)->lpszAddress = strdup((LPSTR) resultInfo->lpszABookAddress);
01956 
01957     // We will be using a string made up of the first and last name of the
01958     // person as a unique ID for that individual. The string will be delimited
01959     // like this:
01960     //
01961     //                <first_name>:=LAST=:<last_name>
01962     //
01963     (*lppRecip)->ulEIDSize = strlen((LPSTR) resultInfo->lpszABookID) + 1;
01964     (*lppRecip)->lpEntryID = strdup((LPSTR) resultInfo->lpszABookID);
01965 
01966     SetPointerArray(*lppRecip, MAPI_RECIPIENT_TYPE);
01967   }  
01968 
01969   //
01970   // Now time to do some real cleanup...
01971   //
01972   NSCloseSharedMemory(sMem, hSharedMemory);
01973 
01974   //
01975   // If we created a temp session, then we need to trash it...
01976   //
01977   if (isTempSession)
01978   {
01979     MAPILogoff(lhSession, 0, 0, 0);
01980   }
01981 
01982   LogString("--MAPIResolveName complete\r\n");
01983   return(result);
01984 }
01985 
01986 MAPI_IMPLEMENT(ULONG) 
01987 MAPIAddress(
01988     LHANDLE lhSession,
01989     ULONG ulUIParam,
01990     LPSTR lpszCaption,
01991     ULONG nEditFields,
01992     LPSTR lpszLabels,
01993     ULONG nRecips,
01994     lpMapiRecipDesc lpRecips,
01995     FLAGS flFlags,
01996     ULONG ulReserved,
01997     LPULONG lpnNewRecips,
01998     lpMapiRecipDesc FAR *lppNewRecips)
01999 {
02000   TRACE_FN("MAPIAddress");
02001   TRACE("MAPIAddress: lhSession=%lu\n", lhSession);
02002   //
02003   // Needed variables...
02004   //
02005   BOOL          isTempSession = FALSE;
02006   LONG          result = SUCCESS_SUCCESS;
02007   HWND          hWndIPC;
02008   MAPIIPCType   ipcInfo;
02009 
02010   *lppNewRecips = NULL;
02011 
02012   //
02013   // If lhSession is ZERO, then we have to get a temporary session and
02014   // go from there.
02015   //
02016   if ( (lhSession == 0) || (flFlags & MAPI_NEW_SESSION))
02017   {
02018     LHANDLE    lhTempSession;
02019     if (MAPILogon(0, NULL, NULL, 0, 0, &lhTempSession) != SUCCESS_SUCCESS)
02020     {
02021       isTempSession = TRUE;
02022       if (MAPILogon(0, "dummy", "dummy", 0, 0, &lhTempSession) != SUCCESS_SUCCESS)
02023       {
02024         return(MAPI_E_LOGIN_FAILURE);
02025       }
02026     }
02027 
02028     lhSession = lhTempSession;
02029   }
02030 
02031   //
02032   // This call locates a Communicator Window, if one is not running,
02033   // it will start up an instance of Communicator and grab that window.
02034   //
02035   hWndIPC = GetCommunicatorIPCWindow();
02036   if (NULL == hWndIPC)
02037   {
02038     return(MAPI_E_FAILURE);
02039   }
02040 
02041   // 
02042   // Build the IPC structure of information that needs to be provided
02043   // to get information into Communicator
02044   //
02045   BuildMemName((LPSTR)ipcInfo.smemName, ulUIParam);
02046 
02047   //
02048   // Build the shared memory segment of information to pass into 
02049   // Communicator for the address call.
02050   //
02051   ULONG             i;
02052   CSharedMem        *sMem;
02053   DWORD             memSize;
02054   HANDLE            hSharedMemory;
02055   MAPIAddressType   addrInfo;
02056   LONG              strSeqSize = 0;
02057   NSstringSeq       strSeq = NULL;
02058   DWORD             currentString = 0;
02059    
02060   //
02061   // First populate a address structure with the passed in information
02062   //
02063   memset(&addrInfo, 0, (size_t) sizeof(MAPIAddressType));
02064 
02065   addrInfo.lhSession  = lhSession;
02066   addrInfo.ulUIParam  = ulUIParam;
02067   addrInfo.flFlags    = flFlags;
02068   addrInfo.ipcWorked  = 0;
02069   addrInfo.nNewRecips = 0;        // number of recips returned...
02070   addrInfo.lpszBlob[0] = '\0';    // file name for blob of information 
02071 
02072   addrInfo.nRecips = nRecips;     // number of recips to start with...
02073 
02074   //
02075   // Copy the caption into the structure
02076   //
02077   if ((lpszCaption) && (*lpszCaption))    // check for no null
02078   {
02079     strcpy((LPSTR) addrInfo.lpszCaption, lpszCaption);
02080   }
02081 
02082   // Now build the glob of memory of addresses to start with...
02083   if (nRecips > 0)
02084   {
02085     LPSTR *strArray = (LPSTR *) malloc((size_t) (sizeof(LPSTR) * ((nRecips * 3) + 1)));
02086     if (!strArray)
02087     {
02088       if (isTempSession)
02089       {
02090         MAPILogoff(lhSession, 0, 0, 0);
02091       }
02092       return(MAPI_E_INSUFFICIENT_MEMORY);
02093     }
02094   
02095     LPSTR toString  = "1";
02096     LPSTR ccString  = "2";
02097     LPSTR bccString = "3";
02098 
02099     for (i=0; i<nRecips; i++)
02100     {
02101       // rhp - need message class
02102       if (lpRecips[i].ulRecipClass == MAPI_BCC)
02103         strArray[currentString++] = CheckNullString(bccString);
02104       else if (lpRecips[i].ulRecipClass == MAPI_CC)
02105         strArray[currentString++] = CheckNullString(ccString);
02106       else
02107         strArray[currentString++] = CheckNullString(toString);
02108 
02109       strArray[currentString++] = CheckNullString(lpRecips[i].lpszName);
02110       strArray[currentString++] = CheckNullString(lpRecips[i].lpszAddress);  
02111     }
02112 
02113     strArray[currentString] = NULL;
02114 
02115     strSeq     = NSStrSeqNew(strArray);
02116     free(strArray);
02117     if (!strSeq)
02118     {
02119       if (isTempSession)
02120       {
02121         MAPILogoff(lhSession, 0, 0, 0);
02122       }
02123       return(MAPI_E_INSUFFICIENT_MEMORY);
02124     }
02125 
02126     strSeqSize = NSStrSeqSize(strSeq);
02127   }
02128   
02129   memSize = sizeof(MAPIAddressType) + strSeqSize;
02130 
02131   //
02132   // Create the shared memory...
02133   //
02134   sMem = NSCreateSharedMemory(memSize, (LPSTR) ipcInfo.smemName, &hSharedMemory);
02135   if (!sMem)
02136   {
02137       if (isTempSession)
02138       {
02139         MAPILogoff(lhSession, 0, 0, 0);
02140       }
02141       return(MAPI_E_INSUFFICIENT_MEMORY);
02142   }
02143 
02144   //
02145   // Now copy the information into the memory segment.
02146   //
02147   sMem->m_dwSize = memSize;
02148   memcpy(sMem->m_buf, &(addrInfo), sizeof(MAPIAddressType));
02149 
02150   // Now if we have recipients...copy in the sequence!
02151   if (nRecips > 0)  
02152   {
02153     MAPIAddressType *ptr = (MAPIAddressType *)&(sMem->m_buf[0]);
02154 
02155     memcpy(ptr->dataBuf, strSeq, strSeqSize);
02156     NSStrSeqDelete(strSeq);
02157   }
02158 
02159   //
02160   // Now set the size of the shared memory segment for the 
02161   // WM_COPYDATA argument that will be sent across.
02162   //
02163   ipcInfo.smemSize = memSize;
02164 
02165   // For Win16, we actually pass in the pointer to the structure,
02166   // so just assign the variable here.
02167 #ifdef WIN16
02168   ipcInfo.lpsmem = sMem;
02169 #else
02170   ipcInfo.lpsmem = NULL;
02171 #endif
02172 
02173   //
02174   // Ok, time to do the SendMessage() to Communicator...
02175   //
02176   result = SendMAPIRequest(hWndIPC, NSCP_MAPIAddress, &ipcInfo);
02177 
02178   // Check the IPC status...
02179   MAPIAddressType *addrPtr = (MAPIAddressType *) &(sMem->m_buf[0]);
02180 
02181   //
02182   // Now return the value to the caller if we bombed...
02183   //
02184   if ((result != SUCCESS_SUCCESS) || (!(addrPtr->ipcWorked)))
02185   {
02186     NSCloseSharedMemory(sMem, hSharedMemory);
02187     if (isTempSession)
02188     {
02189       MAPILogoff(lhSession, 0, 0, 0);
02190     }
02191          LogString("--MAPIAddress failed\r\n");
02192          return(result);
02193   }
02194 
02195   // Now deal with the addresses selected and move on...
02196   if (addrPtr->nNewRecips == 0)
02197   {
02198     NSCloseSharedMemory(sMem, hSharedMemory);
02199     if (isTempSession)
02200     {
02201       MAPILogoff(lhSession, 0, 0, 0);
02202     }
02203 
02204          LogString("--MAPIAddress - ZERO recipients\r\n");
02205          return(result);
02206   }
02207 
02208   //
02209   // Get the blob loaded into memory...
02210   // 
02211   NSstringSeq blobSequence = (NSstringSeq) LoadBlobToMemory((LPSTR) addrPtr->lpszBlob);
02212 
02213   // Now check on the blob
02214   if (!blobSequence)
02215   {      
02216     // Cleanup the shared memory...
02217     NSCloseSharedMemory(sMem, hSharedMemory);
02218 
02219     if (isTempSession)
02220     {
02221       MAPILogoff(lhSession, 0, 0, 0);
02222     }
02223     return(MAPI_E_INSUFFICIENT_MEMORY);
02224   }
02225 
02226   ULONG           stringCount = 0; // This is to start with the rest of the string seq
02227   lpMapiRecipDesc lpNewRecips;
02228 
02229   // Now deal with the recipients of this message
02230   lpNewRecips = (lpMapiRecipDesc) malloc((size_t) (sizeof(MapiRecipDesc) * 
02231                                                     addrPtr->nNewRecips));
02232   if (!lpNewRecips)
02233   {
02234     // Cleanup the shared memory...
02235     NSCloseSharedMemory(sMem, hSharedMemory);
02236 
02237     NSStrSeqDelete(blobSequence);
02238          LogString("--MAPIAddress failed\r\n");
02239     if (isTempSession)
02240     {
02241       MAPILogoff(lhSession, 0, 0, 0);
02242     }
02243          return(MAPI_E_INSUFFICIENT_MEMORY);
02244   }
02245 
02246   memset(lpNewRecips, 0, (size_t) (sizeof(MapiRecipDesc) * addrPtr->nNewRecips));
02247 
02248   for (i=0; i<addrPtr->nNewRecips; i++)
02249   {
02250     // String x: LPSTR lpszName;             // Recipient N name                           
02251     // String x: LPSTR lpszAddress;          // Recipient N address (optional)             
02252     // String x: LPSTR lpszRecipClass        // recipient class - sprintf of ULONG
02253     lpNewRecips[i].lpszName = 
02254         strdup( CheckNullString(NSStrSeqGet(blobSequence, stringCount++)) );
02255 
02256     lpNewRecips[i].lpszAddress = 
02257         strdup( CheckNullString(NSStrSeqGet(blobSequence, stringCount++)) );
02258       
02259     lpNewRecips[i].ulRecipClass = 
02260         (ULONG) atoi( CheckNullString(NSStrSeqGet(blobSequence, stringCount++)) );
02261   }
02262 
02263   //
02264   // Now that we are here, set the pointer array and move on with life...
02265   //
02266   *lppNewRecips = lpNewRecips;
02267   *lpnNewRecips = addrPtr->nNewRecips;
02268   SetPointerArray(lpNewRecips, MAPI_RECIPIENT_TYPE);
02269   
02270   // Cleanup the shared memory...
02271   NSCloseSharedMemory(sMem, hSharedMemory);
02272   if (blobSequence)
02273     NSStrSeqDelete(blobSequence);
02274 
02275   //
02276   // If we created a temp session, then we need to trash it...
02277   //
02278   if (isTempSession)
02279   {
02280     MAPILogoff(lhSession, 0, 0, 0);
02281   }
02282 
02283   TRACE("MAPIAddress Complete");
02284        return(result);
02285 }
02286 
02287 MAPI_IMPLEMENT(ULONG) 
02288 MAPIGetNetscapeVersion(void)
02289 {
02290   return(1);
02291 }