/* wbmapi.c -- DLL to implement an interface to simple MAPI for WordBasic
 *
 * 12-12-92
 * Initial implementation.
 *
 * 4-30-93
 * Added the MAPISetMessageType function.
 * Fixed SaveInboundMessage to save currently constructing message in inbox.
 *
 * 6-15-93
 * New fixes.
 *   MapiQueryFrom -> MapiQueryOriginator(... address)
 *   ResolveName -> ... (... address)
 *
 * 6-24-93
 * Renamed functions, Added address to queryRecipientList, fixed bug
 *  in SetRecipientsLlist, and added index to MapiDetails.
 * Also added QueryRecipientListElement, and CountRecipients.
 *
 * Cleaned up the code a little. (i.e. no compilation warnings at level 4)
 *
 * 9-9-93
 * Expose ClearRecipientList as MAPIClearRecipientList.
 *
 * 5-9-94
 * Port wbmapi.dll to 32 bit version
 * Compiling with WIN32 preprocessor symbol produces 32 bit version of WBMAPI.DLL
 * Compiling with WIN16 preprocessor symbol produces 16 bit version of WBMAPI.DLL
 * If WIN32 is not defined, then WIN16 is defined
 *
 */
 
/* config.h is located in \wdk\capi */
#include "config.h"
#include "wbmapi.h"
#include <windows.h>
#include <string.h>
#include <malloc.h>
#include <stdio.h>
#include "mapi.h"
 
BOOL WBMAPIExit(void);

#ifdef WIN16
short WINAPI LibMain(HANDLE hin, WORD w, WORD wHeap, LPSTR lpszcmd) 
{
	if (wHeap > 0)
		UnlockData(0);
	/*
	* Defeat 'not used' warnings from -W4
	*/
	if (w == wHeap && hin && lpszcmd)
		;
	return 1;
}
#endif

#ifdef WIN32
#include "mapinit.h"
HANDLE hLibrary;

PFNMAPILOGON sysLogon;
PFNMAPILOGOFF sysLogoff;
PFNMAPISENDMAIL sysSendMail;
PFNMAPISENDDOCUMENTS sysSendDocuments;
PFNMAPIFINDNEXT sysFindNext;
PFNMAPIREADMAIL sysReadMail;
PFNMAPISAVEMAIL sysSaveMail;
PFNMAPIDELETEMAIL sysDeleteMail;
PFNMAPIFREEBUFFER sysFreeBuffer;
PFNMAPIADDRESS sysAddress;
PFNMAPIDETAILS sysDetails;
PFNMAPIRESOLVENAME sysResolveName;

/* Unlike Win 3.x DLLs, which have both an initialization (LibMain) and a termination 
 * function (WEP), Windows NT calls one function, DllMain, for both purposes.
 * The ul_reason_for_call parameter indicates the reason DllMain was called:
 * initialization or termination, for a process or thread.
 */
BOOL WINAPI DllMain(HINSTANCE hModule, ULONG ul_reason_for_call, LPVOID lpvReserved) 
{
#undef _Debug
#ifdef _Debug
	char ErrString[80];
#define StringIze(x) #x
	sprintf(ErrString, "In routine %s ...", StringIze(DllMain));
	MessageBox(NULL, ErrString, "Init checking it out...", MB_OK);
#endif // _Debug

	switch (ul_reason_for_call) 
		{
		case DLL_PROCESS_ATTACH:
			if (InitMAPI() != 0)
				return ERR_LOAD_LIB;
			return 1;
			
		case DLL_PROCESS_DETACH:
			WBMAPIExit();
			return DeInitMAPI();
			
	default:
#ifdef _Debug
		sprintf(ErrString, "Default DllMain Reason: %d", ul_reason_for_call);
		MessageBox(NULL, ErrString, "General Confusion", MB_OK);
#endif // _Debug
		return 0;
		}
}

