|
|
/*
- C L I E N T . C - * Purpose: * Sample mail client for the MAPI 1.0 PDK. * Exclusively uses the Simple MAPI interface. * * Copyright 1993-1995 Microsoft Corporation. All Rights Reserved. */
#include <string.h>
#include <stdlib.h>
#include <windows.h>
#include <commdlg.h>
#include <mapiwin.h>
#include <mapidbg.h>
#include "client.h"
#include "bitmap.h"
#include "pvalloc.h"
HANDLE hInst; HINSTANCE hlibMAPI = 0;
LPMAPILOGON lpfnMAPILogon = NULL; LPMAPILOGOFF lpfnMAPILogoff = NULL; LPMAPISENDMAIL lpfnMAPISendMail = NULL; LPMAPISENDDOCUMENTS lpfnMAPISendDocuments = NULL; LPMAPIFINDNEXT lpfnMAPIFindNext = NULL; LPMAPIREADMAIL lpfnMAPIReadMail = NULL; LPMAPISAVEMAIL lpfnMAPISaveMail = NULL; LPMAPIDELETEMAIL lpfnMAPIDeleteMail = NULL; LPMAPIFREEBUFFER lpfnMAPIFreeBuffer = NULL; LPMAPIADDRESS lpfnMAPIAddress = NULL; LPMAPIDETAILS lpfnMAPIDetails = NULL; LPMAPIRESOLVENAME lpfnMAPIResolveName = NULL;
/* Static Data */
static BOOL fDialogIsActive = FALSE; static DWORD cUsers = 0; static ULONG flSendMsgFlags = 0; static LHANDLE lhSession = 0L; static HBITMAP hReadBmp = 0; static HBITMAP hReadABmp = 0; static HBITMAP hUnReadBmp = 0; static HBITMAP hUnReadABmp = 0; static HCURSOR hWaitCur; static LPMSGID lpReadMsgNode; static lpMapiMessage lpmsg = NULL;
#ifdef _WIN32
#define szMAPIDLL "MAPI32.DLL"
#else
#define szMAPIDLL "MAPI.DLL"
#endif
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpszCmd, int nCmdShow) { MSG msg;
if (!hPrevInst) if (!InitApplication (hInstance)) return (FALSE);
if (!InitInstance (hInstance, nCmdShow)) return (FALSE);
while (GetMessage (&msg, 0, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); }
DeinitApplication ();
return (msg.wParam); }
/*
- InitApplication - * Purpose: * Initialize the application. * * Parameters: * hInstance - Instance handle * * Returns: * True/False * */
BOOL InitApplication (HANDLE hInstance) { WNDCLASS wc;
wc.style = 0; wc.lpfnWndProc = MainWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon (hInstance, "NoMail"); wc.hCursor = LoadCursor (0, IDC_ARROW); wc.hbrBackground = GetStockObject (WHITE_BRUSH); wc.lpszMenuName = "MailMenu"; wc.lpszClassName = "Client";
return (RegisterClass (&wc)); }
/*
- InitInstance - * Purpose: * Initialize this instance. * * Parameters: * hInstance - Instance handle * nCmdShow - Do we show the window? * * Returns: * True/False * */
BOOL InitInstance (HANDLE hInstance, int nCmdShow) { HWND hWnd; BOOL fInit; ULONG ulResult;
hInst = hInstance;
hWnd = CreateWindow ("Client", "MAPI Sample Mail Client", WS_OVERLAPPEDWINDOW, 5, 5, 300, 75, 0, 0, hInst, NULL);
if (!hWnd) return (FALSE);
ShowWindow (hWnd, nCmdShow); UpdateWindow (hWnd);
hWaitCur = LoadCursor(0, IDC_WAIT);
if (fInit = InitSimpleMAPI ()) { /* MAPILogon might yield control to Windows. So to prevent the user
from clicking "logon" while we are in the process of loggin on we have to disable it*/ SecureMenu(hWnd, TRUE); if ((ulResult = MAPILogon ((ULONG) hWnd, NULL, NULL, MAPI_LOGON_UI | MAPI_NEW_SESSION, 0, &lhSession)) == SUCCESS_SUCCESS) { ToggleMenuState (hWnd, TRUE); } else { SecureMenu(hWnd, FALSE); lhSession = 0; MakeMessageBox (hWnd, ulResult, IDS_LOGONFAIL, MBS_ERROR); } }
return (fInit); }
/*
- InitSimpleMAPI - * Purpose: * Loads the DLL containing the simple MAPI functions and sets * up a pointer to each. Wrappers for the function pointers * are declared in SMAPI.H. * * Returns: * TRUE if sucessful, else FALSE * * Side effects: * Loads a DLL and sets up function pointers */ BOOL InitSimpleMAPI (void) { UINT fuError;
/*
*Check if MAPI is installed on the system */ if(!fSMAPIInstalled()) return FALSE;
fuError = SetErrorMode(SEM_NOOPENFILEERRORBOX); hlibMAPI = LoadLibrary(szMAPIDLL); SetErrorMode(fuError);
#ifdef _WIN32
if (!hlibMAPI) #else
if (hlibMAPI < 32) #endif
return (FALSE);
if (!(lpfnMAPILogon = (LPMAPILOGON) GetProcAddress (hlibMAPI, "MAPILogon"))) return (FALSE); if (!(lpfnMAPILogoff = (LPMAPILOGOFF) GetProcAddress (hlibMAPI, "MAPILogoff"))) return (FALSE); if (!(lpfnMAPISendMail = (LPMAPISENDMAIL) GetProcAddress (hlibMAPI, "MAPISendMail"))) return (FALSE); if (!(lpfnMAPISendDocuments = (LPMAPISENDDOCUMENTS) GetProcAddress (hlibMAPI, "MAPISendDocuments"))) return (FALSE); if (!(lpfnMAPIFindNext = (LPMAPIFINDNEXT) GetProcAddress (hlibMAPI, "MAPIFindNext"))) return (FALSE); if (!(lpfnMAPIReadMail = (LPMAPIREADMAIL) GetProcAddress (hlibMAPI, "MAPIReadMail"))) return (FALSE); if (!(lpfnMAPISaveMail = (LPMAPISAVEMAIL) GetProcAddress (hlibMAPI, "MAPISaveMail"))) return (FALSE); if (!(lpfnMAPIDeleteMail = (LPMAPIDELETEMAIL) GetProcAddress (hlibMAPI, "MAPIDeleteMail"))) return (FALSE); if (!(lpfnMAPIFreeBuffer = (LPMAPIFREEBUFFER) GetProcAddress (hlibMAPI, "MAPIFreeBuffer"))) return (FALSE); if (!(lpfnMAPIAddress = (LPMAPIADDRESS) GetProcAddress (hlibMAPI, "MAPIAddress"))) return (FALSE); if (!(lpfnMAPIDetails = (LPMAPIDETAILS) GetProcAddress (hlibMAPI, "MAPIDetails"))) return (FALSE); if (!(lpfnMAPIResolveName = (LPMAPIRESOLVENAME) GetProcAddress (hlibMAPI, "MAPIResolveName"))) return (FALSE);
return (TRUE); }
/*
- fSMAPIInstalled - * Purpose: * Checks the appropriate win.ini/registry value to see if Simple MAPI is * installed in the system. * * Returns: * TRUE if Simple MAPI is installed, else FALSE * */ BOOL fSMAPIInstalled(void) { #ifdef _WIN32
/* on win32, if it's NT 3.51 or lower the value to check is
win.ini \ [Mail] \ MAPI, otherwise it's a registry value HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Messaging Subsystem\MAPI */ OSVERSIONINFO osvinfo; LONG lr; HKEY hkWMS; #define MAPIVSize 8
char szMAPIValue[MAPIVSize]; DWORD dwType; DWORD cbMAPIValue = MAPIVSize;
osvinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if(!GetVersionEx(&osvinfo)) return FALSE;
if( osvinfo.dwMajorVersion > 3 || (osvinfo.dwMajorVersion == 3 && osvinfo.dwMinorVersion > 51)) { //check the registry value
lr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows Messaging Subsystem", 0, KEY_READ, &hkWMS); if(ERROR_SUCCESS == lr) { lr = RegQueryValueEx(hkWMS, "MAPI", 0, &dwType, szMAPIValue, &cbMAPIValue); RegCloseKey(hkWMS); if(ERROR_SUCCESS == lr) { Assert(dwType == REG_SZ); if(lstrcmp(szMAPIValue, "1") == 0) return TRUE; } } return FALSE; }
/* fall through*/ #endif /*_WIN32*/
/*check the win.ini value*/ return GetProfileInt("Mail", "MAPI", 0); }
void DeinitApplication () { DeinitSimpleMAPI (); }
void DeinitSimpleMAPI () { if (hlibMAPI) { FreeLibrary (hlibMAPI); hlibMAPI = 0; } }
/*
- MainWndProc - * Purpose: * Main Window Procedure for test program. * * Parameters: * hWnd * message * wParam * lParam * * Returns: * * */
LONG FAR PASCAL MainWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { ULONG ulResult;
switch (msg) { case WM_COMMAND: switch (LOWORD (wParam)) { case IDM_LOGON: if (!lhSession) { /* MAPILogon might yield control to Windows. So to prevent the user
from clicking "logon" while we are in the process of loggin on we have to disable it*/ SecureMenu(hWnd, TRUE);
if ((ulResult = MAPILogon ((ULONG) hWnd, NULL, NULL, MAPI_LOGON_UI | MAPI_NEW_SESSION, 0, &lhSession)) == SUCCESS_SUCCESS) { ToggleMenuState (hWnd, TRUE); } else { SecureMenu(hWnd, FALSE); lhSession = 0; MakeMessageBox (hWnd, ulResult, IDS_LOGONFAIL, MBS_ERROR); } } break;
case IDM_LOGOFF: if (lhSession) { MAPILogoff (lhSession, (ULONG) hWnd, 0, 0); ToggleMenuState (hWnd, FALSE); lhSession = 0; } break;
case IDM_COMPOSE: fDialogIsActive = TRUE; DialogBox (hInst, "ComposeNote", hWnd, ComposeDlgProc); fDialogIsActive = FALSE; break;
case IDM_READ: fDialogIsActive = TRUE; DialogBox (hInst, "InBox", hWnd, InBoxDlgProc); fDialogIsActive = FALSE; break;
case IDM_SEND: if(lhSession) { MapiMessage msgSend;
memset(&msgSend, 0, sizeof(MapiMessage)); fDialogIsActive = TRUE; MAPISendMail(lhSession, (ULONG)hWnd, &msgSend, MAPI_DIALOG, 0L); fDialogIsActive = FALSE; } break;
case IDM_ADDRBOOK: if (lhSession) { fDialogIsActive = TRUE; if ((ulResult = MAPIAddress (lhSession, (ULONG) hWnd, NULL, 0, NULL, 0, NULL, 0, 0, NULL, NULL))) { if (ulResult != MAPI_E_USER_ABORT) MakeMessageBox (hWnd, ulResult, IDS_ADDRBOOKFAIL, MBS_ERROR); } fDialogIsActive = FALSE; } break;
case IDM_DETAILS: if (lhSession) { fDialogIsActive = TRUE; DialogBox(hInst, "Details", hWnd, DetailsDlgProc); fDialogIsActive = FALSE; } break;
case IDM_ABOUT: fDialogIsActive = TRUE; DialogBox (hInst, "AboutBox", hWnd, AboutDlgProc); fDialogIsActive = FALSE; break;
case IDM_EXIT: if (lhSession) MAPILogoff (lhSession, (ULONG) hWnd, 0, 0);
PostQuitMessage (0); break;
default: return (DefWindowProc (hWnd, msg, wParam, lParam)); } break;
case WM_QUERYENDSESSION: {
/*
* If we have a modal dialog open (all our dialogs are modal, so * just see if we have a dialog open), veto the shutdown. */
if (fDialogIsActive) { LPCSTR szTitle = "MAPI Sample Mail Client"; char szText[256];
LoadString (hInst, IDS_DIALOGACTIVE, szText, 255);
#ifdef WIN16
MessageBox((HWND)NULL, szText, szTitle, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL); #else
MessageBoxA(NULL, szText, szTitle, MB_OK | MB_ICONSTOP | MB_TASKMODAL | MB_SETFOREGROUND); #endif
return FALSE; }
else { return TRUE; } }
case WM_ENDSESSION:
if (wParam) { DestroyWindow (hWnd); }
break;
case WM_CLOSE: case WM_DESTROY: if (lhSession) MAPILogoff (lhSession, (ULONG) hWnd, 0, 0);
PostQuitMessage (0); break;
default: return (DefWindowProc (hWnd, msg, wParam, lParam)); } return FALSE; }
/*
- AboutDlgProc - * Purpose: * About box dialog procedure * * Parameters: * hDlg * message * wParam * lParam * * Returns: * True/False * */
BOOL FAR PASCAL AboutDlgProc (HWND hDlg, UINT msg, UINT wParam, LONG lParam) {
#include <pdkver.h>
char rgchVersion[80];
switch (msg) { case WM_INITDIALOG: wsprintf(rgchVersion, "Version %d.%d.%d (%s)", rmj, rmm, rup, szVerName && *szVerName ? szVerName : "BUDDY"); SetDlgItemText(hDlg, IDC_VERSION, rgchVersion); return TRUE;
case WM_COMMAND: if (wParam == IDOK || wParam == IDCANCEL) { EndDialog (hDlg, TRUE); return TRUE; } break; } return FALSE; }
/*
- OptionsDlgProc - * Purpose: * Message Options dialog procedure * * Parameters: * hDlg * message * wParam * lParam * * Returns: * True/False * */
BOOL FAR PASCAL OptionsDlgProc (HWND hDlg, UINT msg, UINT wParam, LONG lParam) { switch (msg) { case WM_INITDIALOG: CheckDlgButton (hDlg, IDC_RETURN, !!(flSendMsgFlags & MAPI_RECEIPT_REQUESTED)); return TRUE;
case WM_COMMAND: switch (LOWORD (wParam)) { case IDOK: if (IsDlgButtonChecked (hDlg, IDC_RETURN)) flSendMsgFlags |= MAPI_RECEIPT_REQUESTED; else flSendMsgFlags &= ~MAPI_RECEIPT_REQUESTED;
case IDCANCEL: EndDialog (hDlg, TRUE); return TRUE; } break; } return FALSE; }
/*
- DetailsDlgProc - * Purpose: * User Details dialog procedure * * Parameters: * hDlg * message * wParam * lParam * * Returns: * True/False * */
BOOL FAR PASCAL DetailsDlgProc (HWND hDlg, UINT msg, UINT wParam, LONG lParam) { LPSTR lpszType = NULL; LPSTR lpszAddr = NULL; LPSTR lpszName; ULONG cRecips; ULONG ulResult; lpMapiRecipDesc lpRecip = NULL;
switch (msg) { case WM_INITDIALOG: while(!lpRecip) { if ((ulResult = MAPIAddress (lhSession, (ULONG) hDlg, "Select One User", 1, "User:", 0, NULL, 0, 0, &cRecips, &lpRecip))) { if (ulResult != MAPI_E_USER_ABORT) MakeMessageBox (hDlg, ulResult, IDS_ADDRBOOKFAIL, MBS_ERROR);
EndDialog (hDlg, TRUE); return TRUE; }
if (cRecips == 0) { EndDialog (hDlg, TRUE); return TRUE; }
if (cRecips > 1) { cRecips = 0; MAPIFreeBuffer (lpRecip); lpRecip = NULL; MakeMessageBox (hDlg, 0, IDS_DETAILS_TOO_MANY, MBS_OOPS); } } lpszName = lpRecip->lpszName; if(lpRecip->lpszAddress) { lpszType = strtok(lpRecip->lpszAddress, ":"); lpszAddr = strtok(NULL, "\n"); }
SetDlgItemText(hDlg, IDC_NAME, lpszName); SetDlgItemText(hDlg, IDC_TYPE, (lpszType ? lpszType : "MSPEER")); SetDlgItemText(hDlg, IDC_ADDR, (lpszAddr ? lpszAddr : ""));
MAPIFreeBuffer (lpRecip); return TRUE;
case WM_COMMAND: if(LOWORD(wParam) == IDC_CLOSE || LOWORD(wParam) ==IDCANCEL) { EndDialog (hDlg, TRUE); return TRUE; } break; } return FALSE; }
/*
- ComposeDlgProc - * Purpose: * Dialog procedure for the ComposeNote dialog. * * Parameters: * hDlg * message * wParam * lParam * * Returns: * True/False * */
BOOL FAR PASCAL ComposeDlgProc (HWND hDlg, UINT msg, UINT wParam, LONG lParam) { char szUnResNames[TO_EDIT_MAX]; char szDisplayNames[TO_EDIT_MAX]; /* char szAttach[FILE_ATTACH_MAX];*/ BOOL fUnResTo, fUnResCc; LONG cb, cLines; ULONG ulResult; HCURSOR hOldCur; static LPSTR lpszSubject; static LPSTR lpszNoteText; static ULONG cRecips; static ULONG cNewRecips; static ULONG cAttach; static lpMapiRecipDesc lpRecips; static lpMapiRecipDesc lpNewRecips; static lpMapiFileDesc lpAttach; ULONG idx;
switch (msg) { case WM_INITDIALOG: if (lpmsg) { /* ComposeNote is being called to either forward or reply */ /* to a message in the Inbox. So, we'll initialize the */ /* ComposeNote form with data from the global MapiMessage */
lpszSubject = lpmsg->lpszSubject; lpszNoteText = lpmsg->lpszNoteText; cRecips = lpmsg->nRecipCount; cAttach = lpmsg->nFileCount; lpRecips = lpmsg->lpRecips; lpAttach = lpmsg->lpFiles;
if (cRecips) { MakeDisplayNameStr (szDisplayNames, MAPI_TO, cRecips, lpRecips); if (*szDisplayNames) SetDlgItemText (hDlg, IDC_TO, szDisplayNames);
MakeDisplayNameStr (szDisplayNames, MAPI_CC, cRecips, lpRecips); if (*szDisplayNames) SetDlgItemText (hDlg, IDC_CC, szDisplayNames); } SetDlgItemText (hDlg, IDC_SUBJECT, lpmsg->lpszSubject); SetDlgItemText (hDlg, IDC_NOTE, lpmsg->lpszNoteText); if (!cAttach) { EnableWindow (GetDlgItem (hDlg, IDC_CATTACHMENT), FALSE); EnableWindow (GetDlgItem (hDlg, IDT_CATTACHMENT), FALSE); } else { for(idx = 0; idx < cAttach; idx++) if (lpAttach[idx].lpszFileName) SendDlgItemMessage(hDlg, IDC_CATTACHMENT, LB_ADDSTRING, 0, (LPARAM)lpAttach[idx].lpszFileName);
/*SendDlgItemMessage(hDlg, IDC_CATTACHMENT, LB_SETCURSEL, 0, 0L);*/ }
SendDlgItemMessage (hDlg, IDC_TO, EM_SETMODIFY, FALSE, 0); SendDlgItemMessage (hDlg, IDC_CC, EM_SETMODIFY, FALSE, 0); SendDlgItemMessage (hDlg, IDC_SUBJECT, EM_SETMODIFY, FALSE, 0); SendDlgItemMessage (hDlg, IDC_NOTE, EM_SETMODIFY, FALSE, 0); if(cRecips) SetFocus (GetDlgItem (hDlg, IDC_NOTE)); else SetFocus (GetDlgItem (hDlg, IDC_TO)); } else { lpmsg = (lpMapiMessage)PvAlloc(sizeof(MapiMessage));
if (!lpmsg) goto cleanup;
memset (lpmsg, 0, sizeof (MapiMessage));
lpszSubject = NULL; lpszNoteText = NULL; cRecips = 0; cAttach = 0; lpRecips = NULL; lpNewRecips = NULL; lpAttach = NULL;
lpmsg->flFlags = flSendMsgFlags; SetFocus (GetDlgItem (hDlg, IDC_TO)); } return FALSE;
case WM_COMMAND: switch (LOWORD (wParam)) { case IDC_ATTACH: if (GetNextFile (hDlg, (ULONG) -1, &cAttach, &lpAttach) == SUCCESS_SUCCESS) { /* if the first attachment */ if (cAttach == 1) { EnableWindow (GetDlgItem (hDlg, IDC_CATTACHMENT), TRUE); EnableWindow (GetDlgItem (hDlg, IDT_CATTACHMENT), TRUE); }
if (lpAttach[cAttach - 1].lpszFileName) SendDlgItemMessage(hDlg, IDC_CATTACHMENT, LB_ADDSTRING, 0, (LPARAM)lpAttach[cAttach -1].lpszFileName);
/* Now, send a little render message to the NoteText edit */
/*wsprintf (szAttach, "<<File: %s>>",
lpAttach[cAttach - 1].lpszFileName);
SendDlgItemMessage (hDlg, IDC_NOTE, EM_REPLACESEL, 0, (LPARAM) ((LPSTR) szAttach));*/ } break;
case IDC_ADDRBOOK: SendMessage(hDlg, WM_COMMAND, MAKELONG(IDC_RESOLVE,0), 0); ulResult = MAPIAddress (lhSession, (ULONG) hDlg, NULL, 2, NULL, cRecips, lpRecips, 0, 0, &cNewRecips, &lpNewRecips); if (ulResult) { if (ulResult != MAPI_E_USER_ABORT) MakeMessageBox (hDlg, ulResult, IDS_ADDRBOOKFAIL, MBS_ERROR); } else { if (cNewRecips) { PvFree(lpRecips); lpRecips = (lpMapiRecipDesc)PvAlloc(cNewRecips*sizeof(MapiRecipDesc)); cRecips = cNewRecips;
while(cNewRecips--) CopyRecipient(lpRecips, &lpRecips[cNewRecips], &lpNewRecips[cNewRecips]);
MAPIFreeBuffer(lpNewRecips); lpNewRecips = NULL; cNewRecips = 0;
MakeDisplayNameStr (szDisplayNames, MAPI_TO, cRecips, lpRecips); if (*szDisplayNames) SetDlgItemText (hDlg, IDC_TO, szDisplayNames);
MakeDisplayNameStr (szDisplayNames, MAPI_CC, cRecips, lpRecips); if (*szDisplayNames) SetDlgItemText (hDlg, IDC_CC, szDisplayNames);
SendDlgItemMessage (hDlg, IDC_TO, EM_SETMODIFY, FALSE, 0); SendDlgItemMessage (hDlg, IDC_CC, EM_SETMODIFY, FALSE, 0); } } break;
case IDC_OPTIONS: DialogBox (hInst, "Options", hDlg, OptionsDlgProc); break;
case IDC_SEND: case IDC_RESOLVE: fUnResTo = FALSE; fUnResCc = FALSE;
hOldCur = SetCursor(hWaitCur);
/* Get the names from the To: field and resolve them first */
/*if (SendDlgItemMessage (hDlg, IDC_TO, EM_GETMODIFY, 0, 0) && */ if (cb = SendDlgItemMessage (hDlg, IDC_TO, WM_GETTEXT, (WPARAM)sizeof(szUnResNames), (LPARAM)szUnResNames)) { if (!ResolveFriendlyNames (hDlg, szUnResNames, MAPI_TO, &cRecips, &lpRecips)) { MakeDisplayNameStr (szDisplayNames, MAPI_TO, cRecips, lpRecips); if (*szDisplayNames) { if (*szUnResNames) { lstrcat (szDisplayNames, "; "); lstrcat (szDisplayNames, szUnResNames); fUnResTo = TRUE; }
SetDlgItemText (hDlg, IDC_TO, szDisplayNames); } else { if (*szUnResNames) { SetDlgItemText (hDlg, IDC_TO, szUnResNames); fUnResTo = TRUE; } } } /*SendDlgItemMessage (hDlg, IDC_TO, EM_SETMODIFY, FALSE, 0);*/ }
/* Now, get the names from the Cc: field and resolve them */
/*if (SendDlgItemMessage (hDlg, IDC_CC, EM_GETMODIFY, 0, 0) &&*/ if (cb = SendDlgItemMessage (hDlg, IDC_CC, WM_GETTEXT, (WPARAM)sizeof(szUnResNames), (LPARAM)szUnResNames)) { if (!ResolveFriendlyNames (hDlg, szUnResNames, MAPI_CC, &cRecips, &lpRecips)) { MakeDisplayNameStr (szDisplayNames, MAPI_CC, cRecips, lpRecips); if (*szDisplayNames) { if (*szUnResNames) { lstrcat (szDisplayNames, "; "); lstrcat (szDisplayNames, szUnResNames); fUnResCc = TRUE; }
SetDlgItemText (hDlg, IDC_CC, szDisplayNames); } else { if (*szUnResNames) { SetDlgItemText (hDlg, IDC_CC, szUnResNames); fUnResCc = TRUE; } } } /*SendDlgItemMessage (hDlg, IDC_CC, EM_SETMODIFY, FALSE, 0);*/ }
/* If we were just Resolving Names then we can leave now */
if (LOWORD (wParam) == IDC_RESOLVE) { SetCursor(hOldCur); break; }
if (cRecips == 0 || fUnResTo || fUnResCc) { if (!cRecips) MakeMessageBox (hDlg, 0, IDS_NORECIPS, MBS_OOPS);
if (fUnResTo) SetFocus (GetDlgItem (hDlg, IDC_TO)); else if (fUnResCc) SetFocus (GetDlgItem (hDlg, IDC_CC)); else SetFocus (GetDlgItem (hDlg, IDC_TO));
SetCursor(hOldCur); break; }
/* Everything is OK so far, lets get the Subject */ /* and the NoteText and try to send the message. */
/* Get Subject from Edit */
if (SendDlgItemMessage (hDlg, IDC_SUBJECT, EM_GETMODIFY, 0, 0)) { cb = SendDlgItemMessage (hDlg, IDC_SUBJECT, EM_LINELENGTH, 0, 0L);
PvFree(lpszSubject); lpszSubject = (LPTSTR)PvAlloc(cb + 1);
if (!lpszSubject) goto cleanup;
GetDlgItemText (hDlg, IDC_SUBJECT, lpszSubject, (int)cb+1); }
/* Get the NoteText from Edit */
if (SendDlgItemMessage (hDlg, IDC_NOTE, EM_GETMODIFY, 0, 0)) { cLines = SendDlgItemMessage (hDlg, IDC_NOTE, EM_GETLINECOUNT, 0, 0L);
if (cLines) { /* Get the total number of bytes in the multi-line */
cb = SendDlgItemMessage (hDlg, IDC_NOTE, EM_LINEINDEX, (UINT)cLines - 1, 0L); cb += SendDlgItemMessage (hDlg, IDC_NOTE, EM_LINELENGTH, (UINT)cb, 0L);
/* The next line is to account for CR-LF pairs per line. */
cb += cLines * 2;
PvFree(lpszNoteText); lpszNoteText = (LPTSTR)PvAlloc(cb + 1);
if (!lpszNoteText) goto cleanup;
/* Get the Note Text from the edit */
GetDlgItemText (hDlg, IDC_NOTE, lpszNoteText, (int)cb); } else { /* Make an empty string for NoteText */
lpszNoteText = (LPTSTR)PvAlloc(1); if (!lpszNoteText) goto cleanup; *lpszNoteText = '\0'; } }
lpmsg->lpszSubject = lpszSubject; lpmsg->lpszNoteText = lpszNoteText; lpmsg->nRecipCount = cRecips; lpmsg->lpRecips = lpRecips; lpmsg->nFileCount = cAttach; lpmsg->lpFiles = lpAttach; lpmsg->flFlags = flSendMsgFlags;
ulResult = MAPISendMail (lhSession, (ULONG) hDlg, lpmsg, 0, 0);
LogSendMail(ulResult);
if (ulResult) { MakeMessageBox (hDlg, ulResult, IDS_SENDERROR, MBS_ERROR); SetCursor(hOldCur); break; } cleanup: SetCursor(hOldCur);
case IDCANCEL: PvFree(lpmsg->lpszMessageType); PvFree(lpmsg->lpszConversationID); PvFree(lpmsg); PvFree(lpRecips); PvFree(lpAttach); PvFree(lpszSubject); PvFree(lpszNoteText); lpmsg = NULL;
EndDialog (hDlg, TRUE); return TRUE; break;
default: break; } break; } return FALSE; }
/*
- InBoxDlgProc - * Purpose: * Dialog procedure for the InBox dialog. * * Parameters: * hDlg * message * wParam * lParam * * Returns: * True/False * */
BOOL FAR PASCAL InBoxDlgProc (HWND hDlg, UINT msg, UINT wParam, LONG lParam) { char szMsgID[512]; char szSeedMsgID[512]; LPMSGID lpMsgNode; static LPMSGID lpMsgIdList = NULL; lpMapiMessage lpMessage; ULONG ulResult; DWORD nIndex; RECT Rect; HCURSOR hOldCur;
switch (msg) { case WM_INITDIALOG: hOldCur = SetCursor(hWaitCur);
InitBmps(hDlg, IDC_MSG);
/* Populate List Box with all messages in InBox. */ /* This is a painfully slow process for now. */
ulResult = MAPIFindNext (lhSession, (ULONG) hDlg, NULL, NULL, MAPI_GUARANTEE_FIFO | MAPI_LONG_MSGID, 0, szMsgID);
while (ulResult == SUCCESS_SUCCESS) { ulResult = MAPIReadMail (lhSession, (ULONG) hDlg, szMsgID, MAPI_PEEK | MAPI_ENVELOPE_ONLY, 0, &lpMessage);
if (!ulResult) { lpMsgNode = MakeMsgNode (lpMessage, szMsgID);
if (lpMsgNode) { InsertMsgNode (lpMsgNode, &lpMsgIdList);
SendDlgItemMessage (hDlg, IDC_MSG, LB_ADDSTRING, 0, (LONG) lpMsgNode); } MAPIFreeBuffer (lpMessage); }
lstrcpy (szSeedMsgID, szMsgID); ulResult = MAPIFindNext (lhSession, (ULONG) hDlg, NULL, szSeedMsgID, MAPI_GUARANTEE_FIFO | MAPI_LONG_MSGID, 0, szMsgID); }
SetCursor(hOldCur); SetFocus (GetDlgItem (hDlg, IDC_MSG)); return TRUE; break;
case WM_SETFOCUS: SetFocus (GetDlgItem (hDlg, IDC_MSG)); break;
case WM_MEASUREITEM: /* Sets the height of the owner-drawn List-Box */ MeasureItem(hDlg, (MEASUREITEMSTRUCT *)lParam); break;
case WM_DRAWITEM: DrawItem((DRAWITEMSTRUCT *)lParam); break;
case WM_DELETEITEM: /* This message is handled by the IDC_DELETE message */ return TRUE; break;
case WM_COMMAND: switch (LOWORD (wParam)) { case IDC_NEW: hOldCur = SetCursor(hWaitCur);
ulResult = MAPIFindNext (lhSession, (ULONG) hDlg, NULL, NULL, MAPI_UNREAD_ONLY | MAPI_LONG_MSGID, 0, szMsgID);
while (ulResult == SUCCESS_SUCCESS) { if (!FindNode (lpMsgIdList, szMsgID)) { ulResult = MAPIReadMail (lhSession, (ULONG) hDlg, szMsgID, MAPI_PEEK | MAPI_ENVELOPE_ONLY, 0, &lpMessage);
if (!ulResult) { lpMsgNode = MakeMsgNode (lpMessage, szMsgID); InsertMsgNode (lpMsgNode, &lpMsgIdList);
SendDlgItemMessage (hDlg, IDC_MSG, LB_ADDSTRING, 0, (LONG) lpMsgNode);
MAPIFreeBuffer (lpMessage); } }
lstrcpy (szSeedMsgID, szMsgID); ulResult = MAPIFindNext (lhSession, (ULONG) hDlg, NULL, szSeedMsgID, MAPI_UNREAD_ONLY | MAPI_LONG_MSGID, 0, szMsgID); } SetCursor(hOldCur); break;
case IDC_MSG: if(HIWORD(wParam) != LBN_DBLCLK) break;
case IDC_READ: nIndex = SendDlgItemMessage (hDlg, IDC_MSG, LB_GETCURSEL, 0, 0);
if (nIndex == LB_ERR) break;
lpReadMsgNode = (LPMSGID) SendDlgItemMessage (hDlg, IDC_MSG, LB_GETITEMDATA, (UINT)nIndex, 0L);
if (lpReadMsgNode) DialogBox (hInst, "ReadNote", hDlg, ReadMailDlgProc);
/* Update the Messages List-Box with new icon */
SendDlgItemMessage (hDlg, IDC_MSG, LB_GETITEMRECT, (UINT)nIndex, (LPARAM) &Rect); InvalidateRect(GetDlgItem(hDlg, IDC_MSG), &Rect, FALSE); break;
case IDC_DELETE: nIndex = SendDlgItemMessage (hDlg, IDC_MSG, LB_GETCURSEL, 0, 0);
if (nIndex == LB_ERR) break;
lpMsgNode = (LPMSGID) SendDlgItemMessage (hDlg, IDC_MSG, LB_GETITEMDATA, (UINT)nIndex, 0);
if (lpMsgNode) { MAPIDeleteMail (lhSession, (ULONG) hDlg, lpMsgNode->lpszMsgID, 0, 0); DeleteMsgNode (lpMsgNode, &lpMsgIdList); }
SendDlgItemMessage (hDlg, IDC_MSG, LB_DELETESTRING, (UINT)nIndex, 0); break;
case IDC_CLOSE: case IDCANCEL: FreeMsgList (lpMsgIdList); lpMsgIdList = NULL;
DeInitBmps();
EndDialog (hDlg, TRUE); return TRUE; break;
default: break; } break; }
return FALSE; }
/*
- ReadMailDlgProc - * Purpose: * Dialog procedure for the ReadMail dilaog. * * Parameters: * hDlg * message * wParam * lParam * * Returns: * True/False * */
BOOL FAR PASCAL ReadMailDlgProc (HWND hDlg, UINT msg, UINT wParam, LONG lParam) { ULONG ulResult; char szTo[TO_EDIT_MAX]; char szCc[TO_EDIT_MAX]; char szChangeMsg[512]; ULONG idx; static lpMapiMessage lpReadMsg;
switch (msg) { case WM_INITDIALOG: if (ulResult = MAPIReadMail (lhSession, (LONG) hDlg, lpReadMsgNode->lpszMsgID, 0, 0, &lpReadMsg)) { MakeMessageBox(hDlg, ulResult, IDS_READFAIL, MBS_ERROR); EndDialog (hDlg, TRUE); return TRUE; }
lpReadMsgNode->fUnRead = FALSE;
szTo[0] = '\0'; szCc[0] = '\0';
for (idx = 0; idx < lpReadMsg->nRecipCount; idx++) { if (lpReadMsg->lpRecips[idx].ulRecipClass == MAPI_TO) { lstrcat (szTo, lpReadMsg->lpRecips[idx].lpszName); lstrcat (szTo, "; "); } else if (lpReadMsg->lpRecips[idx].ulRecipClass == MAPI_CC) { lstrcat (szCc, lpReadMsg->lpRecips[idx].lpszName); lstrcat (szCc, "; "); } else { /* Must be Bcc, lets ignore it! */ } }
if(*szTo) szTo[lstrlen (szTo) - 2] = '\0'; if(*szCc) szCc[lstrlen (szCc) - 2] = '\0';
SetDlgItemText (hDlg, IDC_RFROM, (lpReadMsg->lpOriginator && lpReadMsg->lpOriginator->lpszName ? lpReadMsg->lpOriginator->lpszName : "")); SetDlgItemText (hDlg, IDC_RDATE, (lpReadMsg->lpszDateReceived ? lpReadMsg->lpszDateReceived : "")); SetDlgItemText (hDlg, IDC_RTO, szTo); SetDlgItemText (hDlg, IDC_RCC, szCc); SetDlgItemText (hDlg, IDC_RSUBJECT, (lpReadMsg->lpszSubject ? lpReadMsg->lpszSubject : "")); SetDlgItemText (hDlg, IDC_READNOTE, (lpReadMsg->lpszNoteText ? lpReadMsg->lpszNoteText : ""));
if (!lpReadMsg->nFileCount) { EnableWindow (GetDlgItem (hDlg, IDC_SAVEATTACH), FALSE); EnableWindow (GetDlgItem (hDlg, IDC_ATTACHMENT), FALSE); EnableWindow (GetDlgItem (hDlg, IDT_ATTACHMENT), FALSE); } else { for(idx = 0; idx < lpReadMsg->nFileCount; idx++) if (lpReadMsg->lpFiles[idx].lpszFileName) SendDlgItemMessage(hDlg, IDC_ATTACHMENT, LB_ADDSTRING, 0, (LPARAM)lpReadMsg->lpFiles[idx].lpszFileName);
SendDlgItemMessage(hDlg, IDC_ATTACHMENT, LB_SETCURSEL, 0, 0L); }
SetFocus (GetDlgItem (hDlg, IDC_READNOTE)); return FALSE;
case WM_COMMAND: switch (LOWORD (wParam)) { case IDC_SAVECHANGES: if (SendDlgItemMessage (hDlg, IDC_READNOTE, EM_GETMODIFY, 0, 0)) ulResult = SaveMsgChanges (hDlg, lpReadMsg, lpReadMsgNode->lpszMsgID); SendDlgItemMessage (hDlg, IDC_READNOTE, EM_SETMODIFY, 0, 0); break;
case IDC_ATTACHMENT: if(HIWORD(wParam) != LBN_DBLCLK) break;
case IDC_SAVEATTACH: idx = SendDlgItemMessage(hDlg, IDC_ATTACHMENT, LB_GETCURSEL, 0, 0L);
if(idx != LB_ERR) { SaveFileAttachments(hDlg, &lpReadMsg->lpFiles[idx]); SetFocus(GetDlgItem (hDlg, IDC_ATTACHMENT)); return FALSE;
} break;
case IDC_REPLY: case IDC_REPLYALL: case IDC_FORWARD: MakeNewMessage (lpReadMsg, LOWORD (wParam)); DialogBox (hInst, "ComposeNote", hDlg, ComposeDlgProc); break;
case IDCANCEL: if (SendDlgItemMessage (hDlg, IDC_READNOTE, EM_GETMODIFY, 0, 0)) { wsprintf (szChangeMsg, "Save changes to: '%s' in Inbox?", (lpReadMsg->lpszSubject ? lpReadMsg->lpszSubject : ""));
if (MessageBox (hDlg, szChangeMsg, "Mail", MB_YESNO) == IDYES) { ulResult = SaveMsgChanges (hDlg, lpReadMsg, lpReadMsgNode->lpszMsgID); } }
/* If there were file attachments, then delete the temps */
for(idx = 0; idx < lpReadMsg->nFileCount; idx++) if (lpReadMsg->lpFiles[idx].lpszPathName) DeleteFile(lpReadMsg->lpFiles[idx].lpszPathName);
MAPIFreeBuffer (lpReadMsg); lpReadMsg = NULL; EndDialog (hDlg, TRUE); return TRUE; } break; } return FALSE; }
/*
- MakeMessageBox - * Purpose: * Gets resource string and displays an error message box. * * Parameters: * hWnd - Handle to parent window * idString - Resource ID of message in StringTable * * Returns: * Void * */
void MakeMessageBox (HWND hWnd, ULONG ulResult, UINT idString, UINT fStyle) { char szMessage[256]; char szMapiReturn[64];
LoadString (hInst, idString, szMessage, 255);
if (ulResult) { LoadString (hInst, (UINT)ulResult, szMapiReturn, 64); lstrcat (szMessage, "\nReturn Code: "); lstrcat (szMessage, szMapiReturn); }
MessageBox (hWnd, szMessage, "Problem", fStyle); }
/*
- ResolveFriendlyNames - * Purpose: * Helper function to convert a string of ';' delimited friendly * names into an array of MapiRecipDescs. * * Side Effects: * The display string passed in is modified to contain the * friendly names of the mail users as found in the sample * address book. * * Note: * Duplicate names in the address book will result in undefined * behavior. * * Parameters: * hWnd - Handle to parent window * lpszDisplayNames - string of ';' delimited user names * ulRecipClass - either MAPI_TO, MAPI_CC, or MAPI_BCC * lpcRecips - Address of recipient count to be returned * lppRecips - Address of recipient array to be returned * * Return: * ulResult */
ULONG ResolveFriendlyNames (HWND hWnd, LPSTR lpszDisplayNames, ULONG ulRecipClass, ULONG * lpcRecips, lpMapiRecipDesc * lppRecips) { char szResolve[TO_EDIT_MAX]; LPSTR lpszNameToken; ULONG cRecips = 0; ULONG cFails = 0; ULONG ulResult; lpMapiRecipDesc lpRecip; lpMapiRecipDesc lpRecipList;
*szResolve = '\0'; lpszNameToken = strtok (lpszDisplayNames, ";\n");
while (lpszNameToken) { /* Strip leading blanks from name */
while (*lpszNameToken == ' ') lpszNameToken++;
/* Check if name has already been resolved */
if (!FNameInList (lpszNameToken, *lpcRecips, *lppRecips)) { lstrcat (szResolve, lpszNameToken); lstrcat (szResolve, "; "); cRecips++; }
/* Get Next Token */
lpszNameToken = strtok (NULL, ";\n"); }
*lpszDisplayNames = '\0';
if (!szResolve[0]) { ulResult = SUCCESS_SUCCESS; goto err; }
szResolve[lstrlen (szResolve) - 2] = '\0';
lpRecipList = (lpMapiRecipDesc)PvAlloc((cRecips + *lpcRecips) * sizeof (MapiRecipDesc));
if (!lpRecipList) { ulResult = MAPI_E_INSUFFICIENT_MEMORY; goto err; } memset (lpRecipList, 0, (size_t)(cRecips+*lpcRecips)*sizeof(MapiRecipDesc));
cRecips = 0;
while (cRecips < *lpcRecips) { ulResult = CopyRecipient (lpRecipList, &lpRecipList[cRecips], *lppRecips + cRecips);
if (ulResult) { PvFree(lpRecipList); goto err; }
cRecips++; }
PvFree(*lppRecips);
lpszNameToken = strtok (szResolve, ";\n");
while (lpszNameToken) { /* Strip leading blanks (again) */
while (*lpszNameToken == ' ') lpszNameToken++;
ulResult = MAPIResolveName (lhSession, (ULONG) hWnd, lpszNameToken, MAPI_DIALOG, 0, &lpRecip);
if (ulResult == SUCCESS_SUCCESS) { lpRecip->ulRecipClass = ulRecipClass; ulResult = CopyRecipient (lpRecipList, &lpRecipList[cRecips], lpRecip);
MAPIFreeBuffer (lpRecip);
if (ulResult) goto cleanup;
cRecips++; } else { lstrcat (lpszDisplayNames, lpszNameToken); lstrcat (lpszDisplayNames, "; "); cFails++; } lpszNameToken = strtok (NULL, ";\n"); }
/* if cFails > 0 then we have partial success */
ulResult = SUCCESS_SUCCESS;
if (cFails) MakeMessageBox (hWnd, 0, IDS_UNRESOLVEDNAMES, MBS_INFO);
cleanup: *lpcRecips = cRecips; *lppRecips = lpRecipList; err: if (*lpszDisplayNames) lpszDisplayNames[lstrlen (lpszDisplayNames) - 2] = '\0';
return ulResult; }
/*
- CopyRecipient - * Purpose: * Called in support of ResolveFriendlyNames() to build an array * of chained MapiRecipDescs. * * Parameters: * lpParent - Parent memory that allocations get chained to * lpDest - Destination Recipient * lpSrc - Source Recipient * * Return: * ulResult */
ULONG CopyRecipient (lpMapiRecipDesc lpParent, lpMapiRecipDesc lpDest, lpMapiRecipDesc lpSrc) { lpDest->ulReserved = lpSrc->ulReserved; lpDest->ulRecipClass = lpSrc->ulRecipClass; lpDest->ulEIDSize = lpSrc->ulEIDSize;
if (lpSrc->lpszName) { lpDest->lpszName = (LPTSTR)PvAllocMore(lstrlen(lpSrc->lpszName) + 1, (LPVOID)lpParent);
if (!lpDest->lpszName) return MAPI_E_INSUFFICIENT_MEMORY;
lstrcpy (lpDest->lpszName, lpSrc->lpszName); } else lpDest->lpszName = NULL;
if (lpSrc->lpszAddress) { lpDest->lpszAddress = (LPTSTR)PvAllocMore(lstrlen (lpSrc->lpszAddress) + 1, (LPVOID)lpParent);
if (!lpDest->lpszAddress) return MAPI_E_INSUFFICIENT_MEMORY;
lstrcpy (lpDest->lpszAddress, lpSrc->lpszAddress); } else lpDest->lpszAddress = NULL;
if (lpSrc->lpEntryID) { lpDest->lpEntryID = (LPBYTE)PvAllocMore(lpSrc->ulEIDSize, (LPVOID)lpParent);
if (!lpDest->lpEntryID) return MAPI_E_INSUFFICIENT_MEMORY;
if (lpSrc->ulEIDSize) memcpy (lpDest->lpEntryID, lpSrc->lpEntryID, (size_t)lpSrc->ulEIDSize); } else lpDest->lpEntryID = NULL;
return SUCCESS_SUCCESS;
}
/*
- GetNextFile - * Purpose: * Called when user clicks 'Attach' button in Compose Note form. * We will build a chained memory chunk for mmore than one file * attachment so the memory can be freed with a single call to * PvFree. * * Parameters: * hWnd - Window handle of Compose Note dialog * nPos - Render position of attachment in Notetext. * lpcAttach - Pointer to the count of attachments. * lppAttach - Pointer to the MapiFileDesc array. * * Return: * ulResult. */
ULONG GetNextFile (HWND hWnd, ULONG nPos, ULONG * lpcAttach, lpMapiFileDesc * lppAttach) { lpMapiFileDesc lpAttach; lpMapiFileDesc lpAttachT; OPENFILENAME ofn; char szFileName[256] = ""; char szFilter[256]; static char szFileTitle[16]; static char szDirName[256] = ""; LPSTR lpszEndPath; ULONG idx; ULONG ulResult = SUCCESS_SUCCESS;
if (!szDirName[0]) GetSystemDirectory ((LPSTR) szDirName, 255); else lstrcpy (szFileName, szFileTitle);
LoadString(hInst, IDS_FILTER, szFilter, sizeof(szFilter));
for (idx = 0; szFilter[idx] != '\0'; idx++) if (szFilter[idx] == '|') szFilter[idx] = '\0';
ofn.lStructSize = sizeof (OPENFILENAME); ofn.hwndOwner = 0; ofn.hInstance = 0; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0L; ofn.nFilterIndex = 1L; ofn.lpstrFile = szFileName; ofn.nMaxFile = 256; ofn.lpstrFileTitle = szFileTitle; ofn.nMaxFileTitle = 16; ofn.lpstrInitialDir = szDirName; ofn.lpstrTitle = "Attach"; ofn.nFileOffset = 0; ofn.nFileExtension = 0; ofn.lpstrDefExt = NULL; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
if (!GetOpenFileName (&ofn)) return MAPI_USER_ABORT;
/* Save the directory for the next time we call this */
lstrcpy (szDirName, szFileName); if (lpszEndPath = strstr (szDirName, szFileTitle)) *(--lpszEndPath) = '\0';
lpAttach = (lpMapiFileDesc)PvAlloc(((*lpcAttach) + 1) * sizeof (MapiFileDesc));
if(!lpAttach) goto err;
memset (lpAttach, 0, (size_t)(*lpcAttach + 1) * sizeof (MapiFileDesc));
lpAttachT = *lppAttach;
for (idx = 0; idx < *lpcAttach; idx++) if(ulResult = CopyAttachment (lpAttach, &lpAttach[idx], &lpAttachT[idx])) goto err;
lpAttach[idx].ulReserved = 0; lpAttach[idx].flFlags = 0; lpAttach[idx].nPosition = (ULONG)(-1); lpAttach[idx].lpFileType = NULL;
lpAttach[idx].lpszPathName = (LPTSTR)PvAllocMore(lstrlen (szFileName) + 1, (LPVOID)lpAttach);
if(!lpAttach[idx].lpszPathName) goto err;
lpAttach[idx].lpszFileName = (LPTSTR)PvAllocMore(lstrlen (szFileTitle) + 1, (LPVOID)lpAttach);
if(!lpAttach[idx].lpszFileName) goto err;
lstrcpy (lpAttach[idx].lpszPathName, szFileName); lstrcpy (lpAttach[idx].lpszFileName, szFileTitle);
PvFree(lpAttachT);
*lppAttach = lpAttach; (*lpcAttach)++;
err: if(ulResult) PvFree(lpAttach);
return ulResult; }
/*
- CopyAttachment - * Purpose: * Called in support of GetNextFile() to re-build an array * of chained MapiFileDescs. * * Parameters: * lpParent - Parent memory that allocations get chained to * lpDest - Destination Recipient * lpSrc - Source Recipient * * Return: * Void. */
ULONG CopyAttachment (lpMapiFileDesc lpParent, lpMapiFileDesc lpDest, lpMapiFileDesc lpSrc) { lpDest->ulReserved = lpSrc->ulReserved; lpDest->flFlags = lpSrc->flFlags; lpDest->nPosition = lpSrc->nPosition; lpDest->lpFileType = lpSrc->lpFileType;
if (lpSrc->lpszPathName) { lpDest->lpszPathName = (LPTSTR)PvAllocMore(lstrlen (lpSrc->lpszPathName) + 1, (LPVOID)lpParent);
if (!lpDest->lpszPathName) return MAPI_E_INSUFFICIENT_MEMORY;
lstrcpy (lpDest->lpszPathName, lpSrc->lpszPathName); } else lpDest->lpszPathName = NULL;
if (lpSrc->lpszFileName) { lpDest->lpszFileName = (LPTSTR)PvAllocMore(lstrlen (lpSrc->lpszFileName) + 1, (LPVOID)lpParent);
if (!lpDest->lpszFileName) return MAPI_E_INSUFFICIENT_MEMORY;
lstrcpy (lpDest->lpszFileName, lpSrc->lpszFileName); } else lpDest->lpszFileName = NULL;
return SUCCESS_SUCCESS;
}
/*
- FNameInList - * Purpose: * To find lpszName in an array of recipients. Used to determine * if user name has already been resolved. * * Parameters: * lpszName - Friendly name to search for * cRecips - Count of recipients in lpRecips * lpRecips - Array of MapiRecipDescs * * Return: * TRUE/FALSE */
BOOL FNameInList (LPSTR lpszName, ULONG cRecips, lpMapiRecipDesc lpRecips) { /* Case sensitive compare of each friendly name in list. */
if (!cRecips || !lpRecips) return FALSE;
while (cRecips--) if (!lstrcmp (lpszName, lpRecips[cRecips].lpszName)) return TRUE;
return FALSE; }
/*
- MakeMsgNode - * Purpose: * Allocate memory for a new MSGID node and initialize its * data members to the values passed in. * * Parameters: * lpMsg - Pointer to a MapiMessage * lpszMsgID - Opaque message identifier * * Return: * lpMsgNode - Pointer to new node */
LPMSGID MakeMsgNode (lpMapiMessage lpMsg, LPSTR lpszMsgID) { LPMSGID lpMsgNode = NULL;
if (!lpMsg || !lpszMsgID) goto err;
lpMsgNode = (LPMSGID)PvAlloc(sizeof (MSGID));
if (!lpMsgNode) goto err;
memset (lpMsgNode, 0, sizeof (MSGID));
if (lpMsg->nFileCount) lpMsgNode->fHasAttach = TRUE;
if (lpMsg->flFlags & MAPI_UNREAD) lpMsgNode->fUnRead = TRUE;
lpMsgNode->lpszMsgID = (LPTSTR)PvAllocMore(lstrlen (lpszMsgID) + 1, (LPVOID)lpMsgNode);
if (!lpMsgNode->lpszMsgID) goto err;
lstrcpy (lpMsgNode->lpszMsgID, lpszMsgID);
if (lpMsg->lpOriginator && lpMsg->lpOriginator->lpszName) { lpMsgNode->lpszFrom = (LPTSTR)PvAllocMore(lstrlen(lpMsg->lpOriginator->lpszName) + 1, (LPVOID)lpMsgNode);
if (!lpMsgNode->lpszFrom) goto err;
lstrcpy (lpMsgNode->lpszFrom, lpMsg->lpOriginator->lpszName); }
if (lpMsg->lpszSubject) { lpMsgNode->lpszSubject = (LPTSTR)PvAllocMore(lstrlen (lpMsg->lpszSubject) + 1, (LPVOID)lpMsgNode);
if (!lpMsgNode->lpszSubject) goto err;
lstrcpy (lpMsgNode->lpszSubject, lpMsg->lpszSubject); }
if (lpMsg->lpszDateReceived) { lpMsgNode->lpszDateRec = (LPTSTR)PvAllocMore(lstrlen (lpMsg->lpszDateReceived) + 1, (LPVOID)lpMsgNode);
if (!lpMsgNode->lpszDateRec) goto err;
lstrcpy (lpMsgNode->lpszDateRec, lpMsg->lpszDateReceived); }
return lpMsgNode;
err: PvFree(lpMsgNode); return NULL; }
/*
- InsertMsgNode - * Purpose: * Currently (for simplicity) we will insert the nodes * at the beginning of the list. This can later be * replaced with a routine that can insert sorted on * different criteria, like DateReceived, From, or * Subject. But for now... * * Parameters: * lpMsgNode - Pointer to a MSGID node * lppMsgHead - Pointer to the head of the list * * Return: * Void. */
void InsertMsgNode (LPMSGID lpMsgNode, LPMSGID * lppMsgHead) { if (*lppMsgHead) { lpMsgNode->lpNext = *lppMsgHead; (*lppMsgHead)->lpPrev = lpMsgNode; } else lpMsgNode->lpNext = NULL;
/* The next 2 assignments are here in case the node came from somewhere */ /* other than a call to MakeMsgNode () in which case we aren't sure */ /* they're already NULL. */
lpMsgNode->lpPrev = NULL; *lppMsgHead = lpMsgNode; }
/*
- DeleteMsgNode - * Purpose: * Removes the node passed in from the list. This * may seem like a strange way to do this but it's * not, because the Owner-Drawn List Box gives us * direct access to elements in the list that makes * it easier to do things this way. * * Parameters: * lpMsgNode - Pointer to the MSGID node to delete * lppMsgHead - Pointer to the head of the list * * Return: * Void. */
void DeleteMsgNode (LPMSGID lpMsgNode, LPMSGID * lppMsgHead) { if (!lpMsgNode) return;
/* Check if we are the first node */
if (lpMsgNode->lpPrev) lpMsgNode->lpPrev->lpNext = lpMsgNode->lpNext;
/* Check if we are the last node */
if (lpMsgNode->lpNext) lpMsgNode->lpNext->lpPrev = lpMsgNode->lpPrev;
/* check if we are the only node */
if(lpMsgNode == *lppMsgHead) *lppMsgHead = NULL;
PvFree(lpMsgNode); return; }
/*
- FindNode - * Purpose: * Returns a pointer to the node containing lpszMsgID. * Returns NULL if node doesn't exist or lpszMsgID is NULL. * * Parameters: * lpMsgHead - Pointer to the head of the list * lpszMsgID - Message ID to search for * * Return: * lpMsgNode - Pointer to the node returned */
LPMSGID FindNode (LPMSGID lpMsgHead, LPSTR lpszMsgID) { if (!lpszMsgID) return NULL;
while (lpMsgHead) { if (!lstrcmp (lpMsgHead->lpszMsgID, lpszMsgID)) break;
lpMsgHead = lpMsgHead->lpNext; }
return lpMsgHead; }
/*
- FreeMsgList - * Purpose: * Walks down the MsgList and frees each node. * * Parameters: * lpMsgHead - Pointer to the head of the list * * Return: * Void. */
void FreeMsgList (LPMSGID lpMsgHead) { LPMSGID lpT;
while (lpMsgHead) { lpT = lpMsgHead; lpMsgHead = lpMsgHead->lpNext; PvFree(lpT); } }
/*
- MakeDisplayNameStr - * Purpose: * Finds all recipients of type ulRecipClass in lpRecips and adds * their friendly name to the display string. * * Parameters: * lpszDisplay - Destination string for names * ulRecipClass - Recipient types to search for * cRecips - Count of recipients in lpRecips * lpRecips - Pointer to array of MapiRecipDescs * * Return: * Void. */
void MakeDisplayNameStr (LPSTR lpszDisplay, ULONG ulRecipClass, ULONG cRecips, lpMapiRecipDesc lpRecips) { ULONG idx;
*lpszDisplay = '\0';
for (idx = 0; idx < cRecips; idx++) { if (lpRecips[idx].ulRecipClass == ulRecipClass) { lstrcat (lpszDisplay, lpRecips[idx].lpszName); lstrcat (lpszDisplay, "; "); } }
if (*lpszDisplay) lpszDisplay[lstrlen (lpszDisplay) - 2] = '\0'; }
/*
- SaveMsgChanges - * Purpose: * If while reading a message the user changes the notetext at all * then this function is called to save those changes in the Inbox. * * Parameters: * hWnd - handle to the window/dialog who called us * lpMsg - pointer to the MAPI message to be saved * lpszMsgID - ID of the message to save * * Return: * ulResult - Indicating success/failure */
ULONG SaveMsgChanges (HWND hWnd, lpMapiMessage lpMsg, LPSTR lpszMsgID) { LPSTR lpszT; LPSTR lpszNoteText = NULL; LONG cLines, cb; ULONG ulResult = MAPI_E_INSUFFICIENT_MEMORY;
lpszT = lpMsg->lpszNoteText;
cLines = SendDlgItemMessage (hWnd, IDC_READNOTE, EM_GETLINECOUNT, 0, 0L); cb = SendDlgItemMessage (hWnd, IDC_READNOTE, EM_LINEINDEX, (UINT)cLines - 1, 0L); cb += SendDlgItemMessage (hWnd, IDC_READNOTE, EM_LINELENGTH, (UINT)cb, 0L); cb += cLines * 2;
lpszNoteText = (LPTSTR)PvAlloc(cb + 1);
if (!lpszNoteText) goto err;
SendDlgItemMessage (hWnd, IDC_READNOTE, WM_GETTEXT, (WPARAM) cb, (LPARAM) lpszNoteText);
lpMsg->lpszNoteText = lpszNoteText; ulResult = MAPISaveMail (lhSession, (ULONG) hWnd, lpMsg, MAPI_LONG_MSGID, 0, lpReadMsgNode->lpszMsgID);
PvFree(lpszNoteText);
err: lpMsg->lpszNoteText = lpszT; return ulResult; }
/*
- MakeNewMessage - * Purpose: * This function is used to construct a new message for the * ComposeNote UI. This gets called as a result of a Reply, * ReplyAll, or a Forward action on a message being read. * The destination for the new message is lpmsg, the global * MapiMessage struct pointer used by ComposeNoteDlgProc. * ComposeNoteDlgProc always frees the memory consumed by * this object whether it allocated it or not. * * Parameters: * lpSrcMsg - MapiMessage to be copied * flType - Specifies the action that caused this call * either: IDC_REPLY, IDC_REPLYALL, or IDC_FORWARD * * Return: * ulResult - Indicates success/failure */
ULONG MakeNewMessage (lpMapiMessage lpSrcMsg, UINT flType) { ULONG idx; ULONG ulResult = SUCCESS_SUCCESS;
if (!lpSrcMsg) return MAPI_E_FAILURE;
lpmsg = (lpMapiMessage)PvAlloc(sizeof (MapiMessage));
if (!lpmsg) goto err;
memset (lpmsg, 0, sizeof (MapiMessage));
lpmsg->flFlags = flSendMsgFlags;
if (lpSrcMsg->lpszSubject) { lpmsg->lpszSubject = (LPTSTR)PvAlloc(lstrlen(lpSrcMsg->lpszSubject) + 5);
if (!lpmsg->lpszSubject) goto err;
if (flType == IDC_FORWARD) lstrcpy (lpmsg->lpszSubject, "FW: "); else lstrcpy (lpmsg->lpszSubject, "RE: ");
lstrcat (lpmsg->lpszSubject, lpSrcMsg->lpszSubject); }
if (lpSrcMsg->lpszNoteText) { lpmsg->lpszNoteText = (LPTSTR)PvAlloc(lstrlen(lpSrcMsg->lpszNoteText) + 32);
if (!lpmsg->lpszNoteText) goto err;
lstrcpy (lpmsg->lpszNoteText, "\r\n--------------------------\r\n"); lstrcat (lpmsg->lpszNoteText, lpSrcMsg->lpszNoteText); }
if (lpSrcMsg->lpszMessageType) { lpmsg->lpszMessageType = (LPTSTR)PvAlloc(lstrlen (lpSrcMsg->lpszMessageType) + 1);
if (!lpmsg->lpszMessageType) goto err;
lstrcpy (lpmsg->lpszMessageType, lpSrcMsg->lpszMessageType); }
if (lpSrcMsg->lpszConversationID) { lpmsg->lpszConversationID = (LPTSTR)PvAlloc(lstrlen(lpSrcMsg->lpszConversationID) + 1);
if (!lpmsg->lpszConversationID) goto err;
lstrcpy (lpmsg->lpszConversationID, lpSrcMsg->lpszConversationID); }
if (lpSrcMsg->nFileCount && flType == IDC_FORWARD ) { lpmsg->nFileCount = lpSrcMsg->nFileCount;
lpmsg->lpFiles = (lpMapiFileDesc)PvAlloc(lpmsg->nFileCount * sizeof (MapiFileDesc));
if (!lpmsg->lpFiles) goto err; memset (lpmsg->lpFiles, 0, (size_t)lpmsg->nFileCount * sizeof (MapiFileDesc));
for (idx = 0; idx < lpmsg->nFileCount; idx++) { CopyAttachment (lpmsg->lpFiles, &lpmsg->lpFiles[idx], &lpSrcMsg->lpFiles[idx]); if ((&lpmsg->lpFiles[idx])->nPosition != (ULONG) -1) { /*lpmsg->lpszNoteText[(&lpmsg->lpFiles[idx])->nPosition
+ lstrlen("\r\n--------------------------\r\n")] = '+';*/ (&lpmsg->lpFiles[idx])->nPosition = (ULONG) -1; } } }
if (flType == IDC_REPLY || flType == IDC_REPLYALL) { ULONG idxSrc;
if(lpSrcMsg->lpOriginator) lpmsg->nRecipCount = 1;
if (flType == IDC_REPLYALL) lpmsg->nRecipCount += lpSrcMsg->nRecipCount;
if(!lpmsg->nRecipCount) return ulResult;
lpmsg->lpRecips = (lpMapiRecipDesc)PvAlloc(lpmsg->nRecipCount * sizeof (MapiRecipDesc));
if (!lpmsg->lpRecips) goto err;
memset (lpmsg->lpRecips, 0, (size_t)lpmsg->nRecipCount * sizeof (MapiRecipDesc)); idx = 0;
if(lpSrcMsg->lpOriginator) { lpSrcMsg->lpOriginator->ulRecipClass = MAPI_TO; CopyRecipient (lpmsg->lpRecips, lpmsg->lpRecips, lpSrcMsg->lpOriginator); lpSrcMsg->lpOriginator->ulRecipClass = MAPI_ORIG; idx = 1; }
for (idxSrc = 0; idx < lpmsg->nRecipCount; idxSrc++, idx++) CopyRecipient (lpmsg->lpRecips, &lpmsg->lpRecips[idx], &lpSrcMsg->lpRecips[idxSrc]); }
return ulResult;
err: if(lpmsg) { PvFree(lpmsg->lpszSubject); PvFree(lpmsg->lpszNoteText); PvFree(lpmsg->lpszMessageType); PvFree(lpmsg->lpszConversationID); PvFree(lpmsg->lpRecips); PvFree(lpmsg->lpFiles); PvFree(lpmsg); lpmsg = NULL; } return ulResult; }
/*
- LogSendMail - * Purpose: * Used to track how many messages were sent with this client. * This information is used strictly for gathering stats on * how many messages were pumped through the spooler/transport. * * Usage: * Add the following to the win.ini file: * [MAPI Client] * LogFile=filepath * * where: filepath can be a full UNC path or some local path & file * * Parameters: * ulResult - Currently unused; should be used to count errors * * Result: * Void. */
void LogSendMail(ULONG ulResult) { char szLogFile[128]; char szCount[32]; OFSTRUCT ofs; HFILE hf = HFILE_ERROR; int cSent = 1;
if(!GetProfileString("MAPI Client", "LogFile", "mapicli.log", szLogFile, sizeof(szLogFile))) return;
if((hf = OpenFile(szLogFile, &ofs, OF_READWRITE)) == HFILE_ERROR) { if((hf = OpenFile(szLogFile, &ofs, OF_CREATE|OF_READWRITE)) == HFILE_ERROR) return; } else { if(!_lread(hf, szCount, sizeof(szCount))) { _lclose(hf); return; }
cSent = atoi(szCount) + 1; }
wsprintf(szCount, "%d", cSent);
_llseek(hf, 0, 0);
_lwrite(hf, szCount, lstrlen(szCount)); _lclose(hf);
return; }
/*
- SaveFileAttachments - * Purpose: * Displays a 'Save As' common dialog to allow the user to save * file attachments contained in the current message. * * Parameters: * hWnd - Window handle of calling WndProc * cFiles - Count of the files in the file array * lpFiles - Array of MapiFileDescs * * Return: * Void. */
void SaveFileAttachments(HWND hWnd, lpMapiFileDesc lpFile) { OPENFILENAME ofn; char szFileName[256] = ""; char szFilter[256]; static char szFileTitle[16]; static char szDirName[256] = ""; LPSTR lpszEndPath; ULONG idx;
if (!lpFile) return;
if (!szDirName[0]) GetTempPath (sizeof(szDirName), szDirName);
LoadString(hInst, IDS_FILTER, szFilter, sizeof(szFilter));
for (idx = 0; szFilter[idx] != '\0'; idx++) if (szFilter[idx] == '|') szFilter[idx] = '\0';
lstrcpy (szFileName, lpFile->lpszFileName);
ofn.lStructSize = sizeof (OPENFILENAME); ofn.hwndOwner = hWnd; ofn.hInstance = 0; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0L; ofn.nFilterIndex = 1L; ofn.lpstrFile = szFileName; ofn.nMaxFile = sizeof(szFileName); ofn.lpstrFileTitle = szFileTitle; ofn.nMaxFileTitle = sizeof(szFileTitle); ofn.lpstrInitialDir = szDirName; ofn.lpstrTitle = "Save Attachment"; ofn.nFileOffset = 0; ofn.nFileExtension = 0; ofn.lpstrDefExt = NULL; ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
if (!GetSaveFileName (&ofn)) return;
/* Save the directory for the next time we call this */
lstrcpy (szDirName, szFileName); if (lpszEndPath = strstr (szDirName, szFileTitle)) *(--lpszEndPath) = '\0';
/* Use CopyFile to carry out the operation. */
if(!CopyFile(lpFile->lpszPathName, szFileName, FALSE)) MakeMessageBox (hWnd, 0, IDS_SAVEATTACHERROR, MBS_ERROR); }
/*
- ToggleMenuState - * Purpose: * Enables/Disables menu items depending on the session state. * * Parameters: * hWnd - handle to the window/dialog who called us * fLoggedOn - TRUE if logged on, FALSE if logged off * * Return: * Void. */
void ToggleMenuState(HWND hWnd, BOOL fLoggedOn) { EnableMenuItem (GetMenu (hWnd), IDM_LOGOFF, !fLoggedOn); EnableMenuItem (GetMenu (hWnd), IDM_COMPOSE, !fLoggedOn); EnableMenuItem (GetMenu (hWnd), IDM_READ, !fLoggedOn); EnableMenuItem (GetMenu (hWnd), IDM_SEND, !fLoggedOn); EnableMenuItem (GetMenu (hWnd), IDM_ADDRBOOK, !fLoggedOn); EnableMenuItem (GetMenu (hWnd), IDM_DETAILS, !fLoggedOn); EnableMenuItem (GetMenu (hWnd), IDM_LOGON, fLoggedOn); EnableMenuItem (GetMenu (hWnd), IDM_EXIT, FALSE); }
//
// SecureMenu
//
// Purpose:
// Enables/Disables Logon and Exit menu items.
// CMCLogon might yield control to Windows, so the user might be able to
// access the window menu (for example click Logon) after we call
// MAPILogon, but before it returns.
//
// Parameters:
// hWnd - handle to the window/dialog who called us
// fBeforeLogon - TRUE when this function is called when we are about
// to call MAPILogon, FALSE if called after logon (failed)
// if Logon succeddes ToggleMenuState is called instead of
// this function.
//
// Return:
// Void.
//
void SecureMenu(HWND hWnd, BOOL fBeforeLogon) { EnableMenuItem (GetMenu (hWnd), IDM_LOGON, fBeforeLogon); EnableMenuItem (GetMenu (hWnd), IDM_EXIT, fBeforeLogon); }
|