void NTErrorMessage(LPSTR lpszFunc);
void NTErrorMessage(LPSTR lpszFunc)
{
	char szBuff[80];
	DWORD dw = GetLastError();
	
	sprintf(szBuff, "%s failed: GetLastError returned %u\n", lpszFunc, dw);
	
	MessageBox(NULL, szBuff, "ERROR", MB_OK);
}
#endif // WIN32

short callcount;

short WINAPI DummyDllStatus(void) 
{
	return callcount;
}

#define IncCallcount() {callcount++;}

/*
 * DummyDllStest - canu use this to make sure that DLL is loaded, etc
 */
short WINAPI DummyDllStest(char FAR *s, short value) 
{
	const char *x="Hello World";
	
	_fstrcpy(s, x);
	return value;
}

#undef NoSysMapi
#ifdef NoSysMapi
ULONG WINAPI sysLogon(ULONG uiparam, LPSTR name, LPSTR passwd, ULONG flags, ULONG reserved, LHANDLE FAR *session);
ULONG WINAPI sysLogoff(LHANDLE handle, ULONG dlgbox, ULONG flags, ULONG reserved);
ULONG WINAPI sysFindNext(LHANDLE handle, ULONG dlgbox, LPSTR msgtype, LPSTR seed, ULONG flags, ULONG reserved, LPSTR msgid);
#endif

#undef	DummyFunctions
#ifdef	DummyFunctions
ULONG WINAPI sysLogon(ULONG uiparam, LPSTR name, LPSTR passwd, ULONG flags, ULONG reserved, LHANDLE FAR *session) {
    }
ULONG WINAPI sysLogoff(LHANDLE handle, ULONG dlgbox, ULONG flags, ULONG reserved) {
    }
ULONG WINAPI sysFindNext(LHANDLE handle, ULONG dlgbox, LPSTR msgtype, LPSTR seed, ULONG flags, ULONG reserved, LPSTR msgid) {
    }
#endif

/*
 * MapReturn - map a MAPI return value to a negative short or 0
 * -- note: must be modified if new status returns are introduced
 */
short MapReturn(ULONG err) 
{
	if (err > SUCCESS_SUCCESS && err <= MAPI_E_NOT_SUPPORTED)
		return (short) (- (short) err);
	else
		return 0;
}

/*
 * Simple data structures to maintain the session table
 *  This mapping of a long to a short is necessary to allow
 *  the overloading of the return type as session/error. Errors
 *  negative, and sessions are positive. This kind of overloading
 *  is more or less forced, because params can't be passed by reference
 *  in WB.
 *
 *  -- Marklan
 */
ULONG sessionlist[MAXSESSION];
short sessionindex;

/*
 * InternSesssion - create a new session
 */
short InternSession(ULONG session) 
{
	short value;
	
	IncCallcount();
	if (sessionindex >= MAXSESSION) 
		{
		/*
		* look for a free session somewhere in the table
		*/
		short i;
		for (i=0; i<MAXSESSION; i++) 
			{
			if (sessionlist[i] == 0) 
				{
				sessionlist[i] = session;
				return i;
				}
			}
		return MapReturn(MAPI_E_INVALID_SESSION);
		}
	sessionlist[value = sessionindex++] = session;
	return value;
}

/*
 * End a session
 */
short CancelSession(short id) 
{
	if (id < 0 || id > MAXSESSION)
		return MapReturn(MAPI_E_INVALID_SESSION);
		
	sessionlist[id] = 0;
	return 0;
}

/*
 * RedeemSession - return the handle required by MAPI
 */
ULONG RedeemSession(short id)
{
	if (id < 0 || id > MAXSESSION)
		return MapReturn(MAPI_E_INVALID_SESSION);
		
	return sessionlist[id];
}

void ClearMsgBuffer(void);

BOOL WBMAPIExit(void)
{
	short i;
	
	for (i=0; i<sessionindex; i++)
		{
		if (sessionlist[i]) 
			{
			sysLogoff(sessionlist[i], 0, 0, 0);
			CancelSession(i);
			}
		}
	return 1;
}

#ifdef WIN16
/*
 * WEP - Windows Exit Procedure
 *  -- if windows is bailing out, don't worry about it.
 *  -- do nothing, and just jump out the nearest window
 */
short WINAPI _loadds WEP(short exittype) 
{
	if (exittype == WEP_SYSTEM_EXIT)
		return 1;
		
	return WBMAPIExit();
}
#endif // WIN16

/*
 * MAPILogon - tell MAPI and create session if everything goes ok
 */
short WINAPI _loadds MAPILogon(ULONG uiparam, LPSTR name, LPSTR passwd, ULONG flags, ULONG reserved) 
{
	short value;
	ULONG session = 0;
	ULONG sysreturn;
	    
	sysreturn = sysLogon(HWND32SPECIFIC uiparam, name, passwd, flags, reserved, &session);
	value = MapReturn(sysreturn);
	if (value)
		return value;
		
	value = InternSession(session);
	return value;
}

/*
 * MAPILogoff - logoff session and and delocate session in session table
 */
short WINAPI _loadds MAPILogoff(short session, ULONG pwhan, ULONG flags, ULONG reserved) 
{
	ULONG sysreturn;
	short value;
	
	if (session < 0)
		return MapReturn(MAPI_E_INVALID_SESSION);
		
	sysreturn = sysLogoff(RedeemSession(session), HWND32SPECIFIC pwhan, flags, reserved);
	CancelSession(session);
	value = MapReturn(sysreturn);
	return value;
}

/*
 * MAPIFindNext - find the next message
 */
short WINAPI _loadds MAPIFindNext(short session, ULONG uiparam, LPSTR msgtype, LPSTR seed, ULONG flags, ULONG reserved, LPSTR msgid) 
{
	ULONG sysreturn;
	short value;
	
	if (session < 0)
		return MapReturn(MAPI_E_INVALID_SESSION);
		
	sysreturn = sysFindNext(RedeemSession(session), HWND32SPECIFIC uiparam, 
				msgtype, seed, flags, reserved, msgid);
	value = MapReturn(sysreturn);
	return value;
}

/*
 * Read mail data structures
 *  Marker is used to mark how much the user has read of the current message
 */
lpMapiMessage CurrentMsg;
ULONG Marker;
char CurrentMsgString[65];
ULONG AttachmentIndex=0;

void ClearMsgBuffer(void) 
{
	if (CurrentMsg) 
		{
		sysFreeBuffer(CurrentMsg);
		CurrentMsg = 0;
		AttachmentIndex = 0;
		}
	CurrentMsgString[0] = '\0';
}

/*
 * MAPIReadMail - get next mail message from MAPI server
 */
short WINAPI _loadds MAPIReadMail(short session, ULONG uiparam, LPSTR msgid, ULONG flags, ULONG reserved) 
{
	ULONG sysreturn;
	short value;
	
	if (session < 0)
		return MapReturn(MAPI_E_INVALID_SESSION);
		
	ClearMsgBuffer();
	sysreturn = sysReadMail(RedeemSession(session), HWND32SPECIFIC uiparam,
					msgid, flags, reserved, &CurrentMsg);
	Marker = 0;
	_fstrcpy(CurrentMsgString, msgid);
	value = MapReturn(sysreturn);
	return value;
}

/*
 * MAPIQueryDataReceived - get the current message receipt-date
 */
short WINAPI _loadds MAPIQueryDateReceived(LPSTR s) 
{
	short i;
	
	if (!CurrentMsg || !CurrentMsg->lpszDateReceived)
		return 0;
		
	for (i=0; CurrentMsg->lpszDateReceived[i]; i++)
		s[i] = CurrentMsg->lpszDateReceived[i];
	s[i] = '\0';
	
	return i;
}

/*
 * MAPIQuerySubject - get the current message subject line
 */
short WINAPI _loadds MAPIQuerySubject(LPSTR s) 
{
	short i;
	
	if (!CurrentMsg || !CurrentMsg->lpszSubject)
		return 0;
		
	for (i=0; CurrentMsg->lpszSubject[i]; i++)
		s[i] = CurrentMsg->lpszSubject[i];
	s[i] = '\0';
	
	return i;
}

void mstrcpy(LPSTR s1, LPSTR s2) 
{
    short i; 
    
    for (i=0; s1[i] = s2[i]; i++)
		;
}

/*
 * MAPIQueryOriginator - get the current message from line
 */
short WINAPI _loadds MAPIQueryOriginator(LPSTR name, LPSTR addr) 
{
	/*
	* Obscure bug in version 1, fixed here:
	* If you save a message in the inbox, and you are offline,
	* the lpszAddress will be null...
	*/
	if (!CurrentMsg || !CurrentMsg->lpOriginator ||
		!CurrentMsg->lpOriginator->lpszName ||
		!CurrentMsg->lpOriginator->lpszAddress)
		{
		return 0;
		}
	if (name)
		mstrcpy(name, CurrentMsg->lpOriginator->lpszName);
		
	if (addr)
		mstrcpy(addr, CurrentMsg->lpOriginator->lpszAddress);

	return 0;
}

/*
 * MAPIQueryAttachments - return the file flags, -1 when no more
 */
short WINAPI _loadds MAPIQueryAttachments(LPSTR path, LPSTR name, LPSTR position) 
{
	lpMapiFileDesc fp;
	
	if (!CurrentMsg)
		return -1;
		
	if (AttachmentIndex >= CurrentMsg->nFileCount)
		return -1;
		
	fp = &CurrentMsg->lpFiles[AttachmentIndex];
	_fstrcpy(path, fp->lpszPathName);
	_fstrcpy(name, fp->lpszFileName);
	wsprintf(position, "%d", fp->nPosition);
	AttachmentIndex++;
	return (short) fp->flFlags;
}

/*
 * MAPIQueryNoteText - get the next chunk from the message text of current message
 */
short WINAPI _loadds MAPIQueryNoteText(LPSTR s, short len) 
{
	short i;
	    
	if (!CurrentMsg || !CurrentMsg->lpszNoteText)
		return 0;
		
	for (i=0; CurrentMsg->lpszNoteText[Marker+i]; i++) 
		{
		if (i >= len)
			break;
		s[i] = CurrentMsg->lpszNoteText[Marker+i];
		}
	s[i] = '\0'; 
	
	if (!CurrentMsg->lpszNoteText[Marker+i]) 
		{
		Marker = 0;
		return 0;
		}
	else 
		{
		Marker += i;
		return 1;
		}
}

/*
 * data structures for setting up outbound attachments
 */
MapiFileDesc attachlist[MAXATTACHMENTS];
short OutboundAttachmentIndex;

/*
 * data structures for setting up message and sending message to MAPI
 */
MapiRecipDesc tolist[MAXRECIPIENTS];
short RecipientIndex;

MapiMessage mm;
char xname[256], yname[256];
char xaddr[256], yaddr[256];
char outboundmsgtype[256];

LPSTR StringSave(LPSTR s) 
{
	LPSTR t;
	
	if (!s)
		return ((LPSTR)0);
		
	t = _fmalloc(_fstrlen(s)+1);
	if (t == NULL)
		{
		MessageBox(NULL, "Memory allocation failed", "ERROR", MB_OK);
		return "";
		}
	_fstrcpy(t, s);
	return t;
}

void ClearRecipientList(void) 
{
	short i;
	lpMapiRecipDesc to;
	lpMapiFileDesc attach;
	
	for (i=0; i<RecipientIndex; i++) 
		{
		to = &tolist[i];
		if (to->lpszName)
			_ffree(to->lpszName);
		if (to->lpszAddress)
			_ffree(to->lpszAddress);
		to->lpszName = to->lpszAddress = 0;
		}
	RecipientIndex = 0;
	for (i=0; i<OutboundAttachmentIndex; i++) 
		{
		attach = &attachlist[i];
		if (attach->lpszPathName)
			_ffree(attach->lpszPathName);
		if (attach->lpszFileName)
			_ffree(attach->lpszFileName);
		attach->lpszPathName = attach->lpszFileName = 0;
		}
	mm.lpszMessageType = 0;
	OutboundAttachmentIndex = 0;
}

void WINAPI _loadds MAPIClearRecipientList(void) 
{
	ClearRecipientList();
}

/*
 * MAPISetRecipient - set the recipient in the current outgoing message
 */
short WINAPI _loadds MAPISetRecipient(short class, LPSTR name, LPSTR addr) 
{
	MapiRecipDesc *to;
	
	if (RecipientIndex >= MAXRECIPIENTS) 
		return MapReturn(MAPI_E_TOO_MANY_RECIPIENTS);
		
	to = &tolist[RecipientIndex++];
	to->ulRecipClass = (ULONG) class;
	to->lpszName = StringSave(name);
	to->lpszAddress = StringSave(addr);
	return 0;
}

short WINAPI _loadds MAPISetMessageType(LPSTR msgtype) 
{
	_fstrcpy(outboundmsgtype, msgtype);
	mm.lpszMessageType = outboundmsgtype;
	return 0;
}

short SetBinaryRecipient(lpMapiRecipDesc p) 
{
	MapiRecipDesc *to;
	
	if (RecipientIndex >= MAXRECIPIENTS) 
		return MapReturn(MAPI_E_TOO_MANY_RECIPIENTS);
	
	to = &tolist[RecipientIndex++];
	to->ulReserved = p->ulReserved;
	to->ulRecipClass = p->ulRecipClass;
	to->lpszName = StringSave(p->lpszName);
	to->lpszAddress = StringSave(p->lpszAddress);
	to->ulEIDSize = p->ulEIDSize;
	to->lpEntryID = p->lpEntryID;
	return 0;
}

/*
 * MAPISetAttachment
 */
short WINAPI _loadds MAPISetAttachment(LPSTR name, LPSTR path, ULONG position, ULONG flags, ULONG reserved) 
{
	lpMapiFileDesc attach;
	
	if (OutboundAttachmentIndex >= MAXATTACHMENTS) 
		return MapReturn(MAPI_E_TOO_MANY_FILES);
	
	attach = &attachlist[OutboundAttachmentIndex++];
	attach->lpszFileName = StringSave(name);
	attach->lpszPathName = StringSave(path);
	attach->nPosition = position;
	attach->flFlags = flags;
	attach->lpFileType = (LPVOID) reserved;
	return 0;
}

void PrepareMM(LPSTR subject, LPSTR text) 
{
    mm.lpszNoteText = text;
    mm.lpszSubject = subject;
    mm.lpRecips = tolist;
    mm.nRecipCount = RecipientIndex;
    mm.nFileCount = (ULONG) OutboundAttachmentIndex;
    mm.lpFiles = attachlist;
    /*
     * lpszMessageType: message type, if specified, already set
     */
}

/*
 * MAPISendMail - send the curent outgoing message to MAPI
 */
short WINAPI _loadds MAPISendMail(short session, long uiparam, LPSTR subject, LPSTR text, ULONG flags, ULONG reserved) 
{
	ULONG sysreturn;
	short value;
	
	if (session < 0)
		return MapReturn(MAPI_E_INVALID_SESSION);
		
	PrepareMM(subject, text);
	sysreturn = sysSendMail(RedeemSession(session), HWND32SPECIFIC uiparam,
			    	&mm, flags, reserved);
	ClearRecipientList();
	value = MapReturn(sysreturn);
	return value;
}

/*
 * MAPISendDocuments - tell MAPI to put up the attach documents window
 */
short WINAPI _loadds MAPISendDocuments(ULONG uiparam, LPSTR delim, LPSTR paths, LPSTR names, ULONG reserved) 
{
	ULONG sysreturn;
	short value;
	
	sysreturn = sysSendDocuments(HWND32SPECIFIC uiparam, delim, paths, names, reserved);
	value = MapReturn(sysreturn);
	return value;
}

/*
 * MAPISaveMail - tell MAPI to save the current message in the mail file
 */
short WINAPI _loadds MAPISaveMail(short session, ULONG uiparam, LPSTR subject, 
					LPSTR text, ULONG flags, ULONG reserved, LPSTR msgid) 
{
	ULONG sysreturn;
	short value;
	
	if (session < 0)
		return MapReturn(MAPI_E_INVALID_SESSION);
		
	PrepareMM(subject, text);
	sysreturn = sysSaveMail(RedeemSession(session), HWND32SPECIFIC uiparam, &mm,
					flags, reserved, msgid);
	ClearRecipientList();
	value = MapReturn(sysreturn);
	return value;
}

/*
 * MAPIDeleteMail - tell mapi to delete a message on the server
 */
short WINAPI _loadds MAPIDeleteMail(short session, ULONG uiparam, LPSTR msgid, ULONG flags, ULONG reserved) 
{
	ULONG sysreturn;
	short value;
	
	if (session < 0)
		return MapReturn(MAPI_E_INVALID_SESSION);
		
	sysreturn = sysDeleteMail(RedeemSession(session), HWND32SPECIFIC uiparam, 
					msgid, flags, reserved);
	value = MapReturn(sysreturn);
	return value;
}

/*
 * Expose the recipient data structure for resolve, address and details
 */
#define MAXRECIPDESC	10
#define FIRSTINDEX		1
lpMapiRecipDesc mrdlist[MAXRECIPDESC];
unsigned short mrdentrysize[MAXRECIPDESC];
short mrdindex=FIRSTINDEX;

/*
 * Note: If recipientlists are created by the system (i.e. by address) then
 * there should be a way to free them up, too.	There is no way to free them
 * (or even to note that they are system generated) at this time.
 */
short InternRecipient(lpMapiRecipDesc d, unsigned short size) 
{
	if (mrdindex >= MAXRECIPDESC) 
		return MapReturn(MAPI_E_TOO_MANY_RECIPIENTS);
	
	mrdlist[mrdindex] = d;
	mrdentrysize[mrdindex] = size;
	return mrdindex++;
}

lpMapiRecipDesc RedeemRecipient(short recip) 
{
	if (recip >= FIRSTINDEX && recip < mrdindex) 
		return mrdlist[recip];
		
	return 0;
}

unsigned short LookupRecipientSize(short recip) 
{
	if (recip >= FIRSTINDEX && recip < mrdindex) 
		return mrdentrysize[recip];
	
	return 0;
}

/*
 * ResolveName - resolve a name, return a recipient list
 */
short WINAPI _loadds MAPIResolveName(short session, ULONG uiparam, LPSTR name,
		  				LPSTR addr, ULONG flags, ULONG reserved)
{
	lpMapiRecipDesc p=0;
	ULONG sysreturn;
	
	if (session < 0)
		return MapReturn(MAPI_E_INVALID_SESSION);
		
	sysreturn = sysResolveName(RedeemSession(session), HWND32SPECIFIC uiparam,
		    name, flags, reserved, &p );
	if (sysreturn)
		return MapReturn(sysreturn);
	/*
	 * things went ok.
	 * intern recipient, and copy the address
	 */
	if (addr && p && p->lpszAddress)
		mstrcpy(addr, p->lpszAddress); 
		
	return InternRecipient(p, 1);
}

/*
 * MAPIDetails - display the details of a recipient list
 */
short WINAPI _loadds MAPIDetails(short session, ULONG uiparam, short recip, short recipindex, ULONG flags, ULONG reserved) 
{
	ULONG sysreturn;
	lpMapiRecipDesc p, mrd;
	
	if (session < 0)
		return MapReturn(MAPI_E_INVALID_SESSION);
		
	if (recip < 0)
		return MapReturn(MAPI_E_FAILURE);
		
	mrd = RedeemRecipient(recip);
	if (!mrd)
		return MapReturn(MAPI_E_FAILURE);
	else if (recipindex < 0 || (unsigned short) recipindex >= LookupRecipientSize(recip))
		return MapReturn(MAPI_E_FAILURE);
	else
		p = &mrd[recipindex];
	
	sysreturn = sysDetails(RedeemSession(session), HWND32SPECIFIC uiparam,
					p, flags, reserved);
	return MapReturn(sysreturn);
}

/*
 * MAPIAddress - create a new recipient list modified by the end user from primary recipient list
 */
short WINAPI _loadds MAPIAddress(short session, ULONG uiparam, LPSTR caption,
					ULONG neditfields, LPSTR labels, ULONG flags, ULONG reserved) 
{
	ULONG sysreturn;
	ULONG size;
	lpMapiRecipDesc p;
	short x, value;
	
	if (session < 0)
		return MapReturn(MAPI_E_INVALID_SESSION);
		
	sysreturn = sysAddress(RedeemSession(session), HWND32SPECIFIC uiparam,
					caption, neditfields, labels, (ULONG) RecipientIndex,
					tolist, flags, reserved, &size, &p);
	value = MapReturn(sysreturn);
	if (value < 0)
		return value;
		
	x = InternRecipient(p, (unsigned short) size);
	return x;
}

/*
 * MAPISetRecipientList - copy a recipient list to the primary address list
 *  (return error or number of elements copied)
 */
short WINAPI _loadds MAPISetRecipientList(short recip) 
{
	lpMapiRecipDesc d;
	unsigned short size, i
	;
	d = RedeemRecipient(recip);
	if (!d)
		return MapReturn(SUCCESS_SUCCESS);
		
	size = LookupRecipientSize(recip);
	for (i=0; i<size; i++) 
		{
		short t=SetBinaryRecipient(&d[i]);
		if (t)
			return (short) t;
		}
	return (short) i;
}

unsigned short listindex;
short savedrecip;
/*
 * MAPIQueryRecipientList - extract the name from a recipient list
 *  (return the message class, or -1)
 */
short WINAPI _loadds MAPIQueryRecipientList(short recip, LPSTR username, LPSTR useraddress) 
{
	lpMapiRecipDesc r;
	unsigned short size, i;
	short value;
	
	/*
	* Pass in -1 to indicate continuation
	*/
	if (recip < FIRSTINDEX)
		i = listindex;
	else 
		{
		savedrecip = recip;
		listindex = 0;
		i = 0;
		}
		
	r = RedeemRecipient(savedrecip);
	if (!r)
		return MapReturn(MAPI_E_FAILURE);
		
	size = LookupRecipientSize(savedrecip);
	if (listindex >= size)
		return -1;
		
	if (r && i < size) 
		{
		if (r[i].lpszName)
			_fstrcpy(username, r[i].lpszName);
			
		if (r[i].lpszAddress)
			_fstrcpy(useraddress, r[i].lpszAddress);
		}
	value = (short) r[i].ulRecipClass;
	listindex = ++i;
	return value;
}

/*
 * MAPIQueryRecipientListElement - extract the name from a recipient list by index
 *  (return recip-class or error status)
 */
short WINAPI _loadds MAPIQueryRecipientListElement(short recip, short index, LPSTR username, LPSTR useraddress) 
{
	lpMapiRecipDesc r;
	unsigned short size;
	short value;
	
	r = RedeemRecipient(recip);
	if (!r)
		return MapReturn(MAPI_E_FAILURE);
		
	size = LookupRecipientSize(recip);
	if ((unsigned short) index >= size)
		return MapReturn(MAPI_E_FAILURE);
		
	r = &r[index];
	if (r) 
		{
		if (r->lpszName)
			_fstrcpy(username, r->lpszName);
		
		if (r->lpszAddress)
			_fstrcpy(useraddress, r->lpszAddress);
		}
	value = (short) r->ulRecipClass;
	return value;
}

short WINAPI _loadds MAPICountRecipients(short recip) 
{
	lpMapiRecipDesc r;
	/*
	* return the outbound recipient list, if recip is negative
	*/
	if (recip < 0)
		return (short) RecipientIndex;
		
	r = RedeemRecipient(recip);
	if (!r)
		return MapReturn(MAPI_E_FAILURE);
		
	return (short) LookupRecipientSize(recip);
}

