/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  Copyright (C) 2008 OMC Denmark ApS.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

//**************************************************************************
//
// CONVENTIONS:
// All *_internal_alloc() functions are intended to be used on data
// structures which are memory managed by the caller. All variable sized
// internal data members are allocated by the function. Allocated memory
// is allocated with MAPIAllocateMore() if a non-zero "*Parent" function
// argument is present, but by MAPIAllocateBuffer() if a "Parent" argument
// exist, but is zero.
//
// The input data structure must therefore alway have the "const" specifier
// appended to its type (like "char* const Foo).
//
// There is no such limitation on internal data members of the input data
// structure such as pointers. The  content of the input data structure is
// obviously not constant. The input data structure and its content must
// be free'ed seperately.
//
//****************************************************************************


#include "definesC.h"
#include "utils/globals.h"
#include "utils/poa_utils.h"
#include "recur_utils.h"
#include "conv_utils.h"
#include "templates.i"

#include <mapiutil.h>
#include "edkcode.h"
#include <windows.h>

/*
 * Big ugly hack to easily implement content scrambling
 * in multiprocess mode. Declared in conv_utils.h
 */
bool scramble_content = false;

static inline bool is_standard_bguid(const ::BRUTUS::GUID * const id)
{
	if ((((unsigned long*)id)[1] == 0x00000000)
	    && (((unsigned long*)id)[2] == 0xC0000000)
	    && (((unsigned long*)id)[3] == 0x00000046))
		return true;

	return false;
}

static inline char *mstrdup(void *Parent,
			    const char *Src)
{
	if (!Src)
		return NULL;

	char *retval = 0;
	size_t size = sizeof(char)*(strlen(Src) + 1);

	if (Parent) {
		if (S_OK != MAPIAllocateMore(size, Parent, (void**)&retval))
			return NULL;
	} else {
		if (S_OK != MAPIAllocateBuffer(size, (void**)&retval))
			return NULL;
	}

	memcpy((void *)retval, (void *)Src, size);
	return retval;
}

ULONG proptype_brutus_to_mapi(const ::BRUTUS::PT_TYPE Brutus_Type)
{
	switch (Brutus_Type) {
	case ::BRUTUS::BRUTUS_PT_UNSPECIFIED :
		return PT_UNSPECIFIED;
	case ::BRUTUS::BRUTUS_PT_NULL :
		return PT_NULL;
	case ::BRUTUS::BRUTUS_PT_USHORT :
	case ::BRUTUS::BRUTUS_PT_SHORT :
		return PT_SHORT;
	case ::BRUTUS::BRUTUS_PT_ULONG :
	case ::BRUTUS::BRUTUS_PT_LONG :
		return PT_LONG;
	case ::BRUTUS::BRUTUS_PT_FLOAT :
		return PT_FLOAT;
	case ::BRUTUS::BRUTUS_PT_DOUBLE :
		return PT_DOUBLE;
	case ::BRUTUS::BRUTUS_PT_BOOLEAN :
		return PT_BOOLEAN;
	case ::BRUTUS::BRUTUS_PT_CURRENCY :
		return PT_CURRENCY;
	case ::BRUTUS::BRUTUS_PT_APPTIME :
		return PT_APPTIME;
	case ::BRUTUS::BRUTUS_PT_SYSTIME :
		return PT_SYSTIME;
	case ::BRUTUS::BRUTUS_PT_STRING8 :
		return PT_STRING8;
	case ::BRUTUS::BRUTUS_PT_BINARY :
		return PT_BINARY;
	case ::BRUTUS::BRUTUS_PT_UNICODE :
		return PT_UNICODE;
	case ::BRUTUS::BRUTUS_PT_CLSID :
		return PT_CLSID;
	case ::BRUTUS::BRUTUS_PT_LONGLONG :
		return PT_LONGLONG;
	case ::BRUTUS::BRUTUS_PT_MV_SHORT :
		return PT_MV_SHORT;
	case ::BRUTUS::BRUTUS_PT_MV_LONG :
		return PT_MV_LONG;
	case ::BRUTUS::BRUTUS_PT_MV_FLOAT :
		return PT_MV_FLOAT;
	case ::BRUTUS::BRUTUS_PT_MV_DOUBLE :
		return PT_MV_DOUBLE;
	case ::BRUTUS::BRUTUS_PT_MV_CURRENCY :
		return PT_MV_CURRENCY;
	case ::BRUTUS::BRUTUS_PT_MV_APPTIME :
		return PT_MV_APPTIME;
	case ::BRUTUS::BRUTUS_PT_MV_SYSTIME :
		return PT_MV_SYSTIME;
	case ::BRUTUS::BRUTUS_PT_MV_BINARY :
		return PT_MV_BINARY;
	case ::BRUTUS::BRUTUS_PT_MV_STRING8 :
		return PT_MV_STRING8;
	case ::BRUTUS::BRUTUS_PT_MV_UNICODE :
		return PT_MV_UNICODE;
	case ::BRUTUS::BRUTUS_PT_MV_CLSID :
		return PT_MV_CLSID;
	case ::BRUTUS::BRUTUS_PT_MV_LONGLONG :
		return PT_MV_LONGLONG;
	case ::BRUTUS::BRUTUS_PT_ERROR :
		return PT_ERROR;
	case ::BRUTUS::BRUTUS_PT_OBJECT :
		return PT_OBJECT;
	default :
		return PT_UNSPECIFIED;
	}
}

bool proptag_brutus_to_mapi(const ::BRUTUS::BDEFINE Brutus_Tag,
			    ULONG& Mapi_Tag)
{
	do {
		if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_UNSPECIFIED) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_UNSPECIFIED;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_NULL) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_NULL;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_SHORT) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_SHORT;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_USHORT) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_SHORT;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_LONG) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_LONG;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_ULONG) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_LONG;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_FLOAT) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_FLOAT;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_DOUBLE) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_DOUBLE;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_BOOLEAN) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_BOOLEAN;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_CURRENCY) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_CURRENCY;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_APPTIME) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_APPTIME;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_STRING8) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_STRING8;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_BINARY) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_BINARY;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_SYSTIME) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_SYSTIME;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_UNICODE) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_UNICODE;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_CLSID) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_CLSID;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_LONGLONG) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_LONGLONG;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_MV_SHORT) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_MV_SHORT;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_MV_LONG) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_MV_LONG;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_MV_FLOAT) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_MV_FLOAT;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_MV_DOUBLE) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_MV_DOUBLE;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_MV_CURRENCY) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_MV_CURRENCY;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_MV_APPTIME) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_MV_APPTIME;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_MV_SYSTIME) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_MV_SYSTIME;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_MV_BINARY) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_MV_BINARY;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_MV_STRING8) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_MV_STRING8;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_MV_UNICODE) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_MV_UNICODE;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_MV_CLSID) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_MV_CLSID;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_MV_LONGLONG) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_MV_LONGLONG;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_ERROR) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_ERROR;
			break;
		} else if ((Brutus_Tag & 0x0000FFFF) == ::BRUTUS::BRUTUS_PT_OBJECT) {
			Mapi_Tag = (Brutus_Tag & 0xFFFF0000) | PT_OBJECT;
			break;
		} else {
			char msg[128] = {0};
			sprintf_s(msg, sizeof(msg), "Unknown PropTag Type from BRUTUS : %X", (Brutus_Tag & 0x0000FFFF));
			BRUTUS_LOG_BUG(msg);

			return false;
		}

		break;
	} while (true);

	return true;
}


bool proptag_mapi_to_brutus(const ULONG Mapi_Tag,
			    ::BRUTUS::BDEFINE_out Brutus_Tag)
{
	do {
		if ((Mapi_Tag & 0x0000FFFF) == PT_UNSPECIFIED) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_UNSPECIFIED;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_NULL) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_NULL;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_SHORT) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_SHORT;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_LONG) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_LONG;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_FLOAT) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_FLOAT;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_DOUBLE) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_DOUBLE;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_BOOLEAN) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_BOOLEAN;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_CURRENCY) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_CURRENCY;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_APPTIME) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_APPTIME;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_SYSTIME) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_SYSTIME;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_STRING8) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_STRING8;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_BINARY) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_BINARY;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_UNICODE) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_UNICODE;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_CLSID) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_CLSID;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_LONGLONG) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_LONGLONG;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_MV_SHORT) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_MV_SHORT;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_MV_LONG) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_MV_LONG;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_MV_FLOAT) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_MV_FLOAT;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_MV_DOUBLE) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_MV_DOUBLE;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_MV_CURRENCY) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_MV_CURRENCY;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_MV_APPTIME) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_MV_APPTIME;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_MV_SYSTIME) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_MV_SYSTIME;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_MV_BINARY) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_MV_BINARY;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_MV_STRING8) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_MV_STRING8;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_MV_UNICODE) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_MV_UNICODE;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_MV_CLSID) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_MV_CLSID;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_MV_LONGLONG) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_MV_LONGLONG;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_ERROR) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_ERROR;
			break;
		} else if ((Mapi_Tag & 0x0000FFFF) == PT_OBJECT) {
			Brutus_Tag = (Mapi_Tag & 0xFFFF0000) | ::BRUTUS::BRUTUS_PT_OBJECT;
			break;
		} else {
			char msg[128] = {0};
			sprintf_s(msg, sizeof(msg), "Unknown PropTag Type from MAPI : %X", (Mapi_Tag & 0x0000FFFF));
			BRUTUS_LOG_BUG(msg);

			return false;
		}

		break;
	} while (true);

	return true;
}

bool proptag_array_brutus_to_mapi(const ::BRUTUS::SPropTagArray *Brutus_Tags,
				  void *Parent,
				  ::SPropTagArray*& Mapi_Tags)
{
	if (!Brutus_Tags)
		return false;

	if (!Brutus_Tags->length()) {
		Mapi_Tags = 0;
		return true;
	}

	if (Parent) {
		if (S_OK != MAPIAllocateMore((Brutus_Tags->length() + 1)*sizeof(ULONG),
					     Parent,
					     (void**)&Mapi_Tags)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer((Brutus_Tags->length() + 1)*sizeof(ULONG),
					       (void**)&Mapi_Tags)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	}

#pragma warning( disable : 6385 )

	bool retval = true;
	Mapi_Tags->cValues = Brutus_Tags->length();
	for (ULONG i = 0; i < Mapi_Tags->cValues; i++)
		retval = retval && proptag_brutus_to_mapi((*Brutus_Tags)[i], Mapi_Tags->aulPropTag[i]); // C6385

	return retval;
}

bool proptag_array_mapi_to_brutus(::SPropTagArray *Mapi_Tags,
				  ::BRUTUS::SPropTagArray & Brutus_Tags,
				  bool DeAlloc)
{
	bool retval = true;
	ULONG i = 0; // to avoid compiler error #C2362

	if (!Mapi_Tags) {
		Brutus_Tags.length(0);
		retval = true;
		goto out;
	}

	try {
		Brutus_Tags.length(Mapi_Tags->cValues);
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		retval = false;
		goto out;
	}

	::BRUTUS::BDEFINE tag;
	for (i = 0; i < Mapi_Tags->cValues; i++) {
		retval = retval && proptag_mapi_to_brutus(Mapi_Tags->aulPropTag[i], tag);
		Brutus_Tags[i] = (::CORBA::ULong)tag;
	}

out:
	if (DeAlloc)
		MAPIFreeBuffer(Mapi_Tags);

	return retval;
}


bool proptag_array_mapi_to_brutus(::SPropTagArray *Mapi_Tags,
				  ::BRUTUS::SPropTagArray_out Brutus_Tags,
				  bool DeAlloc)
{
	bool retval = true;
	ULONG i = 0; // to avoid compiler error #C2362

	::BRUTUS::SPropTagArray_var b_tags;
	try {
		b_tags = new ::BRUTUS::SPropTagArray;
		if (!Mapi_Tags) {
			b_tags->length(0);
			Brutus_Tags = b_tags._retn();
			retval = true;
			goto out;
		}
		b_tags->length(Mapi_Tags->cValues);
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		retval = false;
		goto out;
	}

	::BRUTUS::BDEFINE tag;
	for (i = 0; i < Mapi_Tags->cValues; i++) {
		retval = retval && proptag_mapi_to_brutus(Mapi_Tags->aulPropTag[i], tag);
		b_tags[i] = (::CORBA::ULong)tag;
	}
	Brutus_Tags = b_tags._retn();

out:
	if (DeAlloc)
		MAPIFreeBuffer(Mapi_Tags);

	return retval;
}

// The SPropValueArray and the SRow must be allocated
// with separate calls to MAPIAllocateBuffer.
bool srow_brutus_to_mapi(const ::BRUTUS::SRow *Brutus_Row,
			 ::SRow*& Mapi_Row)
{
	if (!Brutus_Row)
		return false;

	if (S_OK != MAPIAllocateBuffer(sizeof(::SRow),
				       (void**)&Mapi_Row)) {
		BRUTUS_LOG_ERR("No memory");
		return false;
	}

	return spropvalue_array_brutus_to_mapi(Brutus_Row,
					       0,
					       Mapi_Row->cValues,
					       Mapi_Row->lpProps);
}


bool srow_brutus_to_mapi_internal_alloc(const ::BRUTUS::SRow *Brutus_Row,
					::SRow* const Mapi_Row)
{
	if (!Brutus_Row)
		return false;

	return spropvalue_array_brutus_to_mapi(Brutus_Row,
					       0,
					       Mapi_Row->cValues,
					       Mapi_Row->lpProps);
}


bool srow_mapi_to_brutus(::SRow *Mapi_Row,
			 ::BRUTUS::SRow& Brutus_Row,
			 LPMAPISESSION Mapi_Session,
			 bool DeAlloc,
			 PortableServer::POA_ptr Poa)
{
	if (!Mapi_Row)
		return false;

	bool retval = spropvalue_array_mapi_to_brutus(Mapi_Row->cValues,
						      Mapi_Row->lpProps,
						      Brutus_Row,
						      Mapi_Session,
						      DeAlloc,
						      Poa);

	if (DeAlloc)
		MAPIFreeBuffer(Mapi_Row);

	return retval;
}

bool srow_set_brutus_to_mapi(const ::BRUTUS::SRowSet *Brutus_RowSet,
			     ::SRowSet*& Mapi_RowSet)
{
	Mapi_RowSet = NULL;
	if (!Brutus_RowSet)
		return false;

	unsigned long set_size = CbNewSRowSet(Brutus_RowSet->length());
	if (S_OK != MAPIAllocateBuffer(set_size, (void**)&Mapi_RowSet)) {
		BRUTUS_LOG_ERR("No memory");
		return false;
	}
	Mapi_RowSet->cRows = Brutus_RowSet->length();

	bool retval = true;
	::SRow *row;
	for (ULONG n = 0; n < Mapi_RowSet->cRows; n++) {
		row = &Mapi_RowSet->aRow[n];
		retval = retval && srow_brutus_to_mapi_internal_alloc(&(*Brutus_RowSet)[n],
								      row);
	}

	return retval;
}


bool srow_set_brutus_to_mapi_internal_alloc(const ::BRUTUS::SRowSet *Brutus_RowSet,
					    ::SRowSet* const Mapi_RowSet)
{
	if (!Brutus_RowSet)
		return false;

	Mapi_RowSet->cRows = Brutus_RowSet->length();
	if (!Mapi_RowSet->cRows)
		return true;

	if (S_OK != MAPIAllocateMore(Mapi_RowSet->cRows * sizeof(::SRow),
				     (void*)Mapi_RowSet,
				     (void**)&Mapi_RowSet->aRow)) {
		BRUTUS_LOG_ERR("No memory");
		return false;
	}

	bool retval = true;
	::SRow *row;
	for (ULONG n = 0; n < Mapi_RowSet->cRows; n++) {
		row = &Mapi_RowSet->aRow[n];
		retval = retval && srow_brutus_to_mapi_internal_alloc(&(*Brutus_RowSet)[n],
								      row);
	}

	return retval;
}


bool srow_set_mapi_to_brutus(::SRowSet *Mapi_RowSet,
			     ::BRUTUS::SRowSet& Brutus_RowSet,
			     LPMAPISESSION Mapi_Session,
			     bool DeAlloc,
			     PortableServer::POA_ptr Poa)
{
	if (!Mapi_RowSet)
		return false;

	Brutus_RowSet.length(Mapi_RowSet->cRows);
	if (!Mapi_RowSet->cRows) {
		return true;
	}

	bool retval = true;
	for (ULONG n = 0; n < Mapi_RowSet->cRows; n++)
		retval = retval && spropvalue_array_mapi_to_brutus(Mapi_RowSet->aRow[n].cValues,
								   Mapi_RowSet->aRow[n].lpProps,
								   Brutus_RowSet[n],
								   Mapi_Session,
								   false,
								   Poa);

	if (DeAlloc)
		FreeProws(Mapi_RowSet);

	return retval;
}

bool order_brutus_to_mapi(const ::BRUTUS::BDEFINE Brutus_Order,
			  ULONG& Mapi_Order)
{
	if (Brutus_Order == ::BRUTUS::BRUTUS_TABLE_SORT_ASCEND) {
		Mapi_Order = TABLE_SORT_ASCEND;
		return true;
	} else if (Brutus_Order == ::BRUTUS::BRUTUS_TABLE_SORT_DESCEND) {
		Mapi_Order = TABLE_SORT_DESCEND;
		return true;
	} else if (Brutus_Order == ::BRUTUS::BRUTUS_TABLE_SORT_COMBINE) {
		Mapi_Order = TABLE_SORT_COMBINE;
		return true;
	} else {
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown sort order from BRUTUS : %X", Brutus_Order);
		BRUTUS_LOG_BUG(msg);

		return false;
	}
}


bool order_mapi_to_brutus(const ULONG Mapi_Order,
			  ::BRUTUS::BDEFINE& Brutus_Order)
{
	if (Mapi_Order == TABLE_SORT_ASCEND) {
		Brutus_Order = ::BRUTUS::BRUTUS_TABLE_SORT_ASCEND;
		return true;
	} else if (Mapi_Order == TABLE_SORT_DESCEND) {
		Brutus_Order = ::BRUTUS::BRUTUS_TABLE_SORT_DESCEND;
		return true;
	} else if (Mapi_Order == TABLE_SORT_COMBINE) {
		Brutus_Order = ::BRUTUS::BRUTUS_TABLE_SORT_COMBINE;
		return true;
	} else {
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown sort order from MAPI : %X", Mapi_Order);
		BRUTUS_LOG_BUG(msg);

		return false;
	}
}


bool sort_order_brutus_to_mapi(const ::BRUTUS::SSortOrder *Brutus_Order,
			       void *Parent,
			       ::SSortOrder*& Mapi_Order)
{
	if (!Brutus_Order)
		return false;

	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(::SSortOrder),
					     Parent,
					     (void**)&Mapi_Order)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::SSortOrder),
					       (void**)&Mapi_Order)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = Mapi_Order;
	}

	order_brutus_to_mapi(Brutus_Order->ulOrder, Mapi_Order->ulOrder);
	proptag_brutus_to_mapi(Brutus_Order->ulPropTag, Mapi_Order->ulPropTag);

	return true;
}


bool sort_order_brutus_to_mapi_internal_alloc(const ::BRUTUS::SSortOrder *Brutus_Order,
					      ::SSortOrder* const Mapi_Order)
{
	if (!Brutus_Order)
		return false;

	order_brutus_to_mapi(Brutus_Order->ulPropTag, Mapi_Order->ulPropTag);
	proptag_brutus_to_mapi(Brutus_Order->ulPropTag, Mapi_Order->ulPropTag);

	return true;
}


bool sort_order_mapi_to_brutus(::SSortOrder *Mapi_Order,
			       ::BRUTUS::SSortOrder& Brutus_Order,
			       bool DeAlloc)
{
	if (!Mapi_Order)
		return false;

	order_mapi_to_brutus(Mapi_Order->ulOrder, Brutus_Order.ulOrder);
	proptag_mapi_to_brutus(Mapi_Order->ulPropTag, Brutus_Order.ulPropTag);

	if (DeAlloc)
		MAPIFreeBuffer(Mapi_Order);

	return true;
}


bool sort_order_set_brutus_to_mapi(const ::BRUTUS::SSortOrderSet *Brutus_OrderSet,
				   void *Parent,
				   ::SSortOrderSet*& Mapi_OrderSet)
{
	if (!Brutus_OrderSet)
		return false;

	ULONG size = Brutus_OrderSet->aSort.length();
	if (!size)
		return false;

	bool can_free = !Parent;
	if (Parent) {
		can_free = 0;
		if (S_OK != MAPIAllocateMore(sizeof(::SSortOrder),
					     Parent,
					     (void**)&Mapi_OrderSet)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::SSortOrder),
					       (void**)&Mapi_OrderSet)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = Mapi_OrderSet;
	}

	if (S_OK != MAPIAllocateMore(size * sizeof(::SSortOrder), Parent, (void**)&Mapi_OrderSet->aSort)) {
		if (can_free)
			MAPIFreeBuffer(Mapi_OrderSet);

		BRUTUS_LOG_ERR("No memory");
		return false;
	}

	Mapi_OrderSet->cSorts = size;
	Mapi_OrderSet->cCategories = Brutus_OrderSet->cCategories;
	Mapi_OrderSet->cExpanded = Brutus_OrderSet->cExpanded;

	bool retval = true;
	for (ULONG n = 0; n < size; n++)
		retval = retval && sort_order_brutus_to_mapi_internal_alloc(&Brutus_OrderSet->aSort[n],
									    &Mapi_OrderSet->aSort[n]);

	return retval;
}


bool sort_order_set_brutus_to_mapi_internal_alloc(const ::BRUTUS::SSortOrderSet *Brutus_OrderSet,
						  void *Parent,
						  ::SSortOrderSet* const Mapi_OrderSet)
{
	if (!Brutus_OrderSet)
		return false;

	ULONG size = Brutus_OrderSet->aSort.length();
	if (Parent) {
		if (S_OK != MAPIAllocateMore(size * sizeof(::SSortOrder),
					     Parent,
					     (void**)&Mapi_OrderSet->aSort)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(size * sizeof(::SSortOrder),
					       (void**)&Mapi_OrderSet->aSort)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = Mapi_OrderSet->aSort;
	}

	Mapi_OrderSet->cSorts = size;
	Mapi_OrderSet->cCategories = Brutus_OrderSet->cCategories;
	Mapi_OrderSet->cExpanded = Brutus_OrderSet->cExpanded;

	for (ULONG n = 0; n < size; n++)
		sort_order_brutus_to_mapi_internal_alloc(&Brutus_OrderSet->aSort[n],
							 &Mapi_OrderSet->aSort[n]);

	return true;
}


bool sort_order_set_mapi_to_brutus(::SSortOrderSet *Mapi_OrderSet,
				   ::BRUTUS::SSortOrderSet& Brutus_OrderSet,
				   bool DeAlloc)
{
	if (!Mapi_OrderSet)
		return false;

	Brutus_OrderSet.cCategories = Mapi_OrderSet->cCategories;
	Brutus_OrderSet.cExpanded = Mapi_OrderSet->cExpanded;
	Brutus_OrderSet.aSort.length(Mapi_OrderSet->cSorts);

	for (ULONG n = 0; n < Mapi_OrderSet->cSorts; n++)
		sort_order_mapi_to_brutus(&(Mapi_OrderSet->aSort[n]), Brutus_OrderSet.aSort[n], false);

	if (DeAlloc)
		MAPIFreeBuffer(Mapi_OrderSet);

	return true;
}


bool notify_mapi_to_brutus(const ULONG cNotif,
			   const ::NOTIFICATION *lpNotifications,
			   ::BRUTUS::seq_NOTIFICATION_out Brutus_Notification,
			   LPMAPISESSION Mapi_Session,
			   PortableServer::POA_ptr Poa)
{
	::BRUTUS::seq_NOTIFICATION_var notifications;
	try {
		notifications = new ::BRUTUS::seq_NOTIFICATION;
		if (!lpNotifications || !cNotif) {
			notifications->length(0);
			Brutus_Notification = notifications._retn();
			return true;
		}
		notifications->length(cNotif);
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		return false;
	}

	const ::OBJECT_NOTIFICATION *mapi_obj_notify;
	const ::ERROR_NOTIFICATION *mapi_err_notify;
	const ::EXTENDED_NOTIFICATION *mapi_ext_notify;
	const ::NEWMAIL_NOTIFICATION *mapi_newmail_notify;
	const ::TABLE_NOTIFICATION *mapi_table_notify;
	const ::STATUS_OBJECT_NOTIFICATION *mapi_status_notify;

	for (::CORBA::ULong n = 0; n < cNotif; n++) {
		switch (lpNotifications[n].ulEventType) {
		case fnevObjectCopied   :
		case fnevObjectCreated  :
		case fnevObjectDeleted  :
		case fnevObjectModified :
		case fnevObjectMoved    :
		case fnevSearchComplete :
		{
			::BRUTUS::NOTIFICATION& brutus_not = notifications[n];
				{ // instantiate the union member
					::BRUTUS::OBJECT_NOTIFICATION init_obj;
					brutus_not.info.obj(init_obj);
				}
				switch (lpNotifications[n].ulEventType) {
				case fnevObjectCopied   :
					brutus_not.ulEventType = ::BRUTUS::BRUTUS_fnevObjectCopied;
					break;
				case fnevObjectCreated  :
					brutus_not.ulEventType = ::BRUTUS::BRUTUS_fnevObjectCreated;
					break;
				case fnevObjectDeleted  :
					brutus_not.ulEventType = ::BRUTUS::BRUTUS_fnevObjectDeleted;
					break;
				case fnevObjectModified :
					brutus_not.ulEventType = ::BRUTUS::BRUTUS_fnevObjectModified;
					break;
				case fnevObjectMoved    :
					brutus_not.ulEventType = ::BRUTUS::BRUTUS_fnevObjectMoved;
					break;
				case fnevSearchComplete :
					brutus_not.ulEventType = ::BRUTUS::BRUTUS_fnevSearchComplete;
					break;
				}
				::BRUTUS::OBJECT_NOTIFICATION& brutus_obj_notify = brutus_not.info.obj();

				mapi_obj_notify = &lpNotifications[n].info.obj;

				entryid_mapi_to_brutus(mapi_obj_notify->cbEntryID,
						       mapi_obj_notify->lpEntryID,
						       brutus_obj_notify.lpEntryID);

				entryid_mapi_to_brutus(mapi_obj_notify->cbOldID,
						       mapi_obj_notify->lpOldID,
						       brutus_obj_notify.lpOldID);

				entryid_mapi_to_brutus(mapi_obj_notify->cbParentID,
						       mapi_obj_notify->lpParentID,
						       brutus_obj_notify.lpParentID);

				entryid_mapi_to_brutus(mapi_obj_notify->cbOldParentID,
						       mapi_obj_notify->lpOldParentID,
						       brutus_obj_notify.lpOldParentID);

				if (mapi_obj_notify->lpPropTagArray) {
					brutus_obj_notify.lpPropTagArray.length(mapi_obj_notify->lpPropTagArray->cValues);
					for (ULONG i = 0; i < mapi_obj_notify->lpPropTagArray->cValues; i++)
						brutus_obj_notify.lpPropTagArray[i] = mapi_obj_notify->lpPropTagArray->aulPropTag[i];
				} else
					brutus_obj_notify.lpPropTagArray.length(0);

				object_type_mapi_to_brutus(mapi_obj_notify->ulObjType,
							   brutus_obj_notify.ulObjType);
		}
		break;
		case fnevCriticalError :
		{
			::BRUTUS::NOTIFICATION& brutus_not = notifications[n];
			{ // instantiate the union member
				::BRUTUS::ERROR_NOTIFICATION init_obj;
				brutus_not.info.err(init_obj);
			}
			brutus_not.ulEventType = ::BRUTUS::BRUTUS_fnevCriticalError;

			::BRUTUS::ERROR_NOTIFICATION& brutus_err_notify = brutus_not.info.err();

			mapi_err_notify = &lpNotifications[n].info.err;

			entryid_mapi_to_brutus(mapi_err_notify->cbEntryID,
					       mapi_err_notify->lpEntryID,
					       brutus_err_notify.lpEntryID);

			brutus_err_notify.scode = mapi_err_notify->scode;

			brutus_err_notify.ulFlags = 0;
			ULONG notify_flags = mapi_err_notify->ulFlags;
			if (MAPI_UNICODE & notify_flags) {
				brutus_err_notify.ulFlags |= ::BRUTUS::BRUTUS_MAPI_UNICODE;
				FLAGS_OFF(ULONG, notify_flags, MAPI_UNICODE);
			}
			if (notify_flags) {
				char msg[128] = {0};
				sprintf_s(msg, sizeof(msg), "Unknown notification flag(s) from MAPI : %X", notify_flags);
				BRUTUS_LOG_BUG(msg);
			}

			mapierror_mapi_to_brutus(mapi_err_notify->lpMAPIError,
						 brutus_err_notify.lpMAPIError);
		}
		break;
		case fnevExtended :
		{
			::BRUTUS::NOTIFICATION& brutus_not = notifications[n];
			{ // instantiate the union member
				::BRUTUS::EXTENDED_NOTIFICATION init_obj;
				brutus_not.info.ext(init_obj);
			}
			brutus_not.ulEventType = ::BRUTUS::BRUTUS_fnevExtended;

			::BRUTUS::EXTENDED_NOTIFICATION& brutus_ext_notify = brutus_not.info.ext();
			mapi_ext_notify = &lpNotifications[n].info.ext;

			brutus_ext_notify.ulEvent = mapi_ext_notify->ulEvent;

			brutus_ext_notify.pbEventParameters.length(mapi_ext_notify->cb);
			for (ULONG i = 0; i < mapi_ext_notify->cb; i++)
				brutus_ext_notify.pbEventParameters[i] = (::CORBA::Octet)mapi_ext_notify->pbEventParameters[i];
		}
		break;
		case fnevNewMail :
		{
			::BRUTUS::NOTIFICATION& brutus_not = notifications[n];
			{ // instantiate the union member
				::BRUTUS::NEWMAIL_NOTIFICATION init_obj;
				brutus_not.info.newmail(init_obj);
			}
			brutus_not.ulEventType = ::BRUTUS::BRUTUS_fnevNewMail;
			::BRUTUS::NEWMAIL_NOTIFICATION& brutus_newmail_notify = brutus_not.info.newmail();

			mapi_newmail_notify = &lpNotifications[n].info.newmail;

			entryid_mapi_to_brutus(mapi_newmail_notify->cbEntryID,
					       mapi_newmail_notify->lpEntryID,
					       brutus_newmail_notify.lpEntryID);

			entryid_mapi_to_brutus(mapi_newmail_notify->cbParentID,
					       mapi_newmail_notify->lpParentID,
					       brutus_newmail_notify.lpParentID);

			brutus_newmail_notify.ulFlags = 0;
			brutus_newmail_notify.ulMessageFlags = 0;

			ULONG flags = mapi_newmail_notify->ulFlags;
			if (MAPI_UNICODE & flags) {
				brutus_newmail_notify.ulFlags |= ::BRUTUS::BRUTUS_MAPI_UNICODE;
				FLAGS_OFF(ULONG, flags, MAPI_UNICODE);
			}
			if (flags) {
				char msg[128] = {0};
				sprintf_s(msg, sizeof(msg), "Unknown notification flag(s) from MAPI : %X", flags);
				BRUTUS_LOG_BUG(msg);
			}

			if (!msg_flags_mapi_to_brutus(mapi_newmail_notify->ulMessageFlags,
						      brutus_newmail_notify.ulMessageFlags))
				BRUTUS_LOG_BUG("Unknown message flag(s) from MAPI");

			if (mapi_newmail_notify->lpszMessageClass)
				brutus_newmail_notify.lpszMessageClass = ::CORBA::string_dup(mapi_newmail_notify->lpszMessageClass);
			else
				brutus_newmail_notify.lpszMessageClass = ::CORBA::string_dup("");

		}
		break;
		case fnevTableModified :
		{
			::BRUTUS::NOTIFICATION& brutus_not = notifications[n];
			{ // instantiate the union member
				::BRUTUS::TABLE_NOTIFICATION init_obj;
				brutus_not.info.tab(init_obj);
			}
			brutus_not.ulEventType = ::BRUTUS::BRUTUS_fnevTableModified;
			::BRUTUS::TABLE_NOTIFICATION& brutus_tab_notify = brutus_not.info.tab();

			mapi_table_notify = &lpNotifications[n].info.tab;

			table_event_mapi_to_brutus(mapi_table_notify->ulTableEvent,
						   brutus_tab_notify.ulTableEvent);

			spropvalue_mapi_to_brutus((SPropValue*)&mapi_table_notify->propIndex,
						  brutus_tab_notify.propIndex,
						  Mapi_Session,
						  false,
						  Poa);

			spropvalue_mapi_to_brutus((SPropValue*)&mapi_table_notify->propPrior,
						  brutus_tab_notify.propPrior,
						  Mapi_Session,
						  false,
						  Poa);

			srow_mapi_to_brutus((SRow*)&mapi_table_notify->row, brutus_tab_notify.row, Mapi_Session, false, Poa);

			hresult_to_bresult(mapi_table_notify->hResult, brutus_tab_notify.hResult);
		}
		break;
		case fnevStatusObjectModified :
		{
			::BRUTUS::NOTIFICATION& brutus_not = notifications[n];
			{ // instantiate the union member
				::BRUTUS::STATUS_OBJECT_NOTIFICATION init_obj;
				brutus_not.info.statobj(init_obj);
			}
			brutus_not.ulEventType = ::BRUTUS::BRUTUS_fnevStatusObjectModified;
			::BRUTUS::STATUS_OBJECT_NOTIFICATION& brutus_status_notify = brutus_not.info.statobj();

			mapi_status_notify = &lpNotifications[n].info.statobj;
			entryid_mapi_to_brutus(mapi_status_notify->cbEntryID,
					       mapi_status_notify->lpEntryID,
					       brutus_status_notify.lpEntryID);

			spropvalue_array_mapi_to_brutus(mapi_status_notify->cValues,
							mapi_status_notify->lpPropVals,
							brutus_status_notify.lpPropVals,
							Mapi_Session,
							false,
							Poa);
		}
		break;
		default :
		{
			char msg[128] = {0};
			sprintf_s(msg, sizeof(msg), "Unknown notification type from MAPI : %X", lpNotifications[n].ulEventType);
			BRUTUS_LOG_BUG(msg);
		}
		}
	}

	Brutus_Notification = notifications._retn();
	return true;
}


bool mapierror_mapi_to_brutus(::MAPIERROR *Mapi_Error,
			      ::BRUTUS::MAPIERROR& Brutus_Error,
			      bool DeAlloc)
{
	// Only CORBA 2.3 and greater autoinitializes strings, so I do it
	// to be on the safe side.
	if (!Mapi_Error) {
		Brutus_Error.lpszError = ::CORBA::string_dup("");
		Brutus_Error.lpszComponent = ::CORBA::string_dup("");
		Brutus_Error.ulLowLevelError = 0;
		Brutus_Error.ulContext = 0;
		Brutus_Error.ulVersion = 0;
		return true;
	}

	if (Mapi_Error->lpszError)
		Brutus_Error.lpszError = ::CORBA::string_dup(Mapi_Error->lpszError);
	else
		Brutus_Error.lpszError = ::CORBA::string_dup("");

	if (Mapi_Error->lpszComponent)
		Brutus_Error.lpszComponent = ::CORBA::string_dup(Mapi_Error->lpszComponent);
	else
		Brutus_Error.lpszComponent = ::CORBA::string_dup("");

	Brutus_Error.ulVersion = (::CORBA::ULong)Mapi_Error->ulVersion;
	Brutus_Error.ulLowLevelError = (::CORBA::ULong)Mapi_Error->ulLowLevelError;
	Brutus_Error.ulContext = (::CORBA::ULong)Mapi_Error->ulContext;

	if (DeAlloc)
		MAPIFreeBuffer(Mapi_Error);

	return true;
}


bool mapierror_brutus_to_mapi(const ::BRUTUS::MAPIERROR *Brutus_Error,
			      void *Parent,
			      ::MAPIERROR*& Mapi_Error)
{
	if (!Brutus_Error)
		return false;

	// Check for NIL
	if (!strlen(Brutus_Error->lpszError)
	    && !strlen(Brutus_Error->lpszComponent)
	    && !Brutus_Error->ulVersion
	    && !Brutus_Error->ulLowLevelError
	    && !Brutus_Error->ulContext) {
		Mapi_Error = 0;
		return true;
	}

	bool can_free = true;

	if (Parent) {
		can_free = false;
		if (S_OK != MAPIAllocateMore(sizeof(::MAPIERROR),
					     Parent,
					     (void**)&Mapi_Error)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::MAPIERROR),
					       (void**)&Mapi_Error)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = Mapi_Error; // to be used by the mstring functions..
	}

	if (strlen(Brutus_Error->lpszError)) {
		Mapi_Error->lpszError = mstrdup(Parent, (const char*)Brutus_Error->lpszError);
	} else
		Mapi_Error->lpszError = mstrdup(Parent, "");
	if (strlen(Brutus_Error->lpszComponent)) {
		Mapi_Error->lpszComponent = mstrdup(Parent, (const char*)Brutus_Error->lpszComponent);
	} else
		Mapi_Error->lpszComponent = mstrdup(Parent, "");

	Mapi_Error->ulVersion = (ULONG)Brutus_Error->ulVersion;
	Mapi_Error->ulLowLevelError = (ULONG)Brutus_Error->ulLowLevelError;
	Mapi_Error->ulContext = (ULONG)Brutus_Error->ulContext;
	if (!Mapi_Error->lpszError || !Mapi_Error->lpszComponent) {
		BRUTUS_LOG_ERR("No memory");

		if (can_free)
			MAPIFreeBuffer(Mapi_Error);

		return false;
	}

	return true;
}

static inline bool valid_hex_digit(const char digit)
{
	switch (digit) {
	case '0' :
	case '1' :
	case '2' :
	case '3' :
	case '4' :
	case '5' :
	case '6' :
	case '7' :
	case '8' :
	case '9' :
	case 'a' :
	case 'A' :
	case 'b' :
	case 'B' :
	case 'c' :
	case 'C' :
	case 'd' :
	case 'D' :
	case 'e' :
	case 'E' :
	case 'f' :
	case 'F' :
		return true;
	default :
		return false;
	}
}

static inline bool brutus_uid_valid(const char *Brutus_Uid)
{
	if (!strlen(Brutus_Uid))
		return true;

	if (79 != strlen(Brutus_Uid))
		return false;

	for (int n = 0; n < 79; n++) {
		switch (n) {
		case 0 : // test for '0'
		case 5 :
		case 10 :
		case 15 :
		case 20 :
		case 25 :
		case 30 :
		case 35 :
		case 40 :
		case 45 :
		case 50 :
		case 55 :
		case 60 :
		case 65 :
		case 70 :
		case 75 :
			if (Brutus_Uid[n] == '0')
				continue;
			else
				return false;
			break;
		case 1 : // test for 'x' or 'X'
		case 6 :
		case 11 :
		case 16 :
		case 21 :
		case 26 :
		case 31 :
		case 36 :
		case 41 :
		case 46 :
		case 51 :
		case 56 :
		case 61 :
		case 66 :
		case 71 :
		case 76 :
			if ((Brutus_Uid[n] == 'x') || (Brutus_Uid[n] == 'X'))
				continue;
			else
				return false;
			break;
		case 4 : // test for ' '
		case 9 :
		case 14 :
		case 19 :
		case 24 :
		case 29 :
		case 34 :
		case 39 :
		case 44 :
		case 49 :
		case 54 :
		case 59 :
		case 64 :
		case 69 :
		case 74 :
			if (Brutus_Uid[n] == ' ')
				continue;
			else
				return false;
			break;

		default : // tst for valid hex digit
			if (valid_hex_digit(Brutus_Uid[n]))
				continue;
			else
				return false;
		}
	}

	return true;
}

bool mapiuid_mapi_to_brutus(::MAPIUID* Mapi_Uid,
			    ::BRUTUS::MAPIUID_out Brutus_Uid,
			    bool DeAlloc)
{
	::BRUTUS::MAPIUID_var retval;

	if (!Mapi_Uid) {
		retval = ::CORBA::string_dup("");
		if (!retval.in()) {
			BRUTUS_LOG_ERR("No memory");
			throw ::CORBA::NO_MEMORY();
		}
		Brutus_Uid = retval._retn();
		return true;
	} else {
		retval = ::CORBA::string_alloc(79);
		if (!retval.in()) {
			BRUTUS_LOG_ERR("No memory");
			throw ::CORBA::NO_MEMORY();
		}
	}
	memset(retval.inout(), 0, 80);

	char *pos = retval.inout();
	if (!Mapi_Uid->ab[0])
		strcat_s(pos, 80, "0x00");
	else
		sprintf_s(pos, 80, "%#.2hhx", Mapi_Uid->ab[0]);

	while (*pos)
		pos++;

	for (int n = 1; n < 16; n++) {
		if (!Mapi_Uid->ab[n])
			strcat_s(pos, 6, " 0x00");
		else {
			sprintf_s(pos, 80, " %#.2hhx", Mapi_Uid->ab[n]);
		}
		while (*pos)
			pos++;
	}

	if (DeAlloc)
		MAPIFreeBuffer((void*)Mapi_Uid);

	Brutus_Uid = retval._retn();

	return true;
}


bool mapiuid_brutus_to_mapi_no_alloc(const char *Brutus_Uid,
				     ::MAPIUID& Mapi_Uid)
{
	if (!strlen(Brutus_Uid)) {
		BRUTUS_LOG_BUG("Brutus GUID must not be NIL here");
		return false;
	}

	if (!brutus_uid_valid(Brutus_Uid))
		return false;

	const char *num = Brutus_Uid;
	char *tmp;

	for (int n = 0; n < 16; n++) {
		Mapi_Uid.ab[n] = (unsigned char)strtoul(num, &tmp, 16);
		num = tmp;
	}

	return true;
}


bool mapiuid_brutus_to_mapi(const char * Brutus_Uid,
			    void *Parent,
			    ::MAPIUID*& Mapi_Uid)
{
	if (!strlen(Brutus_Uid)) {
		Mapi_Uid = NULL;
		return true;
	}

	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(::MAPIUID),
					     Parent,
					     (void**)&Mapi_Uid)) {
			BRUTUS_LOG_ERR("No memory");
			throw ::CORBA::NO_MEMORY();
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::MAPIUID),
					       (void**)&Mapi_Uid)) {
			BRUTUS_LOG_ERR("No memory");
			throw ::CORBA::NO_MEMORY();
		}
	}

	return mapiuid_brutus_to_mapi_no_alloc(Brutus_Uid, *Mapi_Uid);
}

bool mapiuid_array_brutus_to_mapi(const ::BRUTUS::seq_MAPIUID *Brutus_Uids,
				  void *Parent,
				  ::MAPIUID*& Mapi_Uids)
{
	if (!Brutus_Uids)
		return false;

	ULONG len = Brutus_Uids->length();

	if (!len) {
		Mapi_Uids = 0;
		return true;
	}

	::CORBA::ULong n = 0;
	::CORBA::ULong m = 0;
	for (n = 0; n < len; n++) {
		if (!strlen((*Brutus_Uids)[n]))
			m++;
	}

	if (Parent) {
		if (S_OK != MAPIAllocateMore((len-m)*sizeof(::MAPIUID),
					     Parent,
					     (void**)&Mapi_Uids)) {
			BRUTUS_LOG_ERR("No memory");
			throw ::CORBA::NO_MEMORY();
		}
	} else {
		if (S_OK != MAPIAllocateBuffer((len-m)*sizeof(::MAPIUID),
					       (void**)&Mapi_Uids)) {
			BRUTUS_LOG_ERR("No memory");
			throw ::CORBA::NO_MEMORY();
		}
	}

	m = 0;
	for (n = 0; n < len; n++) {
		if (!strlen((*Brutus_Uids)[n])) {
			m++;
			continue;
		}
		if (!mapiuid_brutus_to_mapi_no_alloc((*Brutus_Uids)[n],
						     Mapi_Uids[n-m]))
			return false;
	}

	return true;
}

bool guid_mapi_to_brutus(::GUID *Mapi_Guid,
			 ::BRUTUS::GUID_out Brutus_Guid,
			 bool DeAlloc)
{
	::BRUTUS::GUID_var retval;

	if (!Mapi_Guid) {
		retval = ::CORBA::string_dup("");
		if (!retval.in()) {
			BRUTUS_LOG_ERR("No memory");
			throw ::CORBA::NO_MEMORY();
		}
		Brutus_Guid = retval._retn();
		return true;
	} else {
		retval = ::CORBA::string_alloc(64);
		if (!retval.in()) {
			BRUTUS_LOG_ERR("No memory");
			throw ::CORBA::NO_MEMORY();
		}
	}
	memset(retval.inout(), 0, 65);

	char *pos = retval.inout();
	if (!Mapi_Guid->Data1) {
		strcat_s(pos, 11, "0x00000000");
	} else {
		sprintf_s(pos, 65, "%#.8lx", Mapi_Guid->Data1);
	}
	while (*pos)
		pos++;

	if (!Mapi_Guid->Data2)
		strcat_s(pos, 8, " 0x0000");
	else {
		sprintf_s(pos, 65, " %#.4hx", Mapi_Guid->Data2);
	}
	while (*pos)
		pos++;

	if (!Mapi_Guid->Data3)
		strcat_s(pos, 8, " 0x0000");
	else {
		sprintf_s(pos, 65, " %#.4hx", Mapi_Guid->Data3);
	}
	while (*pos)
		pos++;

	for (int n = 0; n < 8; n++) {
		if (!Mapi_Guid->Data4[n])
			strcat_s(pos, 6, " 0x00");
		else {
			sprintf_s(pos, 65, " %#.2hhx", Mapi_Guid->Data4[n]);
		}
		while (*pos)
			pos++;
	}

	if (DeAlloc)
		MAPIFreeBuffer((void*)Mapi_Guid);

	Brutus_Guid = retval._retn();

	return true;
}

static inline bool brutus_guid_valid(const char *Brutus_Guid)
{
	if (!strlen(Brutus_Guid))
		return true;

	if (64 != strlen(Brutus_Guid))
		return false;

	for (int n = 0; n < 64; n++) {
		switch (n) {
		case 0 : // test for '0'
		case 11 :
		case 18 :
		case 25 :
		case 30 :
		case 35 :
		case 40 :
		case 45 :
		case 50 :
		case 55 :
		case 60 :
			if (Brutus_Guid[n] == '0')
				continue;
			else
				return false;
			break;
		case 1 : // test for 'x' or 'X'
		case 12 :
		case 19 :
		case 26 :
		case 31 :
		case 36 :
		case 41 :
		case 46 :
		case 51 :
		case 56 :
		case 61 :
			if ((Brutus_Guid[n] == 'x') || (Brutus_Guid[n] == 'X'))
				continue;
			else
				return false;
			break;
		case 10 : // test for ' '
		case 17 :
		case 24 :
		case 29 :
		case 34 :
		case 39 :
		case 44 :
		case 49 :
		case 54 :
		case 59 :
			if (Brutus_Guid[n] == ' ')
				continue;
			else
				return false;
			break;

		default : // test for valid hex digit
			if (valid_hex_digit(Brutus_Guid[n]))
				continue;
			else
				return false;
		}
	}

	return true;
}

bool guid_brutus_to_mapi_no_alloc(const char *Brutus_Guid,
				  ::GUID * const Mapi_Guid,
				  bool Input_Verified)
{
	if (!strlen(Brutus_Guid)) {
		BRUTUS_LOG_BUG("Brutus GUID must not be NIL here");
		return false;
	}

	if (!Input_Verified) {
		if (!brutus_guid_valid(Brutus_Guid))
			return false;
	}

	const char *num = Brutus_Guid;
	char *tmp;

	Mapi_Guid->Data1 = (DWORD)strtoul(num, &tmp, 16);
	num = tmp;

	Mapi_Guid->Data2 = (WORD)strtoul(num, &tmp, 16);
	num = tmp;

	Mapi_Guid->Data3 = (WORD)strtoul(num, &tmp, 16);
	num = tmp;

	int n;
	for (n = 0; n < 8; n++) {
		Mapi_Guid->Data4[n] = (BYTE)strtoul(num, &tmp, 16);
		num = tmp;
	}

	return true;
}

// Mapi_Guid is NIL upon return if Brutus_Guid is the empty string
bool guid_brutus_to_mapi(const char *Brutus_Guid,
			 void *Parent,
			 ::GUID *& Mapi_Guid)
{
	if (!brutus_guid_valid(Brutus_Guid))
		return false;

	if (!strlen(Brutus_Guid)) {
		Mapi_Guid = NULL;
		return true;
	}

	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(::GUID),
					     Parent,
					     (void**)&Mapi_Guid)) {
			BRUTUS_LOG_ERR("No memory");
			throw ::CORBA::NO_MEMORY();
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::GUID),
					       (void**)&Mapi_Guid)) {
			BRUTUS_LOG_ERR("No memory");
			throw ::CORBA::NO_MEMORY();
		}
	}

	return guid_brutus_to_mapi_no_alloc(Brutus_Guid,
					    Mapi_Guid,
					    true);
}

bool guid_array_brutus_to_mapi(const ::BRUTUS::seq_GUID *Brutus_Guids,
			       void *Parent,
			       ::GUID*& Mapi_Guids)
{
	if (!Brutus_Guids)
		return false;

	ULONG len = Brutus_Guids->length();

	if (!len) {
		Mapi_Guids = 0;
		return true;
	}

	::CORBA::ULong m = 0;
	::CORBA::ULong n;
	for (n = 0; n < len; n++) {
		if (!strlen((*Brutus_Guids)[n]))
			m++;
	}

	if (Parent) {
		if (S_OK != MAPIAllocateMore((len-m)*sizeof(::GUID),
					     Parent,
					     (void**)&Mapi_Guids)) {
			BRUTUS_LOG_ERR("No memory");
			throw ::CORBA::NO_MEMORY();
		}
	} else {
		if (S_OK != MAPIAllocateBuffer((len-m)*sizeof(::GUID),
					       (void**)&Mapi_Guids)) {
			BRUTUS_LOG_ERR("No memory");
			throw ::CORBA::NO_MEMORY();
		}
	}

	m = 0;
	for (n = 0; n < len; n++) {
		if (!strlen((*Brutus_Guids)[n])) {
			m++;
			continue;
		}
		if (!guid_brutus_to_mapi_no_alloc((*Brutus_Guids)[n],
						  &Mapi_Guids[n-m],
						  false))
			return false;
	}

	return true;
}

bool guid_brutus_to_lpbyte_no_alloc(const char *Brutus_Guid,
				    LPBYTE Mapi_LPBYTE,
				    bool Input_Verified)
{
	int n;

	::GUID mapi_guid = { 0 };
	if (!guid_brutus_to_mapi_no_alloc(Brutus_Guid, &mapi_guid, Input_Verified))
		return false;

	for (n = 0; n < 4; n++)
		Mapi_LPBYTE[n] = (unsigned char)(mapi_guid.Data1>>(32-(n+1)*8) & 0xff);

	for (n = 4; n < 6; n++)
		Mapi_LPBYTE[n] = (unsigned char)(mapi_guid.Data2>>(16-(n-3)*8) & 0xff);

	for (n = 6; n < 8; n++)
		Mapi_LPBYTE[n] = (unsigned char)(mapi_guid.Data3>>(16-(n-5)*8) & 0xff);

	for (n = 8; n < 16; n++)
		Mapi_LPBYTE[n] = (unsigned char)mapi_guid.Data4[n-8];

	return true;
}

bool guid_brutus_to_lpbyte(const char *Brutus_Guid,
			   void *Parent,
			   LPBYTE & Mapi_LPBYTE)
{
	if (!brutus_guid_valid(Brutus_Guid))
		return false;

	if (!strlen(Brutus_Guid)) {
		Mapi_LPBYTE = NULL;
		return true;
	}

	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(::GUID),
					     Parent,
					     (void**)&Mapi_LPBYTE)) {
			BRUTUS_LOG_ERR("No memory");
			throw ::CORBA::NO_MEMORY();
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::GUID),
					       (void**)&Mapi_LPBYTE)) {
			BRUTUS_LOG_ERR("No memory");
			throw ::CORBA::NO_MEMORY();
		}
	}

	return guid_brutus_to_lpbyte_no_alloc(Brutus_Guid, Mapi_LPBYTE, true);
}

// All zero's is returned if Mapi_EntryID == 0
bool entryid_mapi_to_brutus(const ULONG cbEntryId,
			    ::ENTRYID *Mapi_EntryId,
			    ::BRUTUS::ENTRYID_out Brutus_EntryId,
			    bool DeAlloc)
{
	bool retv = false;

	::BRUTUS::ENTRYID_var brutus_eid;
	try {
		brutus_eid = new ::BRUTUS::ENTRYID;
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		goto mem_out;
	}

	ULONG n;
	brutus_eid->ab.length(0);
	for (n = 0; n < 4; n++)
		brutus_eid->abFlags[n] = 0;

	if (1 == !!cbEntryId + !!Mapi_EntryId) {
		BRUTUS_LOG_BUG("Invalid input");
		goto out;
	}
	retv = true;

	if (!cbEntryId && !Mapi_EntryId)
		goto out;

	for (n = 0; n < 4; n++)
		brutus_eid->abFlags[n] = Mapi_EntryId->abFlags[n];

	brutus_eid->ab.length(cbEntryId - 4);
	for (n = 0; n < cbEntryId - 4; n++)
		brutus_eid->ab[n] = Mapi_EntryId->ab[n];
out:
	Brutus_EntryId = brutus_eid._retn();
mem_out:
	if (DeAlloc)
		MAPIFreeBuffer(Mapi_EntryId);

	return true;
}

bool entryid_mapi_to_brutus(const ULONG cbEntryId,
			    ::ENTRYID *Mapi_EntryId,
			    ::BRUTUS::ENTRYID & Brutus_EntryId,
			    bool DeAlloc)
{
	bool retv = false;

	ULONG n;
	Brutus_EntryId.ab.length(0);
	for (n = 0; n < 4; n++)
		Brutus_EntryId.abFlags[n] = 0;

	if (1 == !!cbEntryId + !!Mapi_EntryId) {
		BRUTUS_LOG_BUG("Invalid input");
		goto out;
	}
	retv = true;

	if (!cbEntryId && !Mapi_EntryId)
		goto out;

	for (n = 0; n < 4; n++)
		Brutus_EntryId.abFlags[n] = Mapi_EntryId->abFlags[n];

	Brutus_EntryId.ab.length(cbEntryId - 4);
	for (n = 0; n < cbEntryId - 4; n++)
		Brutus_EntryId.ab[n] = Mapi_EntryId->ab[n];
out:
	if (DeAlloc)
		MAPIFreeBuffer(Mapi_EntryId);

	return retv;
}

// Mapi_EntryId is NULL upon return if Brutus_EntryId contains only zero's
bool entryid_brutus_to_mapi(const ::BRUTUS::ENTRYID *Brutus_EntryId,
			    void *Parent,
			    ULONG& Mapi_EntryIdSize,
			    ::ENTRYID*& Mapi_EntryId)
{
	if (!Brutus_EntryId)
		return false;

	if (brutus_entry_id_is_nil(Brutus_EntryId)) {
		Mapi_EntryIdSize = 0;
		Mapi_EntryId = 0;
		return true;
	}

	Mapi_EntryIdSize = 4 + Brutus_EntryId->ab.length();
	if (Parent) {
		if (S_OK != MAPIAllocateMore(Mapi_EntryIdSize,
					     Parent,
					     (void**)&Mapi_EntryId)) {
			BRUTUS_LOG_ERR("No memory");
			Mapi_EntryIdSize = 0;
			Mapi_EntryId = 0;
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(Mapi_EntryIdSize,
					       (void**)&Mapi_EntryId)) {
			BRUTUS_LOG_ERR("No memory");
			Mapi_EntryIdSize = 0;
			Mapi_EntryId = 0;
			return false;
		}
	}

	ULONG n;
	for (n = 0; n < 4; n++)
		Mapi_EntryId->abFlags[n] = (unsigned char)Brutus_EntryId->abFlags[n];

#pragma warning( disable : 6386 )

	for (n = 0; n < Brutus_EntryId->ab.length(); n++)
		Mapi_EntryId->ab[n] = (unsigned char)Brutus_EntryId->ab[n]; // C6386

	return true;
}

static bool entryid_brutus_to_mapi_sbinary_internal_alloc(const ::BRUTUS::ENTRYID *Brutus_EntryID,
							  void *Parent,
							  ::SBinary *Mapi_Sbinary)
{
	if (!Mapi_Sbinary)
		return false;

	if (!Brutus_EntryID) {
		Mapi_Sbinary->cb = 0;
		Mapi_Sbinary->lpb = NULL;
		return true;
	}

	Mapi_Sbinary->cb = 4 + Brutus_EntryID->ab.length();
	if (Parent) {
		if (S_OK != MAPIAllocateMore(Mapi_Sbinary->cb,
					     Parent,
					     (void**)&Mapi_Sbinary->lpb)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(Mapi_Sbinary->cb,
					       (void**)&Mapi_Sbinary->lpb)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	}

	ULONG n;
	for (n = 0; n < 4; n++)
		Mapi_Sbinary->lpb[n] = (unsigned char)Brutus_EntryID->abFlags[n];

	for (n = 4; n < Mapi_Sbinary->cb; n++)
		Mapi_Sbinary->lpb[n] = (unsigned char)Brutus_EntryID->ab[n-4];

	return true;
}

bool entrylist_brutus_to_mapi_internal_alloc(const ::BRUTUS::seq_ENTRYID *Brutus_ENTRYLIST,
					     void *Parent,
					     ::ENTRYLIST *Mapi_ENTRYLIST)
{
	BRUTUS_LOG_INF("MARK");
	if (!Mapi_ENTRYLIST)
		return false;

	BRUTUS_LOG_INF("MARK");
	if (!Brutus_ENTRYLIST || !Brutus_ENTRYLIST->length()) {
		Mapi_ENTRYLIST->cValues = 0;
		Mapi_ENTRYLIST->lpbin = NULL;
		return true;
	}

	BRUTUS_LOG_INF("MARK");
	Mapi_ENTRYLIST->cValues = Brutus_ENTRYLIST->length();
	if (Parent) {
	BRUTUS_LOG_INF("MARK");
		if (S_OK != MAPIAllocateMore(Mapi_ENTRYLIST->cValues * sizeof(::SBinary),
					     Parent,
					     (void**)&Mapi_ENTRYLIST->lpbin)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
	BRUTUS_LOG_INF("MARK");
		if (S_OK != MAPIAllocateBuffer(Mapi_ENTRYLIST->cValues * sizeof(::SBinary),
					       (void**)&Mapi_ENTRYLIST->lpbin)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = (void*)Mapi_ENTRYLIST->lpbin;
	}
	BRUTUS_LOG_INF("MARK");

	bool retval = true;
	for (ULONG n = 0; n < Mapi_ENTRYLIST->cValues; n++) {
	BRUTUS_LOG_INF("MARK");
		retval = retval && entryid_brutus_to_mapi_sbinary_internal_alloc(&(*Brutus_ENTRYLIST)[n],
										 Parent,
										 &(Mapi_ENTRYLIST->lpbin[n]));
	}
	BRUTUS_LOG_INF("MARK");

	return retval;
}

bool entrylist_brutus_to_mapi(const ::BRUTUS::seq_ENTRYID *Brutus_ENTRYLIST,
			      void *Parent,
			      ::ENTRYLIST*& Mapi_ENTRYLIST)
{
	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(::ENTRYLIST),
					     Parent,
					     (void**)&Mapi_ENTRYLIST)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::ENTRYLIST),
					       (void**)&Mapi_ENTRYLIST)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = (void*)Mapi_ENTRYLIST;
	}

	if (!Brutus_ENTRYLIST || !Brutus_ENTRYLIST->length()) {
		Mapi_ENTRYLIST->cValues = 0;
		Mapi_ENTRYLIST->lpbin = NULL;
		return true;
	}

	return entrylist_brutus_to_mapi_internal_alloc(Brutus_ENTRYLIST, Parent, Mapi_ENTRYLIST);
}

bool table_event_mapi_to_brutus(const ULONG Mapi_TableEvent,
				::BRUTUS::BDEFINE& Brutus_TableEvent)
{
	switch (Mapi_TableEvent) {
	case TABLE_CHANGED :
		Brutus_TableEvent = ::BRUTUS::BRUTUS_TABLE_CHANGED;
		break;
	case TABLE_ERROR :
		Brutus_TableEvent = ::BRUTUS::BRUTUS_TABLE_ERROR;
		break;
	case TABLE_ROW_ADDED :
		Brutus_TableEvent = ::BRUTUS::BRUTUS_TABLE_ROW_ADDED;
		break;
	case TABLE_ROW_DELETED :
		Brutus_TableEvent = ::BRUTUS::BRUTUS_TABLE_ROW_DELETED;
		break;
	case TABLE_ROW_MODIFIED :
		Brutus_TableEvent = ::BRUTUS::BRUTUS_TABLE_ROW_MODIFIED;
		break;
	case TABLE_SORT_DONE :
		Brutus_TableEvent = ::BRUTUS::BRUTUS_TABLE_SORT_DONE;
		break;
	case TABLE_RESTRICT_DONE :
		Brutus_TableEvent = ::BRUTUS::BRUTUS_TABLE_RESTRICT_DONE;
		break;
	case TABLE_SETCOL_DONE :
		Brutus_TableEvent = ::BRUTUS::BRUTUS_TABLE_SETCOL_DONE;
		break;
	case TABLE_RELOAD :
		Brutus_TableEvent = ::BRUTUS::BRUTUS_TABLE_RELOAD;
		break;
	default :
	{
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown table event from MAPI : %X", Mapi_TableEvent);
		BRUTUS_LOG_BUG(msg);

		Brutus_TableEvent = ::BRUTUS::BRUTUS_TABLE_EVENT_UNKNOWN;
		return false;
	}
	}

	return true;
}

bool object_type_mapi_to_brutus(const unsigned long Mapi_Obj_Type,
				::BRUTUS::BDEFINE& Brutus_Obj_Type)
{
	switch (Mapi_Obj_Type) {
	case MAPI_STORE :
		Brutus_Obj_Type = ::BRUTUS::BRUTUS_MAPI_STORE;
		break;
	case MAPI_ADDRBOOK :
		Brutus_Obj_Type = ::BRUTUS::BRUTUS_MAPI_ADDRBOOK;
		break;
	case MAPI_FOLDER :
		Brutus_Obj_Type = ::BRUTUS::BRUTUS_MAPI_FOLDER;
		break;
	case MAPI_ABCONT :
		Brutus_Obj_Type = ::BRUTUS::BRUTUS_MAPI_ABCONT;
		break;
	case MAPI_MESSAGE :
		Brutus_Obj_Type = ::BRUTUS::BRUTUS_MAPI_MESSAGE;
		break;
	case MAPI_MAILUSER :
		Brutus_Obj_Type = ::BRUTUS::BRUTUS_MAPI_MAILUSER;
		break;
	case MAPI_ATTACH :
		Brutus_Obj_Type = ::BRUTUS::BRUTUS_MAPI_ATTACH;
		break;
	case MAPI_DISTLIST :
		Brutus_Obj_Type = ::BRUTUS::BRUTUS_MAPI_DISTLIST;
		break;
	case MAPI_PROFSECT :
		Brutus_Obj_Type = ::BRUTUS::BRUTUS_MAPI_PROFSECT;
		break;
	case MAPI_STATUS :
		Brutus_Obj_Type = ::BRUTUS::BRUTUS_MAPI_STATUS;
		break;
	case MAPI_SESSION :
		Brutus_Obj_Type = ::BRUTUS::BRUTUS_MAPI_SESSION;
		break;
	case MAPI_FORMINFO :
		Brutus_Obj_Type = ::BRUTUS::BRUTUS_MAPI_FORMINFO;
		break;
	default :
	{
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown object type from MAPI : %X", Mapi_Obj_Type);
		BRUTUS_LOG_BUG(msg);
	}
	Brutus_Obj_Type = ::BRUTUS::BRUTUS_MAPI_UNKNOWN_OBJECT;
	return false;
	}

	return true;
}


bool object_type_brutus_to_mapi(const ::BRUTUS::BDEFINE Brutus_Obj_Type,
				unsigned long & Mapi_Obj_Type)
{
	switch (Brutus_Obj_Type) {
	case ::BRUTUS::BRUTUS_MAPI_STORE :
		Mapi_Obj_Type = MAPI_STORE;
		break;
	case ::BRUTUS::BRUTUS_MAPI_ADDRBOOK :
		Mapi_Obj_Type = MAPI_ADDRBOOK;
		break;
	case ::BRUTUS::BRUTUS_MAPI_FOLDER :
		Mapi_Obj_Type = MAPI_FOLDER;
		break;
	case ::BRUTUS::BRUTUS_MAPI_ABCONT :
		Mapi_Obj_Type = MAPI_ABCONT;
		break;
	case ::BRUTUS::BRUTUS_MAPI_MESSAGE :
		Mapi_Obj_Type = MAPI_MESSAGE;
		break;
	case ::BRUTUS::BRUTUS_MAPI_MAILUSER :
		Mapi_Obj_Type = MAPI_MAILUSER;
		break;
	case ::BRUTUS::BRUTUS_MAPI_ATTACH :
		Mapi_Obj_Type = MAPI_ATTACH;
		break;
	case ::BRUTUS::BRUTUS_MAPI_DISTLIST :
		Mapi_Obj_Type = MAPI_DISTLIST;
		break;
	case ::BRUTUS::BRUTUS_MAPI_PROFSECT :
		Mapi_Obj_Type = MAPI_PROFSECT;
		break;
	case ::BRUTUS::BRUTUS_MAPI_STATUS :
		Mapi_Obj_Type = MAPI_STATUS;
		break;
	case ::BRUTUS::BRUTUS_MAPI_SESSION :
		Mapi_Obj_Type = MAPI_SESSION;
		break;
	case ::BRUTUS::BRUTUS_MAPI_FORMINFO :
		Mapi_Obj_Type = MAPI_FORMINFO;
		break;
	case ::BRUTUS::BRUTUS_MAPI_UNKNOWN_OBJECT :
	default :
	{
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown object type from Brutus : %X", Brutus_Obj_Type);
		BRUTUS_LOG_BUG(msg);

		return false;
	}
	}

	return true;
}


bool msg_flags_mapi_to_brutus(const ULONG Mapi_MsgFlags,
			      ::CORBA::ULong& Brutus_MsgFlags)
{
	ULONG mapi_flags = Mapi_MsgFlags;
	Brutus_MsgFlags = 0;

	if (mapi_flags & MSGFLAG_READ) {
		Brutus_MsgFlags |= ::BRUTUS::BRUTUS_MSGFLAG_READ;
		FLAGS_OFF(ULONG, mapi_flags, MSGFLAG_READ);
	}

	if (mapi_flags & MSGFLAG_UNMODIFIED) {
		Brutus_MsgFlags |= ::BRUTUS::BRUTUS_MSGFLAG_UNMODIFIED;
		FLAGS_OFF(ULONG, mapi_flags, MSGFLAG_UNMODIFIED);
	}

	if (mapi_flags & MSGFLAG_SUBMIT) {
		Brutus_MsgFlags |= ::BRUTUS::BRUTUS_MSGFLAG_SUBMIT;
		FLAGS_OFF(ULONG, mapi_flags, MSGFLAG_SUBMIT);
	}

	if (mapi_flags & MSGFLAG_UNSENT) {
		Brutus_MsgFlags |= ::BRUTUS::BRUTUS_MSGFLAG_UNSENT;
		FLAGS_OFF(ULONG, mapi_flags, MSGFLAG_UNSENT);
	}

	if (mapi_flags & MSGFLAG_HASATTACH) {
		Brutus_MsgFlags |= ::BRUTUS::BRUTUS_MSGFLAG_HASATTACH;
		FLAGS_OFF(ULONG, mapi_flags, MSGFLAG_HASATTACH);
	}

	if (mapi_flags & MSGFLAG_FROMME) {
		Brutus_MsgFlags |= ::BRUTUS::BRUTUS_MSGFLAG_FROMME;
		FLAGS_OFF(ULONG, mapi_flags, MSGFLAG_FROMME);
	}

	if (mapi_flags & MSGFLAG_ASSOCIATED) {
		Brutus_MsgFlags |= ::BRUTUS::BRUTUS_MSGFLAG_ASSOCIATED;
		FLAGS_OFF(ULONG, mapi_flags, MSGFLAG_ASSOCIATED);
	}

	if (mapi_flags & MSGFLAG_RESEND) {
		Brutus_MsgFlags |= ::BRUTUS::BRUTUS_MSGFLAG_RESEND;
		FLAGS_OFF(ULONG, mapi_flags, MSGFLAG_RESEND);
	}

	if (mapi_flags & MSGFLAG_RN_PENDING) {
		Brutus_MsgFlags |= ::BRUTUS::BRUTUS_MSGFLAG_RN_PENDING;
		FLAGS_OFF(ULONG, mapi_flags, MSGFLAG_RN_PENDING);
	}

	if (mapi_flags & MSGFLAG_NRN_PENDING) {
		Brutus_MsgFlags |= ::BRUTUS::BRUTUS_MSGFLAG_NRN_PENDING;
		FLAGS_OFF(ULONG, mapi_flags, MSGFLAG_NRN_PENDING);
	}

	if (mapi_flags) {
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown message flag(s) from MAPI : %X", mapi_flags);
		BRUTUS_LOG_BUG(msg);
		return false;
	}

	return true;
}

bool bresult_to_hresult(const ::BRUTUS::BRESULT BValue,
			HRESULT& HValue)
{
#pragma warning( disable : 6225 )

	switch (BValue) {
	case ::BRUTUS::BRUTUS_S_OK :
		HValue = S_OK;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_CALL_FAILED :
		HValue = MAPI_E_CALL_FAILED;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_NOT_ENOUGH_MEMORY :
		HValue = MAPI_E_NOT_ENOUGH_MEMORY;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_INVALID_PARAMETER :
		HValue = MAPI_E_INVALID_PARAMETER;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_INTERFACE_NOT_SUPPORTED :
		HValue = MAPI_E_INTERFACE_NOT_SUPPORTED;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_NO_ACCESS :
		HValue = MAPI_E_NO_ACCESS;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_NO_SUPPORT :
		HValue = MAPI_E_NO_SUPPORT;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_BAD_CHARWIDTH :
		HValue = MAPI_E_BAD_CHARWIDTH;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_STRING_TOO_LONG :
		HValue = MAPI_E_STRING_TOO_LONG;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_UNKNOWN_FLAGS :
		HValue = MAPI_E_UNKNOWN_FLAGS;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_INVALID_ENTRYID :
		HValue = MAPI_E_INVALID_ENTRYID;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_INVALID_OBJECT :
		HValue = MAPI_E_INVALID_OBJECT;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_OBJECT_CHANGED :
		HValue = MAPI_E_OBJECT_CHANGED;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_OBJECT_DELETED :
		HValue = MAPI_E_OBJECT_DELETED;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_BUSY :
		HValue = MAPI_E_BUSY;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_NOT_ENOUGH_DISK :
		HValue = MAPI_E_NOT_ENOUGH_DISK;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_NOT_ENOUGH_RESOURCES :
		HValue = MAPI_E_NOT_ENOUGH_RESOURCES;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_NOT_FOUND :
		HValue = MAPI_E_NOT_FOUND;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_VERSION :
		HValue = MAPI_E_VERSION;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_LOGON_FAILED :
		HValue = MAPI_E_LOGON_FAILED;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_SESSION_LIMIT :
		HValue = MAPI_E_SESSION_LIMIT;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_USER_CANCEL :
		HValue = MAPI_E_USER_CANCEL;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_UNABLE_TO_ABORT :
		HValue = MAPI_E_UNABLE_TO_ABORT;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_NETWORK_ERROR :
		HValue = MAPI_E_NETWORK_ERROR;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_DISK_ERROR :
		HValue = MAPI_E_DISK_ERROR;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_TOO_COMPLEX :
		HValue = MAPI_E_TOO_COMPLEX;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_BAD_COLUMN :
		HValue = MAPI_E_BAD_COLUMN;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_EXTENDED_ERROR :
		HValue = MAPI_E_EXTENDED_ERROR;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_COMPUTED :
		HValue = MAPI_E_COMPUTED;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_CORRUPT_DATA :
		HValue = MAPI_E_CORRUPT_DATA;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_UNCONFIGURED :
		HValue = MAPI_E_UNCONFIGURED;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_FAILONEPROVIDER :
		HValue = MAPI_E_FAILONEPROVIDER;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_UNKNOWN_CPID :
		HValue = MAPI_E_UNKNOWN_CPID;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_UNKNOWN_LCID :
		HValue = MAPI_E_UNKNOWN_LCID;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_PASSWORD_CHANGE_REQUIRED :
		HValue = MAPI_E_PASSWORD_CHANGE_REQUIRED;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_PASSWORD_EXPIRED :
		HValue = MAPI_E_PASSWORD_EXPIRED;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_INVALID_WORKSTATION_ACCOUNT :
		HValue = MAPI_E_INVALID_WORKSTATION_ACCOUNT;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_INVALID_ACCESS_TIME :
		HValue = MAPI_E_INVALID_ACCESS_TIME;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_ACCOUNT_DISABLED :
		HValue = MAPI_E_ACCOUNT_DISABLED;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_END_OF_SESSION :
		HValue = MAPI_E_END_OF_SESSION;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_UNKNOWN_ENTRYID :
		HValue = MAPI_E_UNKNOWN_ENTRYID;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_MISSING_REQUIRED_COLUMN :
		HValue = MAPI_E_MISSING_REQUIRED_COLUMN;
		break;
	case ::BRUTUS::BRUTUS_MAPI_W_NO_SERVICE :
		HValue = MAPI_W_NO_SERVICE;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_BAD_VALUE :
		HValue = MAPI_E_BAD_VALUE;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_INVALID_TYPE :
		HValue = MAPI_E_INVALID_TYPE;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_TYPE_NO_SUPPORT :
		HValue = MAPI_E_TYPE_NO_SUPPORT;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_UNEXPECTED_TYPE :
		HValue = MAPI_E_UNEXPECTED_TYPE;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_TOO_BIG :
		HValue = MAPI_E_TOO_BIG;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_DECLINE_COPY :
		HValue = MAPI_E_DECLINE_COPY;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_UNEXPECTED_ID :
		HValue = MAPI_E_UNEXPECTED_ID;
		break;
	case ::BRUTUS::BRUTUS_MAPI_W_ERRORS_RETURNED :
		HValue = MAPI_W_ERRORS_RETURNED;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_UNABLE_TO_COMPLETE :
		HValue = MAPI_E_UNABLE_TO_COMPLETE;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_TIMEOUT :
		HValue = MAPI_E_TIMEOUT;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_TABLE_EMPTY :
		HValue = MAPI_E_TABLE_EMPTY;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_TABLE_TOO_BIG :
		HValue = MAPI_E_TABLE_TOO_BIG;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_INVALID_BOOKMARK :
		HValue = MAPI_E_INVALID_BOOKMARK;
		break;
	case ::BRUTUS::BRUTUS_MAPI_W_POSITION_CHANGED :
		HValue = MAPI_W_POSITION_CHANGED;
		break;
	case ::BRUTUS::BRUTUS_MAPI_W_APPROX_COUNT :
		HValue = MAPI_W_APPROX_COUNT;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_WAIT :
		HValue = MAPI_E_WAIT;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_CANCEL :
		HValue = MAPI_E_CANCEL;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_NOT_ME :
		HValue = MAPI_E_NOT_ME;
		break;
	case ::BRUTUS::BRUTUS_MAPI_W_CANCEL_MESSAGE :
		HValue = MAPI_W_CANCEL_MESSAGE;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_CORRUPT_STORE :
		HValue = MAPI_E_CORRUPT_STORE;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_NOT_IN_QUEUE :
		HValue = MAPI_E_NOT_IN_QUEUE;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_NO_SUPPRESS :
		HValue = MAPI_E_NO_SUPPRESS;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_COLLISION :
		HValue = MAPI_E_COLLISION;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_NOT_INITIALIZED :
		HValue = MAPI_E_NOT_INITIALIZED;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_NON_STANDARD :
		HValue = MAPI_E_NON_STANDARD;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_NO_RECIPIENTS :
		HValue = MAPI_E_NO_RECIPIENTS;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_SUBMITTED :
		HValue = MAPI_E_SUBMITTED;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_HAS_FOLDERS :
		HValue = MAPI_E_HAS_FOLDERS;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_HAS_MESSAGES :
		HValue = MAPI_E_HAS_MESSAGES;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_FOLDER_CYCLE :
		HValue = MAPI_E_FOLDER_CYCLE;
		break;
	case ::BRUTUS::BRUTUS_MAPI_W_PARTIAL_COMPLETION :
		HValue = MAPI_W_PARTIAL_COMPLETION;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_AMBIGUOUS_RECIP :
		HValue = MAPI_E_AMBIGUOUS_RECIP;
		break;
	case ::BRUTUS::BRUTUS_OLEOBJ_S_CANNOT_DOVERB_NOW :
		HValue = OLEOBJ_S_CANNOT_DOVERB_NOW;
		break;
	case ::BRUTUS::BRUTUS_STG_E_INVALIDFUNCTION :
		HValue = STG_E_INVALIDFUNCTION;
		break;
	case ::BRUTUS::BRUTUS_STG_E_FILENOTFOUND :
		HValue = STG_E_FILENOTFOUND;
		break;
	case ::BRUTUS::BRUTUS_STG_E_PATHNOTFOUND :
		HValue = STG_E_PATHNOTFOUND;
		break;
	case ::BRUTUS::BRUTUS_STG_E_TOOMANYOPENFILES :
		HValue = STG_E_TOOMANYOPENFILES;
		break;
	case ::BRUTUS::BRUTUS_STG_E_ACCESSDENIED :
		HValue = STG_E_ACCESSDENIED;
		break;
	case ::BRUTUS::BRUTUS_STG_E_INVALIDHANDLE :
		HValue = STG_E_INVALIDHANDLE;
		break;
	case ::BRUTUS::BRUTUS_STG_E_INSUFFICIENTMEMORY :
		HValue = STG_E_INSUFFICIENTMEMORY;
		break;
	case ::BRUTUS::BRUTUS_STG_E_INVALIDPOINTER :
		HValue = STG_E_INVALIDPOINTER;
		break;
	case ::BRUTUS::BRUTUS_STG_E_NOMOREFILES :
		HValue = STG_E_NOMOREFILES;
		break;
	case ::BRUTUS::BRUTUS_STG_E_DISKISWRITEPROTECTED :
		HValue = STG_E_DISKISWRITEPROTECTED;
		break;
	case ::BRUTUS::BRUTUS_STG_E_SEEKERROR :
		HValue = STG_E_SEEKERROR;
		break;
	case ::BRUTUS::BRUTUS_STG_E_WRITEFAULT :
		HValue = STG_E_WRITEFAULT;
		break;
	case ::BRUTUS::BRUTUS_STG_E_READFAULT :
		HValue = STG_E_READFAULT;
		break;
	case ::BRUTUS::BRUTUS_STG_E_SHAREVIOLATION :
		HValue = STG_E_SHAREVIOLATION;
		break;
	case ::BRUTUS::BRUTUS_STG_E_LOCKVIOLATION :
		HValue = STG_E_LOCKVIOLATION;
		break;
	case ::BRUTUS::BRUTUS_STG_E_FILEALREADYEXISTS :
		HValue = STG_E_FILEALREADYEXISTS;
		break;
	case ::BRUTUS::BRUTUS_STG_E_INVALIDPARAMETER :
		HValue = STG_E_INVALIDPARAMETER;
		break;
	case ::BRUTUS::BRUTUS_STG_E_MEDIUMFULL :
		HValue = STG_E_MEDIUMFULL;
		break;
	case ::BRUTUS::BRUTUS_STG_E_PROPSETMISMATCHED :
		HValue = STG_E_PROPSETMISMATCHED;
		break;
	case ::BRUTUS::BRUTUS_STG_E_ABNORMALAPIEXIT :
		HValue = STG_E_ABNORMALAPIEXIT;
		break;
	case ::BRUTUS::BRUTUS_STG_E_INVALIDHEADER :
		HValue = STG_E_INVALIDHEADER;
		break;
	case ::BRUTUS::BRUTUS_STG_E_INVALIDNAME :
		HValue = STG_E_INVALIDNAME;
		break;
	case ::BRUTUS::BRUTUS_STG_E_UNKNOWN :
		HValue = STG_E_UNKNOWN;
		break;
	case ::BRUTUS::BRUTUS_STG_E_UNIMPLEMENTEDFUNCTION :
		HValue = STG_E_UNIMPLEMENTEDFUNCTION;
		break;
	case ::BRUTUS::BRUTUS_STG_E_INVALIDFLAG :
		HValue = STG_E_INVALIDFLAG;
		break;
	case ::BRUTUS::BRUTUS_STG_E_INUSE :
		HValue = STG_E_INUSE;
		break;
	case ::BRUTUS::BRUTUS_STG_E_NOTCURRENT :
		HValue = STG_E_NOTCURRENT;
		break;
	case ::BRUTUS::BRUTUS_STG_E_REVERTED :
		HValue = STG_E_REVERTED;
		break;
	case ::BRUTUS::BRUTUS_STG_E_CANTSAVE :
		HValue = STG_E_CANTSAVE;
		break;
	case ::BRUTUS::BRUTUS_STG_E_OLDFORMAT :
		HValue = STG_E_OLDFORMAT;
		break;
	case ::BRUTUS::BRUTUS_STG_E_OLDDLL :
		HValue = STG_E_OLDDLL;
		break;
	case ::BRUTUS::BRUTUS_STG_E_SHAREREQUIRED :
		HValue = STG_E_SHAREREQUIRED;
		break;
	case ::BRUTUS::BRUTUS_STG_E_NOTFILEBASEDSTORAGE :
		HValue = STG_E_NOTFILEBASEDSTORAGE;
		break;
	case ::BRUTUS::BRUTUS_STG_E_EXTANTMARSHALLINGS :
		HValue = STG_E_EXTANTMARSHALLINGS;
		break;
	case ::BRUTUS::BRUTUS_STG_E_DOCFILECORRUPT :
		HValue = STG_E_DOCFILECORRUPT;
		break;
	case ::BRUTUS::BRUTUS_STG_E_BADBASEADDRESS :
		HValue = STG_E_BADBASEADDRESS;
		break;
	case ::BRUTUS::BRUTUS_STG_E_INCOMPLETE :
		HValue = STG_E_INCOMPLETE;
		break;
	case ::BRUTUS::BRUTUS_STG_E_TERMINATED :
		HValue = STG_E_TERMINATED;
		break;
	case ::BRUTUS::BRUTUS_STG_S_CONVERTED :
		HValue = STG_S_CONVERTED;
		break;
	case ::BRUTUS::BRUTUS_STG_S_BLOCK :
		HValue = STG_S_BLOCK;
		break;
	case ::BRUTUS::BRUTUS_STG_S_RETRYNOW :
		HValue = STG_S_RETRYNOW;
		break;
	case ::BRUTUS::BRUTUS_STG_S_MONITORING :
		HValue = STG_S_MONITORING;
		break;
	case ::BRUTUS::BRUTUS_STG_S_MULTIPLEOPENS :
		HValue = STG_S_MULTIPLEOPENS;
		break;
	case ::BRUTUS::BRUTUS_STG_S_CONSOLIDATIONFAILED :
		HValue = STG_S_CONSOLIDATIONFAILED;
		break;
	case ::BRUTUS::BRUTUS_STG_S_CANNOTCONSOLIDATE :
		HValue = STG_S_CANNOTCONSOLIDATE;
		break;
	case ::BRUTUS::BRUTUS_E_PENDING :
		HValue = E_PENDING;
		break;
	case ::BRUTUS::BRUTUS_SYNC_E_OBJECT_DELETED :
		HValue = SYNC_E_OBJECT_DELETED;
		break;
	case ::BRUTUS::BRUTUS_SYNC_E_IGNORE :
		HValue = SYNC_E_IGNORE;
		break;
	case ::BRUTUS::BRUTUS_SYNC_E_CONFLICT :
		HValue = SYNC_E_CONFLICT;
		break;
	case ::BRUTUS::BRUTUS_SYNC_E_NO_PARENT :
		HValue = SYNC_E_NO_PARENT;
		break;
	case ::BRUTUS::BRUTUS_SYNC_E_INCEST :
		HValue = SYNC_E_INCEST;
		break;
	case ::BRUTUS::BRUTUS_SYNC_E_UNSYNCHRONIZED :
		HValue = SYNC_E_UNSYNCHRONIZED;
		break;
	case ::BRUTUS::BRUTUS_SYNC_W_PROGRESS :
		HValue = SYNC_W_PROGRESS;
		break;
	case ::BRUTUS::BRUTUS_SYNC_W_CLIENT_CHANGE_NEWER :
		HValue = SYNC_W_CLIENT_CHANGE_NEWER;
		break;
	case ::BRUTUS::BRUTUS_EC_EDK_E_FAIL :
		HValue = EC_EDK_E_FAIL;
		break;
	case ::BRUTUS::BRUTUS_EC_EDK_E_OUTOFMEMORY :
		HValue = EC_EDK_E_OUTOFMEMORY;
		break;
	case ::BRUTUS::BRUTUS_EC_EDK_E_INVALIDARG :
		HValue = EC_EDK_E_INVALIDARG;
		break;
	case ::BRUTUS::BRUTUS_EC_EDK_E_NOTIMPL :
		HValue = EC_EDK_E_NOTIMPL;
		break;
	case ::BRUTUS::BRUTUS_EC_EDK_E_NOINTERFACE :
		HValue = EC_EDK_E_NOINTERFACE;
		break;
	case ::BRUTUS::BRUTUS_EC_EDK_E_ACCESSDENIED :
		HValue = EC_EDK_E_ACCESSDENIED;
		break;
	case ::BRUTUS::BRUTUS_EC_EDK_E_UNKNOWN :
		HValue = EC_EDK_E_UNKNOWN;
		break;
	case ::BRUTUS::BRUTUS_EC_EDK_E_NOT_FOUND :
		HValue = EC_EDK_E_NOT_FOUND;
		break;
	case ::BRUTUS::BRUTUS_EDK_E_NOT_FOUND :
		HValue = EDK_E_NOT_FOUND;
		break;
	case ::BRUTUS::BRUTUS_EC_EDK_E_SHUTDOWN_SERVICE :
		HValue = EC_EDK_E_SHUTDOWN_SERVICE;
		break;
	case ::BRUTUS::BRUTUS_EDK_E_SHUTDOWN_SERVICE :
		HValue = EDK_E_SHUTDOWN_SERVICE;
		break;
	case ::BRUTUS::BRUTUS_EC_EDK_E_ALREADY_EXISTS :
		HValue = EC_EDK_E_ALREADY_EXISTS;
		break;
	case ::BRUTUS::BRUTUS_EDK_E_ALREADY_EXISTS :
		HValue = EDK_E_ALREADY_EXISTS;
		break;
	case ::BRUTUS::BRUTUS_EC_EDK_E_END_OF_FILE :
		HValue = EC_EDK_E_END_OF_FILE;
		break;
	case ::BRUTUS::BRUTUS_EDK_E_END_OF_FILE :
		HValue = EDK_E_END_OF_FILE;
		break;
	case ::BRUTUS::BRUTUS_EC_EDK_E_AMBIGUOUS :
		HValue = EC_EDK_E_AMBIGUOUS;
		break;
	case ::BRUTUS::BRUTUS_EDK_E_AMBIGUOUS :
		HValue = EDK_E_AMBIGUOUS;
		break;
	case ::BRUTUS::BRUTUS_EC_EDK_E_PARSE :
		HValue = EC_EDK_E_PARSE;
		break;
	case ::BRUTUS::BRUTUS_EDK_E_PARSE :
		HValue = EDK_E_PARSE;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_UNKNOWN_MAILBOX :
		HValue = 0x81002746;
		break;
	case ::BRUTUS::BRUTUS_MAPI_E_PROFILE_DELETED :
		HValue = 0x80040204;
		break;
	case ::BRUTUS::BRUTUS_UNKNOWN_ERROR :
	case ::BRUTUS::BRUTUS_INTERNAL_ERROR :
	{
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Brutus specific BRESULT from client : %X", BValue);
		BRUTUS_LOG_BUG(msg);
	}
	return false;
	default:
	{
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown BRESULT from client : %X", BValue);
		BRUTUS_LOG_BUG(msg);
	}
	return false;
	}

	return true;
}

bool hresult_to_bresult(const HRESULT HValue,
			::BRUTUS::BRESULT& BValue)
{
#pragma warning( disable : 6219 )
#pragma warning( disable : 6221 )

	switch (HValue) {
	case S_OK :
		BValue = ::BRUTUS::BRUTUS_S_OK;
		break;
	case MAPI_E_CALL_FAILED :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_CALL_FAILED;
		break;
	case MAPI_E_NOT_ENOUGH_MEMORY :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_NOT_ENOUGH_MEMORY;
		break;
	case MAPI_E_INVALID_PARAMETER :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_INVALID_PARAMETER;
		break;
	case MAPI_E_INTERFACE_NOT_SUPPORTED :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_INTERFACE_NOT_SUPPORTED;
		break;
	case MAPI_E_NO_ACCESS :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_NO_ACCESS;
		break;
	case MAPI_E_NO_SUPPORT :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_NO_SUPPORT;
		break;
	case MAPI_E_BAD_CHARWIDTH :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_BAD_CHARWIDTH;
		break;
	case MAPI_E_STRING_TOO_LONG :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_STRING_TOO_LONG;
		break;
	case MAPI_E_UNKNOWN_FLAGS :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_UNKNOWN_FLAGS;
		break;
	case MAPI_E_INVALID_ENTRYID :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_INVALID_ENTRYID;
		break;
	case MAPI_E_INVALID_OBJECT :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_INVALID_OBJECT;
		break;
	case MAPI_E_OBJECT_CHANGED :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_OBJECT_CHANGED;
		break;
	case MAPI_E_OBJECT_DELETED :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_OBJECT_DELETED;
		break;
	case MAPI_E_BUSY :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_BUSY;
		break;
	case MAPI_E_NOT_ENOUGH_DISK :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_NOT_ENOUGH_DISK;
		break;
	case MAPI_E_NOT_ENOUGH_RESOURCES :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_NOT_ENOUGH_RESOURCES;
		break;
	case MAPI_E_NOT_FOUND :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_NOT_FOUND;
		break;
	case MAPI_E_VERSION :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_VERSION;
		break;
	case MAPI_E_LOGON_FAILED :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_LOGON_FAILED;
		break;
	case MAPI_E_SESSION_LIMIT :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_SESSION_LIMIT;
		break;
	case MAPI_E_USER_CANCEL :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_USER_CANCEL;
		break;
	case MAPI_E_UNABLE_TO_ABORT :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_UNABLE_TO_ABORT;
		break;
	case MAPI_E_NETWORK_ERROR :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_NETWORK_ERROR;
		break;
	case MAPI_E_DISK_ERROR :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_DISK_ERROR;
		break;
	case MAPI_E_TOO_COMPLEX :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_TOO_COMPLEX;
		break;
	case MAPI_E_BAD_COLUMN :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_BAD_COLUMN;
		break;
	case MAPI_E_EXTENDED_ERROR :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_EXTENDED_ERROR;
		break;
	case MAPI_E_COMPUTED :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_COMPUTED;
		break;
	case MAPI_E_CORRUPT_DATA :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_CORRUPT_DATA;
		break;
	case MAPI_E_UNCONFIGURED :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_UNCONFIGURED;
		break;
	case MAPI_E_FAILONEPROVIDER :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_FAILONEPROVIDER;
		break;
	case MAPI_E_UNKNOWN_CPID :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_UNKNOWN_CPID;
		break;
	case MAPI_E_UNKNOWN_LCID :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_UNKNOWN_LCID;
		break;
	case MAPI_E_PASSWORD_CHANGE_REQUIRED :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_PASSWORD_CHANGE_REQUIRED;
		break;
	case MAPI_E_PASSWORD_EXPIRED :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_PASSWORD_EXPIRED;
		break;
	case MAPI_E_INVALID_WORKSTATION_ACCOUNT :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_INVALID_WORKSTATION_ACCOUNT;
		break;
	case MAPI_E_INVALID_ACCESS_TIME :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_INVALID_ACCESS_TIME;
		break;
	case MAPI_E_ACCOUNT_DISABLED :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_ACCOUNT_DISABLED;
		break;
	case MAPI_E_END_OF_SESSION :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_END_OF_SESSION;
		break;
	case MAPI_E_UNKNOWN_ENTRYID :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_UNKNOWN_ENTRYID;
		break;
	case MAPI_E_MISSING_REQUIRED_COLUMN :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_MISSING_REQUIRED_COLUMN;
		break;
	case MAPI_W_NO_SERVICE :
		BValue = ::BRUTUS::BRUTUS_MAPI_W_NO_SERVICE;
		break;
	case MAPI_E_BAD_VALUE :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_BAD_VALUE;
		break;
	case MAPI_E_INVALID_TYPE :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_INVALID_TYPE;
		break;
	case MAPI_E_TYPE_NO_SUPPORT :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_TYPE_NO_SUPPORT;
		break;
	case MAPI_E_UNEXPECTED_TYPE :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_UNEXPECTED_TYPE;
		break;
	case MAPI_E_TOO_BIG :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_TOO_BIG;
		break;
	case MAPI_E_DECLINE_COPY :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_DECLINE_COPY;
		break;
	case MAPI_E_UNEXPECTED_ID :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_UNEXPECTED_ID;
		break;
	case MAPI_W_ERRORS_RETURNED :
		BValue = ::BRUTUS::BRUTUS_MAPI_W_ERRORS_RETURNED;
		break;
	case MAPI_E_UNABLE_TO_COMPLETE :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_UNABLE_TO_COMPLETE;
		break;
	case MAPI_E_TIMEOUT :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_TIMEOUT;
		break;
	case MAPI_E_TABLE_EMPTY :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_TABLE_EMPTY;
		break;
	case MAPI_E_TABLE_TOO_BIG :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_TABLE_TOO_BIG;
		break;
	case MAPI_E_INVALID_BOOKMARK :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_INVALID_BOOKMARK;
		break;
	case MAPI_W_POSITION_CHANGED :
		BValue = ::BRUTUS::BRUTUS_MAPI_W_POSITION_CHANGED;
		break;
	case MAPI_W_APPROX_COUNT :
		BValue = ::BRUTUS::BRUTUS_MAPI_W_APPROX_COUNT;
		break;
	case MAPI_E_WAIT :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_WAIT;
		break;
	case MAPI_E_CANCEL :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_CANCEL;
		break;
	case MAPI_E_NOT_ME :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_NOT_ME;
		break;
	case MAPI_W_CANCEL_MESSAGE :
		BValue = ::BRUTUS::BRUTUS_MAPI_W_CANCEL_MESSAGE;
		break;
	case MAPI_E_CORRUPT_STORE :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_CORRUPT_STORE;
		break;
	case MAPI_E_NOT_IN_QUEUE :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_NOT_IN_QUEUE;
		break;
	case MAPI_E_NO_SUPPRESS :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_NO_SUPPRESS;
		break;
	case MAPI_E_COLLISION :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_COLLISION;
		break;
	case MAPI_E_NOT_INITIALIZED :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_NOT_INITIALIZED;
		break;
	case MAPI_E_NON_STANDARD :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_NON_STANDARD;
		break;
	case MAPI_E_NO_RECIPIENTS :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_NO_RECIPIENTS;
		break;
	case MAPI_E_SUBMITTED :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_SUBMITTED;
		break;
	case MAPI_E_HAS_FOLDERS :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_HAS_FOLDERS;
		break;
	case MAPI_E_HAS_MESSAGES :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_HAS_MESSAGES;
		break;
	case MAPI_E_FOLDER_CYCLE :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_FOLDER_CYCLE;
		break;
	case MAPI_W_PARTIAL_COMPLETION :
		BValue = ::BRUTUS::BRUTUS_MAPI_W_PARTIAL_COMPLETION;
		break;
	case MAPI_E_AMBIGUOUS_RECIP :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_AMBIGUOUS_RECIP;
		break;
	case OLEOBJ_S_CANNOT_DOVERB_NOW :
		BValue = ::BRUTUS::BRUTUS_OLEOBJ_S_CANNOT_DOVERB_NOW;
		break;
	case STG_E_INVALIDFUNCTION :
		BValue = ::BRUTUS::BRUTUS_STG_E_INVALIDFUNCTION;
		break;
	case STG_E_FILENOTFOUND :
		BValue = ::BRUTUS::BRUTUS_STG_E_FILENOTFOUND;
		break;
	case STG_E_PATHNOTFOUND :
		BValue = ::BRUTUS::BRUTUS_STG_E_PATHNOTFOUND;
		break;
	case STG_E_TOOMANYOPENFILES :
		BValue = ::BRUTUS::BRUTUS_STG_E_TOOMANYOPENFILES;
		break;
	case STG_E_ACCESSDENIED :
		BValue = ::BRUTUS::BRUTUS_STG_E_ACCESSDENIED;
		break;
	case STG_E_INVALIDHANDLE :
		BValue = ::BRUTUS::BRUTUS_STG_E_INVALIDHANDLE;
		break;
	case STG_E_INSUFFICIENTMEMORY :
		BValue = ::BRUTUS::BRUTUS_STG_E_INSUFFICIENTMEMORY;
		break;
	case STG_E_INVALIDPOINTER :
		BValue = ::BRUTUS::BRUTUS_STG_E_INVALIDPOINTER;
		break;
	case STG_E_NOMOREFILES :
		BValue = ::BRUTUS::BRUTUS_STG_E_NOMOREFILES;
		break;
	case STG_E_DISKISWRITEPROTECTED :
		BValue = ::BRUTUS::BRUTUS_STG_E_DISKISWRITEPROTECTED;
		break;
	case STG_E_SEEKERROR :
		BValue = ::BRUTUS::BRUTUS_STG_E_SEEKERROR;
		break;
	case STG_E_WRITEFAULT :
		BValue = ::BRUTUS::BRUTUS_STG_E_WRITEFAULT;
		break;
	case STG_E_READFAULT :
		BValue = ::BRUTUS::BRUTUS_STG_E_READFAULT;
		break;
	case STG_E_SHAREVIOLATION :
		BValue = ::BRUTUS::BRUTUS_STG_E_SHAREVIOLATION;
		break;
	case STG_E_LOCKVIOLATION :
		BValue = ::BRUTUS::BRUTUS_STG_E_LOCKVIOLATION;
		break;
	case STG_E_FILEALREADYEXISTS :
		BValue = ::BRUTUS::BRUTUS_STG_E_FILEALREADYEXISTS;
		break;
	case STG_E_INVALIDPARAMETER :
		BValue = ::BRUTUS::BRUTUS_STG_E_INVALIDPARAMETER;
		break;
	case STG_E_MEDIUMFULL :
		BValue = ::BRUTUS::BRUTUS_STG_E_MEDIUMFULL;
		break;
	case STG_E_PROPSETMISMATCHED :
		BValue = ::BRUTUS::BRUTUS_STG_E_PROPSETMISMATCHED;
		break;
	case STG_E_ABNORMALAPIEXIT :
		BValue = ::BRUTUS::BRUTUS_STG_E_ABNORMALAPIEXIT;
		break;
	case STG_E_INVALIDHEADER :
		BValue = ::BRUTUS::BRUTUS_STG_E_INVALIDHEADER;
		break;
	case STG_E_INVALIDNAME :
		BValue = ::BRUTUS::BRUTUS_STG_E_INVALIDNAME;
		break;
	case STG_E_UNKNOWN :
		BValue = ::BRUTUS::BRUTUS_STG_E_UNKNOWN;
		break;
	case STG_E_UNIMPLEMENTEDFUNCTION :
		BValue = ::BRUTUS::BRUTUS_STG_E_UNIMPLEMENTEDFUNCTION;
		break;
	case STG_E_INVALIDFLAG :
		BValue = ::BRUTUS::BRUTUS_STG_E_INVALIDFLAG;
		break;
	case STG_E_INUSE :
		BValue = ::BRUTUS::BRUTUS_STG_E_INUSE;
		break;
	case STG_E_NOTCURRENT :
		BValue = ::BRUTUS::BRUTUS_STG_E_NOTCURRENT;
		break;
	case STG_E_REVERTED :
		BValue = ::BRUTUS::BRUTUS_STG_E_REVERTED;
		break;
	case STG_E_CANTSAVE :
		BValue = ::BRUTUS::BRUTUS_STG_E_CANTSAVE;
		break;
	case STG_E_OLDFORMAT :
		BValue = ::BRUTUS::BRUTUS_STG_E_OLDFORMAT;
		break;
	case STG_E_OLDDLL :
		BValue = ::BRUTUS::BRUTUS_STG_E_OLDDLL;
		break;
	case STG_E_SHAREREQUIRED :
		BValue = ::BRUTUS::BRUTUS_STG_E_SHAREREQUIRED;
		break;
	case STG_E_NOTFILEBASEDSTORAGE :
		BValue = ::BRUTUS::BRUTUS_STG_E_NOTFILEBASEDSTORAGE;
		break;
	case STG_E_EXTANTMARSHALLINGS :
		BValue = ::BRUTUS::BRUTUS_STG_E_EXTANTMARSHALLINGS;
		break;
	case STG_E_DOCFILECORRUPT :
		BValue = ::BRUTUS::BRUTUS_STG_E_DOCFILECORRUPT;
		break;
	case STG_E_BADBASEADDRESS :
		BValue = ::BRUTUS::BRUTUS_STG_E_BADBASEADDRESS;
		break;
	case STG_E_INCOMPLETE :
		BValue = ::BRUTUS::BRUTUS_STG_E_INCOMPLETE;
		break;
	case STG_E_TERMINATED :
		BValue = ::BRUTUS::BRUTUS_STG_E_TERMINATED;
		break;
	case STG_S_CONVERTED :
		BValue = ::BRUTUS::BRUTUS_STG_S_CONVERTED;
		break;
	case STG_S_BLOCK :
		BValue = ::BRUTUS::BRUTUS_STG_S_BLOCK;
		break;
	case STG_S_RETRYNOW :
		BValue = ::BRUTUS::BRUTUS_STG_S_RETRYNOW;
		break;
	case STG_S_MONITORING :
		BValue = ::BRUTUS::BRUTUS_STG_S_MONITORING;
		break;
	case STG_S_MULTIPLEOPENS :
		BValue = ::BRUTUS::BRUTUS_STG_S_MULTIPLEOPENS;
		break;
	case STG_S_CONSOLIDATIONFAILED :
		BValue = ::BRUTUS::BRUTUS_STG_S_CONSOLIDATIONFAILED;
		break;
	case STG_S_CANNOTCONSOLIDATE :
		BValue = ::BRUTUS::BRUTUS_STG_S_CANNOTCONSOLIDATE;
		break;
	case E_PENDING :
		BValue = ::BRUTUS::BRUTUS_E_PENDING;
		break;
	case SYNC_E_OBJECT_DELETED :
		BValue = ::BRUTUS::BRUTUS_SYNC_E_OBJECT_DELETED;
		break;
	case SYNC_E_IGNORE :
		BValue = ::BRUTUS::BRUTUS_SYNC_E_IGNORE;
		break;
	case SYNC_E_CONFLICT :
		BValue = ::BRUTUS::BRUTUS_SYNC_E_CONFLICT;
		break;
	case SYNC_E_NO_PARENT :
		BValue = ::BRUTUS::BRUTUS_SYNC_E_NO_PARENT;
		break;
	case SYNC_E_INCEST :
		BValue = ::BRUTUS::BRUTUS_SYNC_E_INCEST;
		break;
	case SYNC_E_UNSYNCHRONIZED :
		BValue = ::BRUTUS::BRUTUS_SYNC_E_UNSYNCHRONIZED;
		break;
	case SYNC_W_PROGRESS :
		BValue = ::BRUTUS::BRUTUS_SYNC_W_PROGRESS;
		break;
	case SYNC_W_CLIENT_CHANGE_NEWER :
		BValue = ::BRUTUS::BRUTUS_SYNC_W_CLIENT_CHANGE_NEWER;
		break;
	case EC_EDK_E_FAIL :
		BValue = ::BRUTUS::BRUTUS_EC_EDK_E_FAIL;
		break;
	case EC_EDK_E_OUTOFMEMORY :
		BValue = ::BRUTUS::BRUTUS_EC_EDK_E_OUTOFMEMORY;
		break;
	case EC_EDK_E_INVALIDARG :
		BValue = ::BRUTUS::BRUTUS_EC_EDK_E_INVALIDARG;
		break;
	case EC_EDK_E_NOTIMPL :
		BValue = ::BRUTUS::BRUTUS_EC_EDK_E_NOTIMPL;
		break;
	case EC_EDK_E_NOINTERFACE :
		BValue = ::BRUTUS::BRUTUS_EC_EDK_E_NOINTERFACE;
		break;
	case EC_EDK_E_ACCESSDENIED :
		BValue = ::BRUTUS::BRUTUS_EC_EDK_E_ACCESSDENIED;
		break;
	case EC_EDK_E_UNKNOWN :
		BValue = ::BRUTUS::BRUTUS_EC_EDK_E_UNKNOWN;
		break;
	case EC_EDK_E_NOT_FOUND :
		BValue = ::BRUTUS::BRUTUS_EC_EDK_E_NOT_FOUND;
		break;
	case EDK_E_NOT_FOUND :
		BValue = ::BRUTUS::BRUTUS_EDK_E_NOT_FOUND;
		break;
	case EC_EDK_E_SHUTDOWN_SERVICE :
		BValue = ::BRUTUS::BRUTUS_EC_EDK_E_SHUTDOWN_SERVICE;
		break;
	case EDK_E_SHUTDOWN_SERVICE :
		BValue = ::BRUTUS::BRUTUS_EDK_E_SHUTDOWN_SERVICE;
		break;
	case EC_EDK_E_ALREADY_EXISTS :
		BValue = ::BRUTUS::BRUTUS_EC_EDK_E_ALREADY_EXISTS;
		break;
	case EDK_E_ALREADY_EXISTS :
		BValue = ::BRUTUS::BRUTUS_EDK_E_ALREADY_EXISTS;
		break;
	case EC_EDK_E_END_OF_FILE :
		BValue = ::BRUTUS::BRUTUS_EC_EDK_E_END_OF_FILE;
		break;
	case EDK_E_END_OF_FILE :
		BValue = ::BRUTUS::BRUTUS_EDK_E_END_OF_FILE;
		break;
	case EC_EDK_E_AMBIGUOUS :
		BValue = ::BRUTUS::BRUTUS_EC_EDK_E_AMBIGUOUS;
		break;
	case EDK_E_AMBIGUOUS :
		BValue = ::BRUTUS::BRUTUS_EDK_E_AMBIGUOUS;
		break;
	case EC_EDK_E_PARSE :
		BValue = ::BRUTUS::BRUTUS_EC_EDK_E_PARSE;
		break;
	case EDK_E_PARSE :
		BValue = ::BRUTUS::BRUTUS_EDK_E_PARSE;
		break;
	case 0x81002746 :
		BValue = ::BRUTUS::BRUTUS_MAPI_E_UNKNOWN_MAILBOX;
		break;
	case 0x80040204 :
		BValue = BRUTUS::BRUTUS_MAPI_E_PROFILE_DELETED;
		break;
	default:
	{
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown HRESULT from MAPI : %X", HValue);
		BRUTUS_LOG_BUG(msg);
	}
	BValue = ::BRUTUS::BRUTUS_UNKNOWN_ERROR;
	return false;
	}

	return true;
}


bool sPropProblem_mapi_to_brutus(::SPropProblem *Mapi_Problem,
				 ::BRUTUS::SPropProblem& Brutus_Problem,
				 bool DeAlloc)
{
	if (!Mapi_Problem)
		return false;

	proptag_mapi_to_brutus(Mapi_Problem->ulPropTag, Brutus_Problem.ulPropTag);
	hresult_to_bresult(Mapi_Problem->scode, Brutus_Problem.scode);
	Brutus_Problem.ulIndex = (::CORBA::ULong)Mapi_Problem->ulIndex;

	if (DeAlloc)
		MAPIFreeBuffer(Mapi_Problem);

	return true;
}


bool sPropProblem_array_mapi_to_brutus(::SPropProblemArray *Mapi_Problems,
				       ::BRUTUS::SPropProblemArray& Brutus_Problems,
				       bool DeAlloc)
{
	if (!Mapi_Problems) {
		Brutus_Problems.length(0);
		return true;
	}

	bool retval = true;
	Brutus_Problems.length(Mapi_Problems->cProblem);

	for (ULONG n = 0; n < Mapi_Problems->cProblem; n++)
		retval = retval && sPropProblem_mapi_to_brutus(&Mapi_Problems->aProblem[n],
							       Brutus_Problems[n],
							       false);
	if (DeAlloc)
		MAPIFreeBuffer(Mapi_Problems);

	return retval;
}


bool currency_mapi_to_brutus(::CURRENCY *Mapi_Curr,
			     ::BRUTUS::CURRENCY& Brutus_Curr,
			     bool DeAlloc)
{
	if (!Mapi_Curr)
		return false;

	Brutus_Curr.Hi = (::CORBA::Long)Mapi_Curr->Hi;
	Brutus_Curr.Lo = (::CORBA::ULong)Mapi_Curr->Lo;

	if (DeAlloc)
		MAPIFreeBuffer(Mapi_Curr);

	return true;
}


bool currency_brutus_to_mapi(const ::BRUTUS::CURRENCY *Brutus_Curr,
			     void *Parent,
			     ::CURRENCY*& Mapi_Curr)
{
	if (!Brutus_Curr)
		return false;

	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(::CURRENCY),
					     Parent,
					     (void**)&Mapi_Curr)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::CURRENCY),
					       (void**)&Mapi_Curr)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	}

	Mapi_Curr->Hi = (long)Brutus_Curr->Hi;
	Mapi_Curr->Lo = (ULONG)Brutus_Curr->Lo;

	return true;
}


bool currency_brutus_to_mapi_no_alloc(const ::BRUTUS::CURRENCY *Brutus_Curr,
				      ::CURRENCY& Mapi_Curr)
{
	if (!Brutus_Curr)
		return false;

	Mapi_Curr.Hi = (long)Brutus_Curr->Hi;
	Mapi_Curr.Lo = (ULONG)Brutus_Curr->Lo;

	return true;
}

bool large_int_mapi_to_brutus(::LARGE_INTEGER *Mapi_LI,
			      ::BRUTUS::LARGE_INTEGER& Brutus_LI,
			      bool DeAlloc)
{
	if (!Mapi_LI)
		return false;

	memcpy((void*)&Brutus_LI, (void*)Mapi_LI, sizeof(::CORBA::LongLong));

	if (DeAlloc)
		MAPIFreeBuffer(Mapi_LI);

	return true;
}

bool large_int_brutus_to_mapi(const ::BRUTUS::LARGE_INTEGER *Brutus_LI,
			      void *Parent,
			      ::LARGE_INTEGER*& Mapi_LI)
{
	if (!Brutus_LI)
		return false;

	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(::LARGE_INTEGER),
					     Parent,
					     (void**)&Mapi_LI)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::LARGE_INTEGER),
					       (void**)&Mapi_LI)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	}
	memcpy((void*)&Mapi_LI, (void*)Brutus_LI, sizeof(::LARGE_INTEGER));

	return true;
}


bool large_int_brutus_to_mapi_no_alloc(const ::BRUTUS::LARGE_INTEGER *Brutus_LI,
				       ::LARGE_INTEGER& Mapi_LI)
{
	if (!Brutus_LI)
		return false;

	memcpy((void*)&Mapi_LI, (void*)Brutus_LI, sizeof(::LARGE_INTEGER));

	return true;
}


bool filetime_mapi_to_brutus(::FILETIME *Mapi_FT,
			     ::BRUTUS::FILETIME& Brutus_FT,
			     bool DeAlloc)
{
	if (!Mapi_FT)
		return false;

	Brutus_FT.dwHighDateTime = (::CORBA::ULong)Mapi_FT->dwHighDateTime;
	Brutus_FT.dwLowDateTime = (::CORBA::ULong)Mapi_FT->dwLowDateTime;

	if (DeAlloc)
		MAPIFreeBuffer(Mapi_FT);

	return true;
}


bool filetime_brutus_to_mapi(const ::BRUTUS::FILETIME *Brutus_FT,
			     void *Parent,
			     ::FILETIME*& Mapi_FT)
{
	if (!Brutus_FT)
		return false;

	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(::FILETIME),
					     Parent,
					     (void**)&Mapi_FT)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::FILETIME),
					       (void**)&Mapi_FT)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	}

	Mapi_FT->dwHighDateTime = (ULONG)Brutus_FT->dwHighDateTime;
	Mapi_FT->dwLowDateTime = (ULONG)Brutus_FT->dwLowDateTime;

	return true;
}


bool filetime_brutus_to_mapi_no_alloc(const ::BRUTUS::FILETIME *Brutus_FT,
				      ::FILETIME& Mapi_FT)
{
	if (!Brutus_FT)
		return false;

	Mapi_FT.dwHighDateTime = (ULONG)Brutus_FT->dwHighDateTime;
	Mapi_FT.dwLowDateTime = (ULONG)Brutus_FT->dwLowDateTime;

	return true;
}


bool sbinary_mapi_to_brutus(::SBinary *Mapi_Bin,
			    ::BRUTUS::SBinary& Brutus_Bin,
			    bool DeAlloc)
{
	if (!Mapi_Bin)
		return false;

	Brutus_Bin.length(Mapi_Bin->cb);
	for (ULONG n = 0; n < Mapi_Bin->cb; n++)
		Brutus_Bin[n] = (::CORBA::Octet)Mapi_Bin->lpb[n];

	if (DeAlloc)
		MAPIFreeBuffer(Mapi_Bin);

	return true;
}


bool sbinary_brutus_to_mapi(const ::BRUTUS::SBinary *Brutus_Bin,
			    void *Parent,
			    ::SBinary*& Mapi_Bin)
{
	if (!Brutus_Bin)
		return false;

	if (!Brutus_Bin->length()) {
		Mapi_Bin = 0;
		return true;
	}

	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(::SBinary) + Brutus_Bin->length(),
					     Parent,
					     (void**)&Mapi_Bin)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::SBinary) + Brutus_Bin->length(),
					       (void**)&Mapi_Bin)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	}

	Mapi_Bin->cb = Brutus_Bin->length();
	for (ULONG n = 0; n < Mapi_Bin->cb; n++)
		Mapi_Bin->lpb[n] = (unsigned char)(*Brutus_Bin)[n];

	return true;
}


bool sbinary_brutus_to_mapi_internal_alloc(const ::BRUTUS::SBinary *Brutus_Bin,
					   void *Parent,
					   ::SBinary* const Mapi_Bin)
{
	if (!Brutus_Bin)
		return false;

	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(unsigned char) * Brutus_Bin->length(),
					     Parent,
					     (void**)&Mapi_Bin->lpb)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(unsigned char) * Brutus_Bin->length(),
					       (void**)&Mapi_Bin->lpb)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	}

	Mapi_Bin->cb = Brutus_Bin->length();
	for (ULONG n = 0; n < Mapi_Bin->cb; n++)
		Mapi_Bin->lpb[n] = (unsigned char)(*Brutus_Bin)[n];

	return true;
}


bool sbinary_array_mapi_to_brutus(::SBinaryArray *Mapi_BinArray,
				  ::BRUTUS::SBinaryArray& Brutus_BinArray,
				  bool DeAlloc)
{
	if (!Mapi_BinArray) {
		Brutus_BinArray.length(0);
		return false;
	}

	bool retval = true;
	Brutus_BinArray.length(Mapi_BinArray->cValues);
	for (ULONG n = 0; n < Mapi_BinArray->cValues; n++)
		retval = retval && sbinary_mapi_to_brutus(&Mapi_BinArray->lpbin[n],
							  Brutus_BinArray[n],
							  false);
	if (DeAlloc)
		MAPIFreeBuffer(Mapi_BinArray);

	return retval;
}


bool sbinary_array_brutus_to_mapi(const ::BRUTUS::SBinaryArray *Brutus_BinArray,
				  void *Parent,
				  ::SBinaryArray*& Mapi_BinArray)
{
	if (!Brutus_BinArray)
		return false;

	if (!Brutus_BinArray->length()) {
		Mapi_BinArray = 0;
		return true;
	}

	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(::SBinaryArray),
					     Parent,
					     (void**)&Mapi_BinArray)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::SBinaryArray),
					       (void**)&Mapi_BinArray)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = Mapi_BinArray;
	}
	if (S_OK != MAPIAllocateMore(sizeof(::SBinary) * Brutus_BinArray->length(),
				     Parent,
				     (void**)&Mapi_BinArray->lpbin)) {
		BRUTUS_LOG_ERR("No memory");
		MAPIFreeBuffer(Mapi_BinArray);
		return false;
	}

	bool retval = true;
	Mapi_BinArray->cValues = Brutus_BinArray->length();
	for (ULONG n = 0; n < Mapi_BinArray->cValues; n++) {
		retval = retval && sbinary_brutus_to_mapi_internal_alloc(&(*Brutus_BinArray)[n],
									 Parent,
									 &(Mapi_BinArray->lpbin[n]));
	}
	return retval;
}


bool sbinary_array_brutus_to_mapi_internal_alloc(const ::BRUTUS::SBinaryArray *Brutus_BinArray,
						 void *Parent,
						 ::SBinaryArray* const Mapi_BinArray)
{
	if (!Brutus_BinArray)
		return false;

	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(::SBinary) * Brutus_BinArray->length(),
					     Parent,
					     (void**)&Mapi_BinArray->lpbin)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::SBinary) * Brutus_BinArray->length(),
					       (void**)&Mapi_BinArray->lpbin)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = Mapi_BinArray->lpbin;
	}

	bool retval = true;
	Mapi_BinArray->cValues = Brutus_BinArray->length();
	for (ULONG n = 0; n < Mapi_BinArray->cValues; n++)
		retval = retval && sbinary_brutus_to_mapi_internal_alloc(&(*Brutus_BinArray)[n],
									 Parent,
									 &(Mapi_BinArray->lpbin[n]));
	return retval;
}

//
// Hrmpff! There is no way to tell if some of these
// property types are signed or unsigned. Take e.g
// PT_LONG.. MSDN says:
//
// PT_LONG (PT_MV_LONG)
// Signed or unsigned 32-bit integer. This property
// type is the same as PT_I4 and the OLE type VT_I4.
//
// What gives.. but we just have to work with what
// we have, don't we ?
//
bool spropvalue_mapi_to_brutus(::SPropValue *Mapi_SPropValue,
			       ::BRUTUS::SPropValue& Brutus_SPropValue,
			       LPMAPISESSION Mapi_Session,
			       bool DeAlloc,
			       PortableServer::POA_ptr Poa)
{
	ULONG n;
	ULONG prop_id = PROP_ID(Mapi_SPropValue->ulPropTag);
	Brutus_SPropValue.dwAlignPad = Mapi_SPropValue->dwAlignPad;

	switch (PROP_TYPE(Mapi_SPropValue->ulPropTag)) {
	case PT_UNSPECIFIED :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_UNSPECIFIED, prop_id);
		break;
	case PT_NULL :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_NULL, prop_id);
		Brutus_SPropValue.Value.x((::CORBA::ULong)Mapi_SPropValue->Value.x);
		break;
	case PT_SHORT :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_SHORT, prop_id);
		Brutus_SPropValue.Value.i((::CORBA::Short)Mapi_SPropValue->Value.i);
		break;
	case PT_LONG :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_LONG, prop_id);
		Brutus_SPropValue.Value.l((::CORBA::Long)Mapi_SPropValue->Value.l);
		break;
	case PT_FLOAT :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_FLOAT, prop_id);
		Brutus_SPropValue.Value.flt((::CORBA::Float)Mapi_SPropValue->Value.flt);
		break;
	case PT_DOUBLE :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_DOUBLE, prop_id);
		Brutus_SPropValue.Value.dbl((::CORBA::Double)Mapi_SPropValue->Value.dbl);
		break;
	case PT_CURRENCY :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_CURRENCY, prop_id);
		{
			::BRUTUS::CURRENCY c;
			Brutus_SPropValue.Value.cur(c);
		}
		currency_mapi_to_brutus(&Mapi_SPropValue->Value.cur, Brutus_SPropValue.Value.cur());
		break;
	case PT_APPTIME :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_APPTIME, prop_id);
		Brutus_SPropValue.Value.at((::CORBA::Double)Mapi_SPropValue->Value.at);
		break;
	case PT_ERROR :
	{
		::BRUTUS::BRESULT br;
			hresult_to_bresult(Mapi_SPropValue->Value.err, br);

			Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_ERROR, prop_id);
			Brutus_SPropValue.Value.err(br);
	}
	break;
	case PT_BOOLEAN :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_BOOLEAN, prop_id);
		Brutus_SPropValue.Value.b(Mapi_SPropValue->Value.b ? (::CORBA::Boolean)1 : (::CORBA::Boolean)0);
		break;
	case PT_OBJECT :
	{
		if (::CORBA::is_nil(Poa)) {
			BRUTUS_LOG_BUG("POA parameter was NIL");
			return false;
		}

		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_OBJECT, prop_id);
		::BRUTUS::IUnknown_ptr obj;
		obj = create_object<BRUTUS_IUnknown_i, ::BRUTUS::IUnknown, LPUNKNOWN>
			((LPUNKNOWN)Mapi_SPropValue->Value.x, Poa, Mapi_Session);

		Brutus_SPropValue.Value.obj(obj);
	}
	break;
	case PT_LONGLONG :
	{
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_LONGLONG, prop_id);
		::BRUTUS::LARGE_INTEGER li;
		large_int_mapi_to_brutus(&Mapi_SPropValue->Value.li, li, false);
		Brutus_SPropValue.Value.li(li);
	}
	break;
	case PT_STRING8 :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_STRING8, prop_id);
		if (Mapi_SPropValue->Value.lpszA) {
			if (scramble_content) {
				char *scr_str = NULL;
				size_t scr_len = strlen(Mapi_SPropValue->Value.lpszA);

				switch (Brutus_SPropValue.ulPropTag) {
				case ::BRUTUS::BRUTUS_PR_BODY :
					scr_str = (char*)malloc(scr_len + 1);
					for (n = 0; n < scr_len; n++)
						scr_str[n] = 'B';
					break;
				case ::BRUTUS::BRUTUS_PR_BODY_HTML :
					scr_str = (char*)malloc(scr_len + 1);
					for (n = 0; n < scr_len; n++)
						scr_str[n] = 'H';
					break;
				case ::BRUTUS::BRUTUS_PR_SUBJECT :
					scr_str = (char*)malloc(scr_len + 1);
					for (n = 0; n < scr_len; n++)
						scr_str[n] = 'S';
					break;
				default :
					break;
				}
				if (scr_str) {
					scr_str[scr_len] = '\0';
					Brutus_SPropValue.Value.lpszA(::CORBA::string_dup(scr_str));
					free(scr_str);
				} else
					Brutus_SPropValue.Value.lpszA(::CORBA::string_dup("*** SCRAMBLED ***"));
			} else {
				if (local_code_page) { // Codeset conversion from "local_code_page" to UTF8 
					char *tmp = codepage_to_utf8(NULL, Mapi_SPropValue->Value.lpszA, local_code_page);
					Brutus_SPropValue.Value.lpszA(::CORBA::string_dup(tmp));
					MAPIFreeBuffer(tmp);
				} else {
					Brutus_SPropValue.Value.lpszA(::CORBA::string_dup(Mapi_SPropValue->Value.lpszA));
				}
			}
		} else
			Brutus_SPropValue.Value.lpszA(::CORBA::string_alloc(0));

		break;
	case PT_UNICODE :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_UNICODE, prop_id);		
			if (Mapi_SPropValue->Value.lpszW) {
				Brutus_SPropValue.Value.lpszW(unicode_to_utf8(Mapi_SPropValue->Value.lpszW));
			} else {
				Brutus_SPropValue.Value.lpszW(::CORBA::string_alloc(0));
			}		
		break;
	case PT_SYSTIME :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_SYSTIME, prop_id);
		{
			::BRUTUS::FILETIME f;
			Brutus_SPropValue.Value.ft(f);
		}
		filetime_mapi_to_brutus(&Mapi_SPropValue->Value.ft, Brutus_SPropValue.Value.ft(), false);
		break;
	case PT_CLSID :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_CLSID, prop_id);
		{
			::BRUTUS::GUID_var g;
			guid_mapi_to_brutus(Mapi_SPropValue->Value.lpguid, g.out(), false);
			Brutus_SPropValue.Value.lpguid(g._retn());
		}
		break;
	case PT_BINARY :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_BINARY, prop_id);
		{
			::BRUTUS::SBinary sb;
			Brutus_SPropValue.Value.bin(sb);
		}
		sbinary_mapi_to_brutus(&Mapi_SPropValue->Value.bin, Brutus_SPropValue.Value.bin(), false);
		if ((scramble_content) && (::BRUTUS::BRUTUS_PR_ATTACH_DATA_BIN == Brutus_SPropValue.ulPropTag)) {
			for (n = 0; n < Brutus_SPropValue.Value.bin().length(); n++)
				Brutus_SPropValue.Value.bin()[(::CORBA::ULong)n] = (::CORBA::Octet)'A';
		}
		break;
	case PT_MV_SHORT :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_MV_SHORT, prop_id);
		{
			::BRUTUS::SShortArray a;
			Brutus_SPropValue.Value.MVi(a);
		}
		Brutus_SPropValue.Value.MVi().length(Mapi_SPropValue->Value.MVi.cValues);
		for (n = 0; n < Mapi_SPropValue->Value.MVi.cValues; n++)
			Brutus_SPropValue.Value.MVi()[n] = (::CORBA::Short)Mapi_SPropValue->Value.MVi.lpi[n];
		break;
	case PT_MV_LONG :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_MV_LONG, prop_id);
		{
			::BRUTUS::SLongArray a;
			Brutus_SPropValue.Value.MVl(a);
		}
		Brutus_SPropValue.Value.MVl().length(Mapi_SPropValue->Value.MVl.cValues);
		for (n = 0; n < Mapi_SPropValue->Value.MVl.cValues; n++)
			Brutus_SPropValue.Value.MVl()[n] = (::CORBA::Long)Mapi_SPropValue->Value.MVl.lpl[n];
		break;
	case PT_MV_FLOAT :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_MV_FLOAT, prop_id);
		{
			::BRUTUS::SRealArray a;
			Brutus_SPropValue.Value.MVflt(a);
		}
		Brutus_SPropValue.Value.MVflt().length(Mapi_SPropValue->Value.MVflt.cValues);
		for (n = 0; n < Mapi_SPropValue->Value.MVflt.cValues; n++)
			Brutus_SPropValue.Value.MVflt()[n] = (::CORBA::Float)Mapi_SPropValue->Value.MVflt.lpflt[n];
		break;
	case PT_MV_DOUBLE :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_MV_DOUBLE, prop_id);
		{
			::BRUTUS::SDoubleArray a;
			Brutus_SPropValue.Value.MVdbl(a);
		}
		Brutus_SPropValue.Value.MVdbl().length(Mapi_SPropValue->Value.MVdbl.cValues);
		for (n = 0; n < Mapi_SPropValue->Value.MVdbl.cValues; n++)
			Brutus_SPropValue.Value.MVdbl()[n] = (::CORBA::Double)Mapi_SPropValue->Value.MVdbl.lpdbl[n];
		break;
	case PT_MV_CURRENCY :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_MV_CURRENCY, prop_id);
		{
			::BRUTUS::SCurrencyArray a;
			Brutus_SPropValue.Value.MVcur(a);
		}
		Brutus_SPropValue.Value.MVcur().length(Mapi_SPropValue->Value.MVcur.cValues);
		for (n = 0; n < Mapi_SPropValue->Value.MVcur.cValues; n++)
			currency_mapi_to_brutus(&Mapi_SPropValue->Value.MVcur.lpcur[n], Brutus_SPropValue.Value.MVcur()[n], false);
		break;
	case PT_MV_APPTIME :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_MV_APPTIME, prop_id);
		{
			::BRUTUS::SAppTimeArray a;
			Brutus_SPropValue.Value.MVat(a);
		}
		Brutus_SPropValue.Value.MVat().length(Mapi_SPropValue->Value.MVat.cValues);
		for (n = 0; n < Mapi_SPropValue->Value.MVat.cValues; n++)
			Brutus_SPropValue.Value.MVat()[n] = (::CORBA::Double)Mapi_SPropValue->Value.MVat.lpat[n];
		break;
	case PT_MV_SYSTIME :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_MV_SYSTIME, prop_id);
		{
			::BRUTUS::SDateTimeArray a;
			Brutus_SPropValue.Value.MVft(a);
		}
		Brutus_SPropValue.Value.MVft().length(Mapi_SPropValue->Value.MVft.cValues);
		for (n = 0; n < Mapi_SPropValue->Value.MVft.cValues; n++)
			filetime_mapi_to_brutus(&Mapi_SPropValue->Value.MVft.lpft[n], Brutus_SPropValue.Value.MVft()[n], false);
		break;
	case PT_MV_STRING8 :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_MV_STRING8, prop_id);
		{
			::BRUTUS::SLPSTRArray a;
			Brutus_SPropValue.Value.MVszA(a);
		}
		Brutus_SPropValue.Value.MVszA().length(Mapi_SPropValue->Value.MVszA.cValues);
		for (n = 0; n < Mapi_SPropValue->Value.MVszA.cValues; n++)
			if (Mapi_SPropValue->Value.MVszA.lppszA[n])
				Brutus_SPropValue.Value.MVszA()[n] = ::CORBA::string_dup(Mapi_SPropValue->Value.MVszA.lppszA[n]);
			else
				Brutus_SPropValue.Value.MVszA()[n] = ::CORBA::string_alloc(0);
		break;
	case PT_MV_BINARY :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_MV_BINARY, prop_id);
		{
			::BRUTUS::SBinaryArray a;
			Brutus_SPropValue.Value.MVbin(a);
		}
		Brutus_SPropValue.Value.MVbin().length(Mapi_SPropValue->Value.MVbin.cValues);
		for (n = 0; n < Mapi_SPropValue->Value.MVbin.cValues; n++)
			sbinary_mapi_to_brutus(&Mapi_SPropValue->Value.MVbin.lpbin[n], Brutus_SPropValue.Value.MVbin()[n], false);
		break;
	case PT_MV_UNICODE :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_MV_UNICODE, prop_id);
		{
			::BRUTUS::SWStringArray a;
			Brutus_SPropValue.Value.MVszW(a);
		}
		Brutus_SPropValue.Value.MVszW().length(Mapi_SPropValue->Value.MVszW.cValues);
		for (n = 0; n < Mapi_SPropValue->Value.MVszW.cValues; n++)
			if (Mapi_SPropValue->Value.MVszW.lppszW[n])
				Brutus_SPropValue.Value.MVszW()[n] = unicode_to_utf8((LPCWSTR)Mapi_SPropValue->Value.MVszW.lppszW[n]);
			else
				Brutus_SPropValue.Value.MVszW()[n] = ::CORBA::string_alloc(0);
		break;
	case PT_MV_CLSID :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_MV_CLSID, prop_id);
		{
			::BRUTUS::SGuidArray a;
			Brutus_SPropValue.Value.MVguid(a);
		}
		Brutus_SPropValue.Value.MVguid().length(Mapi_SPropValue->Value.MVguid.cValues);
		{
			::BRUTUS::GUID_var b_guid;
			for (n = 0; n < Mapi_SPropValue->Value.MVguid.cValues; n++) {
				guid_mapi_to_brutus(&Mapi_SPropValue->Value.MVguid.lpguid[n], b_guid.out(), false);
				Brutus_SPropValue.Value.MVguid()[n] = b_guid._retn();
			}
		}
		break;
	case PT_MV_LONGLONG :
		Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_MV_LONGLONG, prop_id);
		{
			::BRUTUS::SLargeIntegerArray a;
			Brutus_SPropValue.Value.MVli(a);
		}
		Brutus_SPropValue.Value.MVli().length(Mapi_SPropValue->Value.MVli.cValues);
		for (n = 0; n < Mapi_SPropValue->Value.MVli.cValues; n++)
			large_int_mapi_to_brutus(&Mapi_SPropValue->Value.MVli.lpli[n], Brutus_SPropValue.Value.MVli()[n], false);
		break;
	default :
	{
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown PROP_TYPE from MAPI : %X", PROP_TYPE(Mapi_SPropValue->ulPropTag));
		BRUTUS_LOG_BUG(msg);
	}
	Brutus_SPropValue.ulPropTag = PROP_TAG(::BRUTUS::BRUTUS_PT_UNSPECIFIED, prop_id);
	return false;
	}

	if (DeAlloc)
		MAPIFreeBuffer(Mapi_SPropValue);

	return true;
}

bool spropvalue_array_mapi_to_brutus(const ULONG cValues,
				     ::SPropValue *Mapi_SPropValues,
				     ::BRUTUS::seq_SPropValue & Brutus_SPropValues,
				     LPMAPISESSION Mapi_Session,
				     bool DeAlloc,
				     PortableServer::POA_ptr Poa)
{
	bool retval = true;

	Brutus_SPropValues.length(cValues);
	for (ULONG i = 0; i < cValues; i++) {
		retval = retval && spropvalue_mapi_to_brutus(&Mapi_SPropValues[i],
							     Brutus_SPropValues[i],
							     Mapi_Session,
							     false,
							     Poa);
	}

	if (DeAlloc)
		MAPIFreeBuffer(Mapi_SPropValues);

	return retval;
}

bool spropvalue_brutus_to_mapi_internal_alloc(const ::BRUTUS::SPropValue *Brutus_SPropValue,
					      void *Parent,
					      ::SPropValue* const Mapi_SPropValue)
{
	if (!Brutus_SPropValue)
		return false;

	ULONG n;
	ULONG prop_id = PROP_ID(Brutus_SPropValue->ulPropTag);
	ULONG type = Brutus_SPropValue->Value._d();

	Mapi_SPropValue->dwAlignPad = Brutus_SPropValue->dwAlignPad;

	if (::BRUTUS::BRUTUS_PT_UNSPECIFIED == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_UNSPECIFIED, prop_id);
	} else if (::BRUTUS::BRUTUS_PT_NULL == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_NULL, prop_id);
		Mapi_SPropValue->Value.x = (ULONG)Brutus_SPropValue->Value.x();
	} else if (::BRUTUS::BRUTUS_PT_SHORT == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_SHORT, prop_id);
		Mapi_SPropValue->Value.i = (short)Brutus_SPropValue->Value.i();
	} else if (::BRUTUS::BRUTUS_PT_LONG == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_LONG, prop_id);
		Mapi_SPropValue->Value.l = (LONG)Brutus_SPropValue->Value.l();
	} else if (::BRUTUS::BRUTUS_PT_ULONG == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_LONG, prop_id);
		Mapi_SPropValue->Value.ul = (LONG)Brutus_SPropValue->Value.l();
	} else if (::BRUTUS::BRUTUS_PT_FLOAT == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_FLOAT, prop_id);
		Mapi_SPropValue->Value.flt = (float)Brutus_SPropValue->Value.flt();
	} else if (::BRUTUS::BRUTUS_PT_DOUBLE == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_DOUBLE, prop_id);
		Mapi_SPropValue->Value.dbl = (double)Brutus_SPropValue->Value.dbl();
	} else if (::BRUTUS::BRUTUS_PT_CURRENCY == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_CURRENCY, prop_id);
		currency_brutus_to_mapi_no_alloc(&Brutus_SPropValue->Value.cur(),
						 Mapi_SPropValue->Value.cur);
	} else if (::BRUTUS::BRUTUS_PT_APPTIME == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_APPTIME, prop_id);
		Mapi_SPropValue->Value.at = (double)Brutus_SPropValue->Value.at();
	} else if (::BRUTUS::BRUTUS_PT_ERROR == type) {
		HRESULT hr;

		if (!bresult_to_hresult(Brutus_SPropValue->Value.err(), hr)) {
			BRUTUS_LOG_BUG("BRUTUS specific error code");
			Mapi_SPropValue->Value.err = E_FAIL;
		} else
			Mapi_SPropValue->Value.err = hr;
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_ERROR, prop_id);
	} else if (::BRUTUS::BRUTUS_PT_BOOLEAN == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_BOOLEAN, prop_id);
		Mapi_SPropValue->Value.b = (unsigned short) (Brutus_SPropValue->Value.b() ? 1 : 0);
	} else if (::BRUTUS::BRUTUS_PT_OBJECT == type) {
		BRUTUS_LOG_BUG("::BRUTUS::BRUTUS_PT_OBJECT is not supported");
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_UNSPECIFIED, prop_id);
		return false;
	} else if (::BRUTUS::BRUTUS_PT_LONGLONG == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_LONGLONG, prop_id);
		::BRUTUS::LARGE_INTEGER li = Brutus_SPropValue->Value.li();
		large_int_brutus_to_mapi_no_alloc(&li, Mapi_SPropValue->Value.li);
	} else if (::BRUTUS::BRUTUS_PT_STRING8 == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_STRING8, prop_id);
		if (Brutus_SPropValue->Value.lpszA()) {
			if (local_code_page) {
				Mapi_SPropValue->Value.lpszA = utf8_to_codepage(Parent, Brutus_SPropValue->Value.lpszA(), local_code_page);
			} else {
				Mapi_SPropValue->Value.lpszA = mstrdup(Parent, Brutus_SPropValue->Value.lpszA());
			}
		} else {
			Mapi_SPropValue->Value.lpszA = mstrdup(Parent, "");
			BRUTUS_LOG_BUG("NIL CORBA string");
		}
	} else if (::BRUTUS::BRUTUS_PT_UNICODE == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_UNICODE, prop_id);
		if (Brutus_SPropValue->Value.lpszW()) {
			Mapi_SPropValue->Value.lpszW = utf8_to_unicode(Parent, (const char*)Brutus_SPropValue->Value.lpszW());
		} else {
			Mapi_SPropValue->Value.lpszW = utf8_to_unicode(Parent, "");
			BRUTUS_LOG_BUG("NIL CORBA wide string");
		}
	} else if (::BRUTUS::BRUTUS_PT_SYSTIME == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_SYSTIME, prop_id);
		filetime_brutus_to_mapi_no_alloc(&Brutus_SPropValue->Value.ft(),
						 Mapi_SPropValue->Value.ft);
	} else if (::BRUTUS::BRUTUS_PT_CLSID == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_CLSID, prop_id);
		if (!guid_brutus_to_mapi((const ::BRUTUS::GUID)Brutus_SPropValue->Value.lpguid(),
					 Parent,
					 Mapi_SPropValue->Value.lpguid)) {
			BRUTUS_LOG_ERR("No memory");
			Mapi_SPropValue->ulPropTag = PROP_TAG(PT_UNSPECIFIED, prop_id);
			Mapi_SPropValue->Value.lpguid = 0;
			return false;
		}
	} else if (::BRUTUS::BRUTUS_PT_BINARY == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_BINARY, prop_id);
		sbinary_brutus_to_mapi_internal_alloc(&Brutus_SPropValue->Value.bin(),
						      Parent,
						      &(Mapi_SPropValue->Value.bin));
	} else if (::BRUTUS::BRUTUS_PT_MV_SHORT == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_MV_SHORT, prop_id);
		n = Brutus_SPropValue->Value.MVi().length();
		if (S_OK != MAPIAllocateMore(n*sizeof(short int),
					     Parent,
					     (void **)&Mapi_SPropValue->Value.MVi.lpi)) {
			BRUTUS_LOG_ERR("No memory");
			Mapi_SPropValue->ulPropTag = PROP_TAG(PT_UNSPECIFIED, prop_id);
			Mapi_SPropValue->Value.MVi.lpi = 0;
			return false;
		}

		Mapi_SPropValue->Value.MVi.cValues = n;
		for (n = 0; n < Mapi_SPropValue->Value.MVi.cValues; n++)
			Mapi_SPropValue->Value.MVi.lpi[n] = (short int)Brutus_SPropValue->Value.MVi()[n];
	} else if (::BRUTUS::BRUTUS_PT_MV_LONG == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_MV_LONG, prop_id);
		n = Brutus_SPropValue->Value.MVl().length();
		if (S_OK != MAPIAllocateMore(n*sizeof(LONG),
					     Parent,
					     (void **)&Mapi_SPropValue->Value.MVl.lpl)) {
			BRUTUS_LOG_ERR("No memory");
			Mapi_SPropValue->ulPropTag = PROP_TAG(PT_UNSPECIFIED, prop_id);
			Mapi_SPropValue->Value.MVl.lpl = 0;
			return false;
		}

		Mapi_SPropValue->Value.MVl.cValues = n;
		for (n = 0; n < Mapi_SPropValue->Value.MVl.cValues; n++)
			Mapi_SPropValue->Value.MVl.lpl[n] = (LONG)Brutus_SPropValue->Value.MVl()[n];
	} else if (::BRUTUS::BRUTUS_PT_MV_FLOAT == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_MV_FLOAT, prop_id);
		n = Brutus_SPropValue->Value.MVflt().length();
		if (S_OK != MAPIAllocateMore(n*sizeof(float),
					     Parent,
					     (void **)&Mapi_SPropValue->Value.MVflt.lpflt)) {
			BRUTUS_LOG_ERR("No memory");
			Mapi_SPropValue->ulPropTag = PROP_TAG(PT_UNSPECIFIED, prop_id);
			Mapi_SPropValue->Value.MVflt.lpflt = 0;
			return false;
		}

		Mapi_SPropValue->Value.MVflt.cValues = n;
		for (n = 0; n < Mapi_SPropValue->Value.MVflt.cValues; n++)
			Mapi_SPropValue->Value.MVflt.lpflt[n] = (float)Brutus_SPropValue->Value.MVflt()[n];
	} else if (::BRUTUS::BRUTUS_PT_MV_DOUBLE == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_MV_DOUBLE, prop_id);
		n = Brutus_SPropValue->Value.MVdbl().length();
		if (S_OK != MAPIAllocateMore(n*sizeof(double),
					     Parent,
					     (void **)&Mapi_SPropValue->Value.MVdbl.lpdbl)) {
			BRUTUS_LOG_ERR("No memory");
			Mapi_SPropValue->ulPropTag = PROP_TAG(PT_UNSPECIFIED, prop_id);
			Mapi_SPropValue->Value.MVdbl.lpdbl = 0;
			return false;
		}

		Mapi_SPropValue->Value.MVdbl.cValues = n;
		for (n = 0; n < Mapi_SPropValue->Value.MVdbl.cValues; n++)
			Mapi_SPropValue->Value.MVdbl.lpdbl[n] = (double)Brutus_SPropValue->Value.MVdbl()[n];
	} else if (::BRUTUS::BRUTUS_PT_MV_CURRENCY == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_MV_CURRENCY, prop_id);
		n = Brutus_SPropValue->Value.MVcur().length();
		if (S_OK != MAPIAllocateMore(n*sizeof(::CURRENCY),
					     Parent,
					     (void **)&Mapi_SPropValue->Value.MVcur.lpcur)) {
			BRUTUS_LOG_ERR("No memory");
			Mapi_SPropValue->ulPropTag = PROP_TAG(PT_UNSPECIFIED, prop_id);
			Mapi_SPropValue->Value.MVcur.lpcur = 0;
			return false;
		}

		Mapi_SPropValue->Value.MVcur.cValues = n;
		for (n = 0; n < Mapi_SPropValue->Value.MVcur.cValues; n++)
			currency_brutus_to_mapi_no_alloc(&Brutus_SPropValue->Value.MVcur()[n],
							 Mapi_SPropValue->Value.MVcur.lpcur[n]);
	} else if (::BRUTUS::BRUTUS_PT_MV_APPTIME == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_MV_APPTIME, prop_id);
		n = Brutus_SPropValue->Value.MVat().length();
		if (S_OK != MAPIAllocateMore(n*sizeof(double),
					     Parent,
					     (void **)&Mapi_SPropValue->Value.MVat.lpat)) {
			BRUTUS_LOG_ERR("No memory");
			Mapi_SPropValue->ulPropTag = PROP_TAG(PT_UNSPECIFIED, prop_id);
			Mapi_SPropValue->Value.MVat.lpat = 0;
			return false;
		}

		Mapi_SPropValue->Value.MVat.cValues = n;
		for (n = 0; n < Mapi_SPropValue->Value.MVat.cValues; n++)
			Mapi_SPropValue->Value.MVat.lpat[n] = (double)Brutus_SPropValue->Value.MVat()[n];
	} else if (::BRUTUS::BRUTUS_PT_MV_SYSTIME == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_MV_SYSTIME, prop_id);
		n = Brutus_SPropValue->Value.MVft().length();
		if (S_OK != MAPIAllocateMore(n*sizeof(::FILETIME),
					     Parent,
					     (void **)&Mapi_SPropValue->Value.MVft.lpft)) {
			BRUTUS_LOG_ERR("No memory");
			Mapi_SPropValue->ulPropTag = PROP_TAG(PT_UNSPECIFIED, prop_id);
			Mapi_SPropValue->Value.MVft.lpft = 0;
			return false;
		}

		Mapi_SPropValue->Value.MVft.cValues = n;
		for (n = 0; n < Mapi_SPropValue->Value.MVft.cValues; n++)
			filetime_brutus_to_mapi_no_alloc(&Brutus_SPropValue->Value.MVft()[n],
							 Mapi_SPropValue->Value.MVft.lpft[n]);
	} else if (::BRUTUS::BRUTUS_PT_MV_BINARY == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_MV_BINARY, prop_id);
		n = Brutus_SPropValue->Value.MVbin().length();
		if (S_OK != MAPIAllocateMore(n*sizeof(::SBinary),
					     Parent,
					     (void **)&Mapi_SPropValue->Value.MVbin.lpbin)) {
			BRUTUS_LOG_ERR("No memory");
			Mapi_SPropValue->ulPropTag = PROP_TAG(PT_UNSPECIFIED, prop_id);
			Mapi_SPropValue->Value.MVbin.lpbin = 0;
			return false;
		}

		Mapi_SPropValue->Value.MVbin.cValues = n;
		for (n = 0; n < Mapi_SPropValue->Value.MVbin.cValues; n++)
			sbinary_brutus_to_mapi_internal_alloc(&Brutus_SPropValue->Value.MVbin()[n],
							      Parent,
							      &(Mapi_SPropValue->Value.MVbin.lpbin[n]));
	} else if (::BRUTUS::BRUTUS_PT_MV_STRING8 == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_MV_STRING8, prop_id);
		n = Brutus_SPropValue->Value.MVszA().length();
		if (S_OK != MAPIAllocateMore(n*sizeof(char*),
					     Parent,
					     (void **)&Mapi_SPropValue->Value.MVszA.lppszA)) {
			BRUTUS_LOG_ERR("No memory");
			Mapi_SPropValue->ulPropTag = PROP_TAG(PT_UNSPECIFIED, prop_id);
			Mapi_SPropValue->Value.MVszA.lppszA = 0;
			return false;
		}

		Mapi_SPropValue->Value.MVszA.cValues = n;
		for (n = 0; n < Mapi_SPropValue->Value.MVszA.cValues; n++) {
			if (Brutus_SPropValue->Value.MVszA()[n]) {
				if (local_code_page) {
					Mapi_SPropValue->Value.MVszA.lppszA[n] = utf8_to_codepage(Parent, (const char*)Brutus_SPropValue->Value.MVszA()[n], local_code_page);
				} else {
					Mapi_SPropValue->Value.MVszA.lppszA[n] = mstrdup(Parent, (const char*)Brutus_SPropValue->Value.MVszA()[n]);
				}
			} else {
				Mapi_SPropValue->Value.MVszA.lppszA[n] = mstrdup(Parent, "");
			}
		}
	} else if (::BRUTUS::BRUTUS_PT_MV_UNICODE == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_MV_UNICODE, prop_id);
		n = Brutus_SPropValue->Value.MVszW().length(); 
		if (S_OK != MAPIAllocateMore(n*sizeof(wchar_t*),
					     Parent,
					     (void **)&Mapi_SPropValue->Value.MVszW.lppszW)) {
			BRUTUS_LOG_ERR("No memory");
			Mapi_SPropValue->ulPropTag = PROP_TAG(PT_UNSPECIFIED, prop_id);
			Mapi_SPropValue->Value.MVszW.lppszW = 0;
			return false;
		}

		Mapi_SPropValue->Value.MVszW.cValues = n;
		for (n = 0; n < Mapi_SPropValue->Value.MVszW.cValues; n++) {
			if (Brutus_SPropValue->Value.MVszW()[n])
				Mapi_SPropValue->Value.MVszW.lppszW[n] = utf8_to_unicode(Parent, (const char*)Brutus_SPropValue->Value.MVszW()[n]);
			else
				Mapi_SPropValue->Value.MVszW.lppszW[n] = utf8_to_unicode(Parent, "");
		}
	} else if (::BRUTUS::BRUTUS_PT_MV_CLSID == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_MV_CLSID, prop_id);
		n = Brutus_SPropValue->Value.MVguid().length();
		if (S_OK != MAPIAllocateMore(n*sizeof(::GUID),
					     Parent,
					     (void **)&Mapi_SPropValue->Value.MVguid.lpguid)) {
			BRUTUS_LOG_ERR("No memory");
			Mapi_SPropValue->ulPropTag = PROP_TAG(PT_UNSPECIFIED, prop_id);
			Mapi_SPropValue->Value.MVguid.lpguid = 0;
			return false;
		}

		Mapi_SPropValue->Value.MVguid.cValues = n;
		{
			::BRUTUS::GUID_var b_guid;
			for (n = 0; n < Mapi_SPropValue->Value.MVguid.cValues; n++) {
				b_guid = Brutus_SPropValue->Value.MVguid()[n];
				guid_brutus_to_mapi_no_alloc(b_guid,
							     &Mapi_SPropValue->Value.MVguid.lpguid[n]);
			}
		}
	} else if (::BRUTUS::BRUTUS_PT_MV_LONGLONG == type) {
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_MV_LONGLONG, prop_id);
		n = Brutus_SPropValue->Value.MVli().length();
		if (S_OK != MAPIAllocateBuffer(n*sizeof(::LARGE_INTEGER),
					       (void **)&Mapi_SPropValue->Value.MVli.lpli)) {
			BRUTUS_LOG_ERR("No memory");
			Mapi_SPropValue->ulPropTag = PROP_TAG(PT_UNSPECIFIED, prop_id);
			Mapi_SPropValue->Value.MVli.lpli = 0;
			return false;
		}

		Mapi_SPropValue->Value.MVli.cValues = n;
		for (n = 0; n < Mapi_SPropValue->Value.MVli.cValues; n++)
			large_int_brutus_to_mapi_no_alloc(&Brutus_SPropValue->Value.MVli()[n],
							  Mapi_SPropValue->Value.MVli.lpli[n]);
	} else {
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown PROP_TYPE from BRUTUS : %X", PROP_TYPE(Brutus_SPropValue->ulPropTag));
		BRUTUS_LOG_BUG(msg);
		Mapi_SPropValue->ulPropTag = PROP_TAG(PT_UNSPECIFIED, prop_id);
		return false;
	}

	return true;
}

bool spropvalue_brutus_to_mapi(const ::BRUTUS::SPropValue *Brutus_SPropValue,
			       void *Parent,
			       ::SPropValue*& Mapi_SPropValue)
{
	if (!Brutus_SPropValue)
		return false;

	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(::SPropValue), Parent, (void**)&Mapi_SPropValue)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::SPropValue), (void**)&Mapi_SPropValue)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = (void*)Mapi_SPropValue;
	}

	return spropvalue_brutus_to_mapi_internal_alloc(Brutus_SPropValue, Parent, Mapi_SPropValue);
}

bool spropvalue_array_brutus_to_mapi(const ::BRUTUS::seq_SPropValue *Brutus_SPropValues,
				     void *Parent,
				     ULONG& cValues,
				     ::SPropValue*& Mapi_SPropValues)
{
	if (!Brutus_SPropValues)
		return false;

	cValues = Brutus_SPropValues->length();
	if (Parent) {
		if (S_OK != MAPIAllocateMore(cValues*sizeof(::SPropValue),
					     Parent,
					     (void**)&Mapi_SPropValues)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(cValues*sizeof(::SPropValue),
					       (void**)&Mapi_SPropValues)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = (void*)Mapi_SPropValues;
	}

	bool retval = true;
	for (ULONG i = 0; i < cValues; i++) {
		retval = retval && spropvalue_brutus_to_mapi_internal_alloc(&(*Brutus_SPropValues)[i],
									    Parent,
									    &(Mapi_SPropValues[i]));
	}

	return retval;
}

bool fuzzyLevel_brutus_to_mapi(const ::BRUTUS::FUZZY_TYPE Brutus_Fuzzy,
			       ULONG& Mapi_Fuzzy)
{
	::BRUTUS::FUZZY_TYPE fl = Brutus_Fuzzy;
	Mapi_Fuzzy = 0;

	if (fl & ::BRUTUS::BRUTUS_FL_FULLSTRING) {
		Mapi_Fuzzy |= FL_FULLSTRING;
		FLAGS_OFF(::BRUTUS::FUZZY_TYPE, fl, ::BRUTUS::BRUTUS_FL_FULLSTRING);
	} else if (fl & ::BRUTUS::BRUTUS_FL_SUBSTRING) {
		Mapi_Fuzzy |= FL_SUBSTRING;
		FLAGS_OFF(::BRUTUS::FUZZY_TYPE, fl, ::BRUTUS::BRUTUS_FL_SUBSTRING);
	} else if (fl & ::BRUTUS::BRUTUS_FL_PREFIX) {
		Mapi_Fuzzy |= FL_PREFIX;
		FLAGS_OFF(::BRUTUS::FUZZY_TYPE, fl, ::BRUTUS::BRUTUS_FL_PREFIX);
	} else {
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Missing or unknown fuzzy level from BRUTUS : %X", fl);
		BRUTUS_LOG_BUG(msg);

		return false;
	}

	if (fl & ::BRUTUS::BRUTUS_FL_IGNORECASE) {
		Mapi_Fuzzy |= FL_IGNORECASE;
		FLAGS_OFF(::BRUTUS::FUZZY_TYPE, fl, ::BRUTUS::BRUTUS_FL_IGNORECASE);
	}
	if (fl & ::BRUTUS::BRUTUS_FL_IGNORENONSPACE) {
		Mapi_Fuzzy |= FL_IGNORENONSPACE;
		FLAGS_OFF(::BRUTUS::FUZZY_TYPE, fl, ::BRUTUS::BRUTUS_FL_IGNORENONSPACE);
	}
	if (fl & ::BRUTUS::BRUTUS_FL_LOOSE) {
		Mapi_Fuzzy |= FL_LOOSE;
		FLAGS_OFF(::BRUTUS::FUZZY_TYPE, fl, ::BRUTUS::BRUTUS_FL_LOOSE);
	}

	if (fl) {
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown fuzzy level from BRUTUS : %X", fl);
		BRUTUS_LOG_BUG(msg);

		return false;
	}

	return true;
}


bool fuzzyLevel_mapi_to_brutus(const ULONG Mapi_Fuzzy,
			       ::BRUTUS::FUZZY_TYPE & Brutus_Fuzzy)
{
	ULONG fl = Mapi_Fuzzy;
	Brutus_Fuzzy = 0;

	if (FL_FULLSTRING == fl) { // FL_FULLSTRING == 0 (zero)
		Brutus_Fuzzy = ::BRUTUS::BRUTUS_FL_FULLSTRING;
		FLAGS_OFF(ULONG, fl, FL_FULLSTRING);
	} else if (fl & FL_SUBSTRING) {
		Brutus_Fuzzy |= ::BRUTUS::BRUTUS_FL_SUBSTRING;
		FLAGS_OFF(ULONG, fl, FL_SUBSTRING);
	} else if (fl & FL_PREFIX) {
		Brutus_Fuzzy |= ::BRUTUS::BRUTUS_FL_PREFIX;
		FLAGS_OFF(ULONG, fl, FL_PREFIX);
	} else {
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Missing or unknown fuzzy level from BRUTUS : %X", fl);
		BRUTUS_LOG_BUG(msg);

		return false;
	}

	if (fl & FL_IGNORECASE) {
		Brutus_Fuzzy |= ::BRUTUS::BRUTUS_FL_IGNORECASE;
		FLAGS_OFF(ULONG, fl, FL_IGNORECASE);
	}
	if (fl & FL_IGNORENONSPACE) {
		Brutus_Fuzzy |= ::BRUTUS::BRUTUS_FL_IGNORENONSPACE;
		FLAGS_OFF(ULONG, fl, FL_IGNORENONSPACE);
	}
	if (fl & FL_LOOSE) {
		Brutus_Fuzzy |= ::BRUTUS::BRUTUS_FL_LOOSE;
		FLAGS_OFF(ULONG, fl, FL_LOOSE);
	}

	if (fl) {
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown fuzzy level from BRUTUS : %X", fl);
		BRUTUS_LOG_BUG(msg);

		return false;
	}

	return true;
}


bool relop_brutus_to_mapi(const ::BRUTUS::RELOP_TYPE Brutus_Relop,
			  ULONG& Mapi_Relop)
{
	if (Brutus_Relop == ::BRUTUS::BRUTUS_RELOP_LT) {
		Mapi_Relop = RELOP_LT;
		return true;
	}

	if (Brutus_Relop == ::BRUTUS::BRUTUS_RELOP_LE) {
		Mapi_Relop = RELOP_LE;
		return true;
	}

	if (Brutus_Relop == ::BRUTUS::BRUTUS_RELOP_GT) {
		Mapi_Relop = RELOP_GT;
		return true;
	}

	if (Brutus_Relop == ::BRUTUS::BRUTUS_RELOP_GE) {
		Mapi_Relop = RELOP_GE;
		return true;
	}

	if (Brutus_Relop == ::BRUTUS::BRUTUS_RELOP_EQ) {
		Mapi_Relop = RELOP_EQ;
		return true;
	}

	if (Brutus_Relop == ::BRUTUS::BRUTUS_RELOP_NE) {
		Mapi_Relop = RELOP_NE;
		return true;
	}

	if (Brutus_Relop == ::BRUTUS::BRUTUS_RELOP_RE) {
		Mapi_Relop = RELOP_RE;
		return true;
	}

	{
		Mapi_Relop = Brutus_Relop;

		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown relational operator from BRUTUS : %X", Brutus_Relop);
		BRUTUS_LOG_BUG(msg);

		return false;
	}
}


bool relop_mapi_to_brutus(const ULONG Mapi_Relop,
			  ::BRUTUS::RELOP_TYPE & Brutus_Relop)
{
	if (Mapi_Relop == RELOP_LT) {
		Brutus_Relop = ::BRUTUS::BRUTUS_RELOP_LT;
		return true;
	}

	if (Mapi_Relop == RELOP_LE) {
		Brutus_Relop = ::BRUTUS::BRUTUS_RELOP_LE;
		return true;
	}

	if (Mapi_Relop == RELOP_GT) {
		Brutus_Relop = ::BRUTUS::BRUTUS_RELOP_GT;
		return true;
	}

	if (Mapi_Relop == RELOP_GE) {
		Brutus_Relop = ::BRUTUS::BRUTUS_RELOP_GE;
		return true;
	}

	if (Mapi_Relop == RELOP_EQ) {
		Brutus_Relop = ::BRUTUS::BRUTUS_RELOP_EQ;
		return true;
	}

	if (Mapi_Relop == RELOP_NE) {
		Brutus_Relop = ::BRUTUS::BRUTUS_RELOP_NE;
		return true;
	}

	if (Mapi_Relop == RELOP_RE) {
		Brutus_Relop = ::BRUTUS::BRUTUS_RELOP_RE;
		return true;
	}

	{
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown relational operator from Mapi : %X", Mapi_Relop);
		BRUTUS_LOG_BUG(msg);

		return false;
	}

}


bool bmr_brutus_to_mapi(const ::BRUTUS::BMR_TYPE Brutus_Bmr,
			ULONG& Mapi_Bmr)
{
	if (Brutus_Bmr == ::BRUTUS::BRUTUS_BMR_EQZ) {
		Mapi_Bmr = BMR_EQZ;
		return true;
	}

	if (Brutus_Bmr == ::BRUTUS::BRUTUS_BMR_NEZ) {
		Mapi_Bmr = BMR_NEZ;
		return true;
	}

	{
		Mapi_Bmr = Brutus_Bmr;

		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown bit mask relational operator from BRUTUS : %X", Brutus_Bmr);
		BRUTUS_LOG_BUG(msg);

		return false;
	}
}

bool bmr_mapi_to_brutus(const ULONG Mapi_Bmr,
			::BRUTUS::BMR_TYPE & Brutus_Bmr)
{
	if (Mapi_Bmr == BMR_EQZ) {
		Brutus_Bmr = ::BRUTUS::BRUTUS_BMR_EQZ;
		return true;
	}

	if (Mapi_Bmr == BMR_NEZ) {
		Brutus_Bmr = ::BRUTUS::BRUTUS_BMR_NEZ;
		return true;
	}

	{
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown bit mask relational operator from MAPI : %X", Mapi_Bmr);
		BRUTUS_LOG_BUG(msg);

		return false;
	}
}


bool sub_object_brutus_to_mapi(const ::BRUTUS::BDEFINE Brutus_Sub,
			       ULONG& Mapi_Sub)
{
	if (Brutus_Sub == ::BRUTUS::BRUTUS_PR_MESSAGE_RECIPIENTS) {
		Mapi_Sub = PR_MESSAGE_RECIPIENTS;
		return true;
	}

	if (Brutus_Sub == ::BRUTUS::BRUTUS_PR_MESSAGE_ATTACHMENTS) {
		Mapi_Sub = PR_MESSAGE_ATTACHMENTS;
		return true;
	}

	{
		Mapi_Sub = Brutus_Sub;

		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown sub object flag from BRUTUS : %X", Brutus_Sub);
		BRUTUS_LOG_BUG(msg);

		return false;
	}
}


bool sub_object_mapi_to_brutus(const ULONG Mapi_Sub,
			       ::BRUTUS::BDEFINE & Brutus_Sub)
{
	if (Mapi_Sub == PR_MESSAGE_RECIPIENTS) {
		Brutus_Sub = ::BRUTUS::BRUTUS_PR_MESSAGE_RECIPIENTS;
		return true;
	}

	if (Mapi_Sub == PR_MESSAGE_ATTACHMENTS) {
		Brutus_Sub = ::BRUTUS::BRUTUS_PR_MESSAGE_ATTACHMENTS;
		return true;
	}

	{
		Brutus_Sub = Mapi_Sub;

		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown sub object flag from MAPI : %X", Mapi_Sub);
		BRUTUS_LOG_BUG(msg);

		return false;
	}
}


bool srestriction_mapi_to_container(::SRestriction *Mapi_Res,
				    LPMAPISESSION MAPISession,
				    ::BRUTUS::SRestrictionContainer_out Brutus_Res,
				    PortableServer::POA_ptr Poa)
{
	Brutus_Res = ::BRUTUS::SRestrictionContainer::_nil();

	if (!Mapi_Res) {
		BRUTUS_LOG_BUG("SRestriction is NIL");
		return false;
	}

	// Create the child poa for this restriction. We need a child of the session
	// poa because of all the lower restriction interfaces that are imbedded in
	// the container and for which the container has memory management
	// responsibility.
	PortableServer::POA_var restrict_poa = create_poa((const char *)0,
							  PortableServer::POAManager::_nil(),
							  Poa);
	if (::CORBA::is_nil(restrict_poa)) {
		BRUTUS_LOG_CRITICAL("Could not create POA");
		return false;
	}

	// create the SRestrictionContainer servant
	BRUTUS_SRestrictionContainer_i *restrict_servant;
	try {
		restrict_servant = new BRUTUS_SRestrictionContainer_i(Mapi_Res,
								      MAPISession,
								      restrict_poa.in());
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		return false;
	}

	// create the SRestrictionContainer object and register it in the restrict poa
	PortableServer::ServantBase_var owner_transfer(restrict_servant);
	PortableServer::ObjectId_var oid = restrict_poa->activate_object(restrict_servant);
	::CORBA::Object_var obj = restrict_poa->id_to_reference(oid);
	Brutus_Res = ::BRUTUS::SRestrictionContainer::_narrow(obj);

	// activate the SRestrictionContainer object's poa so that requests can be served
	PortableServer::POAManager_var poa_manager = restrict_poa->the_POAManager();
	poa_manager->activate();

	return true;
}

// Must only be used for a MAPI restriction which is embedded in
// a brutus restriction container. The Poa parameter *must* be the
// container poa - i.e. this function should only be used internally
// in the restriction interfaces.
bool srestriction_mapi_to_brutus(::SRestriction *Mapi_Res,
				 LPMAPISESSION MAPISession,
				 ::BRUTUS::SRestriction_out Brutus_Res,
				 PortableServer::POA_ptr Poa)
{

	::BRUTUS::SRestriction_var retval;
	try {
		retval = new ::BRUTUS::SRestriction;
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		return false;
	}
	retval->Error(::BRUTUS::BRUTUS_UNKNOWN_ERROR);

	if (!Mapi_Res) {
		BRUTUS_LOG_BUG("SRestriction is NIL");
		retval->Error(::BRUTUS::BRUTUS_MAPI_E_INVALID_PARAMETER);
		Brutus_Res = retval._retn();
		return false;
	}

	if (Mapi_Res->rt == RES_AND) {
		::SAndRestriction *res_and = &Mapi_Res->res.resAnd;
		::BRUTUS::SAndRestriction_var bres;
		bres = create_type_container<BRUTUS_SAndRestriction_i, ::BRUTUS::SAndRestriction, ::SAndRestriction*>
			(res_and, MAPISession, Poa);
		retval->resAnd(bres._retn());
	} else if (Mapi_Res->rt == RES_OR) {
		::SOrRestriction *res_or = &Mapi_Res->res.resOr;
		::BRUTUS::SOrRestriction_var bres;
		bres = create_type_container<BRUTUS_SOrRestriction_i, ::BRUTUS::SOrRestriction, ::SOrRestriction*>
			(res_or, MAPISession, Poa);
		retval->resOr(bres._retn());
	} else if (Mapi_Res->rt == RES_NOT) {
		::SNotRestriction *res_not = &Mapi_Res->res.resNot;
		::BRUTUS::SNotRestriction_var bres;
		bres = create_type_container<BRUTUS_SNotRestriction_i, ::BRUTUS::SNotRestriction, ::SNotRestriction*>
			(res_not, MAPISession, Poa);
		retval->resNot(bres._retn());
	} else if (Mapi_Res->rt == RES_CONTENT) {
		::SContentRestriction *res_content = &Mapi_Res->res.resContent;
		::BRUTUS::SContentRestriction_var bres;
		bres = create_type_container<BRUTUS_SContentRestriction_i, ::BRUTUS::SContentRestriction, ::SContentRestriction*>
			(res_content, MAPISession, Poa);
		retval->resContent(bres._retn());
	} else if (Mapi_Res->rt == RES_PROPERTY) {
		::SPropertyRestriction *res_property = &Mapi_Res->res.resProperty;
		::BRUTUS::SPropertyRestriction_var bres;
		bres = create_type_container<BRUTUS_SPropertyRestriction_i, ::BRUTUS::SPropertyRestriction, ::SPropertyRestriction*>
			(res_property, MAPISession, Poa);
		retval->resProperty(bres._retn());
	} else if (Mapi_Res->rt == RES_COMPAREPROPS) {
		::SComparePropsRestriction *res_compareProps = &Mapi_Res->res.resCompareProps;
		::BRUTUS::SComparePropsRestriction_var bres;
		bres = create_type_container<BRUTUS_SComparePropsRestriction_i, ::BRUTUS::SComparePropsRestriction, ::SComparePropsRestriction*>
			(res_compareProps, MAPISession, Poa);
		retval->resCompareProps(bres._retn());
	} else if (Mapi_Res->rt == RES_BITMASK) {
		::SBitMaskRestriction *res_bit_mask = &Mapi_Res->res.resBitMask;
		::BRUTUS::SBitMaskRestriction_var bres;
		bres = create_type_container<BRUTUS_SBitMaskRestriction_i, ::BRUTUS::SBitMaskRestriction, ::SBitMaskRestriction*>
			(res_bit_mask, MAPISession, Poa);
		retval->resBitMask(bres._retn());
	} else if (Mapi_Res->rt == RES_SIZE) {
		::SSizeRestriction *res_size = &Mapi_Res->res.resSize;
		::BRUTUS::SSizeRestriction_var bres;
		bres = create_type_container<BRUTUS_SSizeRestriction_i, ::BRUTUS::SSizeRestriction, ::SSizeRestriction*>
			(res_size, MAPISession, Poa);
		retval->resSize(bres._retn());
	} else if (Mapi_Res->rt == RES_EXIST) {
		::SExistRestriction *res_exist = &Mapi_Res->res.resExist;
		::BRUTUS::SExistRestriction_var bres;
		bres = create_type_container<BRUTUS_SExistRestriction_i, ::BRUTUS::SExistRestriction, ::SExistRestriction*>
			(res_exist, MAPISession, Poa);
		retval->resExist(bres._retn());
	} else if (Mapi_Res->rt == RES_SUBRESTRICTION) {
		::SSubRestriction *res_sub = &Mapi_Res->res.resSub;
		::BRUTUS::SSubRestriction_var bres;
		bres = create_type_container<BRUTUS_SSubRestriction_i, ::BRUTUS::SSubRestriction, ::SSubRestriction*>
			(res_sub, MAPISession, Poa);
		retval->resSub(bres._retn());
	} else if (Mapi_Res->rt == RES_COMMENT) {
		::BRUTUS::SCommentRestriction_var bres;
		::SCommentRestriction *res_comment = &Mapi_Res->res.resComment;
		bres = create_type_container<BRUTUS_SCommentRestriction_i, ::BRUTUS::SCommentRestriction, ::SCommentRestriction*>
			(res_comment, MAPISession, Poa);
		retval->resComment(bres._retn());
	} else
		retval->Error(::BRUTUS::BRUTUS_MAPI_E_TYPE_NO_SUPPORT);

	Brutus_Res = retval._retn();

	return true;
}

bool ANDrestriction_brutus_to_mapi_internal_alloc(const ::BRUTUS::SAndRestriction_ptr Brutus_Res,
						  void *Parent,
						  ::SAndRestriction* const Mapi_Res)
{
	Mapi_Res->cRes = (ULONG)Brutus_Res->lpRes()->length();
	if (Parent) {
		if (S_OK != MAPIAllocateMore(Mapi_Res->cRes * sizeof(::SRestriction),
					     Parent,
					     (void**)&Mapi_Res->lpRes)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(Mapi_Res->cRes * sizeof(::SRestriction),
					       (void**)&Mapi_Res->lpRes)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = (void*)Mapi_Res->lpRes;
	}

	bool retval = true;
	::BRUTUS::seq_SRestriction_var seq_res = Brutus_Res->lpRes();
	for (ULONG n = 0; n < Mapi_Res->cRes; n++) {
		retval = retval && srestriction_brutus_to_mapi_internal_alloc(seq_res[(::CORBA::ULong)n],
									      Parent,
									      &(Mapi_Res->lpRes[n]));
	}

	return retval;
}

bool ORrestriction_brutus_to_mapi_internal_alloc(::BRUTUS::SOrRestriction_ptr Brutus_Res,
						 void *Parent,
						 ::SOrRestriction* const Mapi_Res)
{
	Mapi_Res->cRes = (ULONG)Brutus_Res->lpRes()->length();
	if (Parent) {
		if (S_OK != MAPIAllocateMore(Mapi_Res->cRes * sizeof(::SRestriction),
					     Parent,
					     (void**)&Mapi_Res->lpRes)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(Mapi_Res->cRes * sizeof(::SRestriction),
					       (void**)&Mapi_Res->lpRes)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = (void*)Mapi_Res->lpRes;
	}

	bool retval = true;
	::BRUTUS::seq_SRestriction_var seq_res = Brutus_Res->lpRes();
	for (ULONG n = 0; n < Mapi_Res->cRes; n++) {
		retval = retval && srestriction_brutus_to_mapi_internal_alloc(seq_res[(::CORBA::ULong)n],
									      Parent,
									      &(Mapi_Res->lpRes[n]));
	}

	return retval;
}

bool NOTrestriction_brutus_to_mapi_internal_alloc(::BRUTUS::SNotRestriction_ptr Brutus_Res,
						  void *Parent,
						  ::SNotRestriction* const Mapi_Res)
{
	Mapi_Res->ulReserved = (ULONG)Brutus_Res->ulReserved();
	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(::SRestriction),
					     Parent,
					     (void**)&Mapi_Res->lpRes)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::SRestriction),
					       (void**)&Mapi_Res->lpRes)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = (void*)Mapi_Res->lpRes;
	}

	::BRUTUS::SRestriction_var res = Brutus_Res->lpRes();
	return srestriction_brutus_to_mapi_internal_alloc(res,
							  Parent,
							  Mapi_Res->lpRes);
}

bool CONTENTrestriction_brutus_to_mapi_internal_alloc(::BRUTUS::SContentRestriction_ptr Brutus_Res,
						      void *Parent,
						      ::SContentRestriction* const Mapi_Res)
{
	bool retval = true;
	retval = retval && fuzzyLevel_brutus_to_mapi(Brutus_Res->ulFuzzyLevel(),
						     Mapi_Res->ulFuzzyLevel);

	retval = retval && proptag_brutus_to_mapi(Brutus_Res->ulPropTag(),
						  Mapi_Res->ulPropTag);

	::BRUTUS::SPropValue_var pv = Brutus_Res->lpProp();
	retval = retval && spropvalue_brutus_to_mapi(&pv.in(),
						     Parent,
						     Mapi_Res->lpProp);

	return retval;
}

bool PROPERTYrestriction_brutus_to_mapi_internal_alloc(::BRUTUS::SPropertyRestriction_ptr Brutus_Res,
						       void *Parent,
						       ::SPropertyRestriction* const Mapi_Res)
{
	bool retval = true;
	retval = retval && relop_brutus_to_mapi(Brutus_Res->relop(),
						Mapi_Res->relop);

	retval = retval && proptag_brutus_to_mapi(Brutus_Res->ulPropTag(),
						  Mapi_Res->ulPropTag);

	::BRUTUS::SPropValue_var pv = Brutus_Res->lpProp();
	retval = retval && spropvalue_brutus_to_mapi(&pv.in(),
						     Parent,
						     Mapi_Res->lpProp);

	return retval;
}

bool COMPAREPROPSrestriction_brutus_to_mapi_internal_alloc(::BRUTUS::SComparePropsRestriction_ptr Brutus_Res,
							   void *Parent,
							   ::SComparePropsRestriction* const Mapi_Res)
{
	bool retval = true;
	retval = retval && relop_brutus_to_mapi(Brutus_Res->relop(),
						Mapi_Res->relop);

	retval = retval && proptag_brutus_to_mapi(Brutus_Res->ulPropTag1(),
						  Mapi_Res->ulPropTag1);

	retval = retval && proptag_brutus_to_mapi(Brutus_Res->ulPropTag2(),
						  Mapi_Res->ulPropTag2);

	return retval;
}

bool BITMASKrestriction_brutus_to_mapi_internal_alloc(::BRUTUS::SBitMaskRestriction_ptr Brutus_Res,
						      void *Parent,
						      ::SBitMaskRestriction* const Mapi_Res)
{
	bool retval = true;
	retval = retval && bmr_brutus_to_mapi(Brutus_Res->relBMR(),
					      Mapi_Res->relBMR);

	retval = retval && proptag_brutus_to_mapi(Brutus_Res->ulPropTag(),
						  Mapi_Res->ulPropTag);

	Mapi_Res->ulMask = (ULONG)Brutus_Res->ulMask();

	return retval;
}

bool SIZErestriction_brutus_to_mapi_internal_alloc(::BRUTUS::SSizeRestriction_ptr Brutus_Res,
						   void *Parent,
						   ::SSizeRestriction* const Mapi_Res)
{
	bool retval = true;
	retval = retval && relop_brutus_to_mapi(Brutus_Res->relop(),
						Mapi_Res->relop);

	retval = retval && proptag_brutus_to_mapi(Brutus_Res->ulPropTag(),
						  Mapi_Res->ulPropTag);

	Mapi_Res->cb = (ULONG)Brutus_Res->cb();

	return retval;
}

bool EXISTrestriction_brutus_to_mapi_internal_alloc(::BRUTUS::SExistRestriction_ptr Brutus_Res,
						    void *Parent,
						    ::SExistRestriction* const Mapi_Res)
{
	bool retval = true;
	Mapi_Res->ulReserved1 = (ULONG)Brutus_Res->ulReserved1();

	retval = retval && proptag_brutus_to_mapi(Brutus_Res->ulPropTag(),
						  Mapi_Res->ulPropTag);

	Mapi_Res->ulReserved2 = (ULONG)Brutus_Res->ulReserved2();

	return retval;
}

bool SUBrestriction_brutus_to_mapi_internal_alloc(::BRUTUS::SSubRestriction_ptr Brutus_Res,
						  void *Parent,
						  ::SSubRestriction* const Mapi_Res)
{
	bool retval = true;
	retval = retval && sub_object_brutus_to_mapi(Brutus_Res->ulSubObject(),
						     Mapi_Res->ulSubObject);

	::BRUTUS::SRestriction_var res = Brutus_Res->lpRes();
	retval = retval && srestriction_brutus_to_mapi(res.in(),
						       Parent,
						       Mapi_Res->lpRes);

	return retval;
}

bool COMMENTrestriction_brutus_to_mapi_internal_alloc(::BRUTUS::SCommentRestriction_ptr Brutus_Res,
						      void *Parent,
						      ::SCommentRestriction* const Mapi_Res)
{
	bool retval = true;

	::BRUTUS::SRestriction_var res = Brutus_Res->lpRes();
	retval = retval && srestriction_brutus_to_mapi(res.in(),
						       Parent,
						       Mapi_Res->lpRes);

	ULONG cValues = 0;
	::BRUTUS::seq_SPropValue_var pv = Brutus_Res->lpProp();
	retval = retval && spropvalue_array_brutus_to_mapi(&pv.in(),
							   Parent,
							   cValues,
							   Mapi_Res->lpProp);
	Mapi_Res->cValues = cValues;

	return retval;
}

bool srestriction_brutus_to_mapi_internal_alloc(const ::BRUTUS::SRestriction& Brutus_Res,
						void *Parent,
						::SRestriction* const Mapi_Res)
{
	if (Brutus_Res._d() == ::BRUTUS::BRUTUS_RES_AND) {
		Mapi_Res->rt = RES_AND;
		::BRUTUS::SAndRestriction_ptr bres = Brutus_Res.resAnd();
		ANDrestriction_brutus_to_mapi_internal_alloc(bres, Parent, &Mapi_Res->res.resAnd);
	} else if (Brutus_Res._d() == ::BRUTUS::BRUTUS_RES_OR) {
		Mapi_Res->rt = RES_OR;
		::BRUTUS::SOrRestriction_ptr bres = Brutus_Res.resOr();
		ORrestriction_brutus_to_mapi_internal_alloc(bres, Parent, &Mapi_Res->res.resOr);
	} else if (Brutus_Res._d() == ::BRUTUS::BRUTUS_RES_NOT) {
		Mapi_Res->rt = RES_NOT;
		::BRUTUS::SNotRestriction_ptr bres = Brutus_Res.resNot();
		NOTrestriction_brutus_to_mapi_internal_alloc(bres, Parent, &Mapi_Res->res.resNot);
	} else if (Brutus_Res._d() == ::BRUTUS::BRUTUS_RES_CONTENT) {
		Mapi_Res->rt = RES_CONTENT;
		::BRUTUS::SContentRestriction_ptr bres = Brutus_Res.resContent();
		CONTENTrestriction_brutus_to_mapi_internal_alloc(bres, Parent, &Mapi_Res->res.resContent);
	} else if (Brutus_Res._d() == ::BRUTUS::BRUTUS_RES_PROPERTY) {
		Mapi_Res->rt = RES_PROPERTY;
		::BRUTUS::SPropertyRestriction_ptr bres = Brutus_Res.resProperty();
		PROPERTYrestriction_brutus_to_mapi_internal_alloc(bres, Parent, &Mapi_Res->res.resProperty);
	} else if (Brutus_Res._d() == ::BRUTUS::BRUTUS_RES_COMPAREPROPS) {
		Mapi_Res->rt = RES_COMPAREPROPS;
		::BRUTUS::SComparePropsRestriction_ptr bres = Brutus_Res.resCompareProps();
		COMPAREPROPSrestriction_brutus_to_mapi_internal_alloc(bres, Parent, &Mapi_Res->res.resCompareProps);
	} else if (Brutus_Res._d() == ::BRUTUS::BRUTUS_RES_BITMASK) {
		Mapi_Res->rt = RES_BITMASK;
		::BRUTUS::SBitMaskRestriction_ptr bres = Brutus_Res.resBitMask();
		BITMASKrestriction_brutus_to_mapi_internal_alloc(bres, Parent, &Mapi_Res->res.resBitMask);
	} else if (Brutus_Res._d() == ::BRUTUS::BRUTUS_RES_SIZE) {
		Mapi_Res->rt = RES_SIZE;
		::BRUTUS::SSizeRestriction_ptr bres = Brutus_Res.resSize();
		SIZErestriction_brutus_to_mapi_internal_alloc(bres, Parent, &Mapi_Res->res.resSize);
	} else if (Brutus_Res._d() == ::BRUTUS::BRUTUS_RES_EXIST) {
		Mapi_Res->rt = RES_EXIST;
		::BRUTUS::SExistRestriction_ptr bres = Brutus_Res.resExist();
		EXISTrestriction_brutus_to_mapi_internal_alloc(bres, Parent, &Mapi_Res->res.resExist);
	} else if (Brutus_Res._d() == ::BRUTUS::BRUTUS_RES_SUBRESTRICTION) {
		Mapi_Res->rt = RES_SUBRESTRICTION;
		::BRUTUS::SSubRestriction_ptr bres = Brutus_Res.resSub();
		SUBrestriction_brutus_to_mapi_internal_alloc(bres, Parent, &Mapi_Res->res.resSub);
	} else if (Brutus_Res._d() == ::BRUTUS::BRUTUS_RES_COMMENT) {
		Mapi_Res->rt = RES_COMMENT;
		::BRUTUS::SCommentRestriction_ptr bres = Brutus_Res.resComment();
		COMMENTrestriction_brutus_to_mapi_internal_alloc(bres, Parent, &Mapi_Res->res.resComment);
	} else
		return false;

	return true;
}


bool srestriction_brutus_to_mapi(const ::BRUTUS::SRestriction& Brutus_Res,
				 void *Parent,
				 ::SRestriction*& Mapi_Res)
{
	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(::SRestriction),
					     Parent,
					     (void**)&Mapi_Res)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::SRestriction),
					       (void**)&Mapi_Res)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = Mapi_Res;
	}

	return srestriction_brutus_to_mapi_internal_alloc(Brutus_Res, Parent, Mapi_Res);
}


bool nameid_mapi_to_brutus(::MAPINAMEID *Mapi_Name,
			   ::BRUTUS::MAPINAMEID& Brutus_Name,
			   bool DeAlloc)
{
	if (!Mapi_Name)
		return false;

	switch (Mapi_Name->ulKind) {
	case MNID_ID :
		Brutus_Name.Kind.lID(Mapi_Name->Kind.lID);
		break;
	case MNID_STRING :
		Brutus_Name.Kind.lpwstrName(unicode_to_utf8((LPCWSTR)Mapi_Name->Kind.lpwstrName));
		break;
	default :
		if (DeAlloc)
			MAPIFreeBuffer(Mapi_Name);
		return false;
	}

	bool retval = guid_mapi_to_brutus(Mapi_Name->lpguid, Brutus_Name.lpguid);

	if (DeAlloc)
		MAPIFreeBuffer(Mapi_Name);

	return retval;
}


bool nameid_brutus_to_mapi(const ::BRUTUS::MAPINAMEID *Brutus_Name,
			   void *Parent,
			   ::MAPINAMEID*& Mapi_Name)
{
	if (!Brutus_Name)
		return false;

	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(::MAPINAMEID),
					     Parent,
					     (void**)&Mapi_Name)) {
			BRUTUS_LOG_ERR("No memory");
			throw ::CORBA::NO_MEMORY();
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::MAPINAMEID),
					       (void**)&Mapi_Name)) {
			BRUTUS_LOG_ERR("No memory");
			throw ::CORBA::NO_MEMORY();
		}
		Parent = Mapi_Name;
	}

	if (::BRUTUS::BRUTUS_MNID_ID == Brutus_Name->Kind._d()) {
		Mapi_Name->ulKind = MNID_ID;
		Mapi_Name->Kind.lID = Brutus_Name->Kind.lID();
	} else if (::BRUTUS::BRUTUS_MNID_STRING == Brutus_Name->Kind._d()) {
		Mapi_Name->ulKind = MNID_STRING;
		Mapi_Name->Kind.lpwstrName = utf8_to_unicode(Parent, (const char*)Brutus_Name->Kind.lpwstrName());
	} else
		return false;

	::BRUTUS::GUID_var b_guid = Brutus_Name->lpguid;
	return guid_brutus_to_mapi(b_guid, Parent, Mapi_Name->lpguid);
}


bool nameid_brutus_to_mapi_internal_alloc(const ::BRUTUS::MAPINAMEID *Brutus_Name,
					  void *Parent,
					  ::MAPINAMEID* const Mapi_Name)
{
	if (!Brutus_Name)
		return false;

	if (::BRUTUS::BRUTUS_MNID_ID == Brutus_Name->Kind._d()) {
		Mapi_Name->ulKind = MNID_ID;
		Mapi_Name->Kind.lID = Brutus_Name->Kind.lID();
	} else if (::BRUTUS::BRUTUS_MNID_STRING == Brutus_Name->Kind._d()) {
		Mapi_Name->ulKind = MNID_STRING;
		Mapi_Name->Kind.lpwstrName = utf8_to_unicode(Parent, (const char*)Brutus_Name->Kind.lpwstrName());
	} else
		return false;

	::BRUTUS::GUID_var b_guid = Brutus_Name->lpguid;
	return guid_brutus_to_mapi(b_guid, Parent, Mapi_Name->lpguid);
}


bool nameid_array_mapi_to_brutus(const ULONG cValues,
				 ::MAPINAMEID **Mapi_Names,
				 ::BRUTUS::seq_MAPINAMEID& Brutus_Names,
				 bool DeAlloc)
{
	Brutus_Names.length(cValues);
	if (!cValues)
		return true;

	if (!Mapi_Names)
		return false;

	bool retval = true;
	for (ULONG i = 0; i < cValues; i++)
		retval = retval && nameid_mapi_to_brutus(Mapi_Names[i],
							 Brutus_Names[i]);

	if (DeAlloc)
		MAPIFreeBuffer(Mapi_Names);

	return retval;
}

bool nameid_array_brutus_to_mapi(const ::BRUTUS::seq_MAPINAMEID *Brutus_Names,
				 void *Parent,
				 ::LPMAPINAMEID*& Mapi_Names)
{
	if (!Brutus_Names)
		return false;

	ULONG cValues = Brutus_Names->length();
	if (!cValues) {
		Mapi_Names = NULL;
		return true;
	}

	if (Parent) {
		if (S_OK != MAPIAllocateMore(cValues * sizeof(::MAPINAMEID*),
					     Parent,
					     (void**)&Mapi_Names)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(cValues * sizeof(::MAPINAMEID*),
					       (void**)&Mapi_Names)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = Mapi_Names;
	}

	ULONG n = 0;
	for (n = 0; n < cValues; n++) {
		if (S_OK != MAPIAllocateMore(sizeof(::MAPINAMEID),
					     Parent,
					     (void**)&(Mapi_Names[n]))) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	}

	bool retval = true;
	for (n = 0; n < cValues; n++)
		retval = retval && nameid_brutus_to_mapi_internal_alloc(&(*Brutus_Names)[n],
									Parent,
									Mapi_Names[n]);

	return retval;
}

bool adr_brutus_to_mapi(const ::BRUTUS::ADRENTRY *Brutus_Adr,
			::ADRENTRY*& Mapi_Adr)
{
	if (!Brutus_Adr)
		return false;

	if (S_OK != MAPIAllocateBuffer(sizeof(::ADRENTRY), (void**)&Mapi_Adr)) {
		BRUTUS_LOG_ERR("No memory");
		return false;
	}
	Mapi_Adr->ulReserved1 = 0;

	return spropvalue_array_brutus_to_mapi(&Brutus_Adr->rgPropVals,
					       0,
					       Mapi_Adr->cValues,
					       Mapi_Adr->rgPropVals);
}


bool adr_brutus_to_mapi_internal_alloc(const ::BRUTUS::ADRENTRY *Brutus_Adr,
				       ::ADRENTRY * const Mapi_Adr)
{
	if (!Brutus_Adr)
		return false;

	Mapi_Adr->ulReserved1 = 0;

	return spropvalue_array_brutus_to_mapi(&Brutus_Adr->rgPropVals,
					       0,
					       Mapi_Adr->cValues,
					       Mapi_Adr->rgPropVals);
}


bool adr_mapi_to_brutus(::ADRENTRY *Mapi_Adr,
			::BRUTUS::ADRENTRY& Brutus_Adr,
			LPMAPISESSION Mapi_Session,
			bool DeAlloc,
			PortableServer::POA_ptr Poa)
{
	if (!Mapi_Adr)
		return false;

	bool retval = spropvalue_array_mapi_to_brutus(Mapi_Adr->cValues,
						      Mapi_Adr->rgPropVals,
						      Brutus_Adr.rgPropVals,
						      Mapi_Session,
						      DeAlloc,
						      Poa);

	if (DeAlloc)
		MAPIFreeBuffer(Mapi_Adr);

	return retval;
}


bool adr_list_brutus_to_mapi(const ::BRUTUS::ADRLIST *Brutus_AdrList,
			     ::ADRLIST*& Mapi_AdrList)
{
	Mapi_AdrList = NULL;
	if (!Brutus_AdrList)
		return false;

	unsigned long list_size = CbNewADRLIST(Brutus_AdrList->length());
	if (S_OK != MAPIAllocateBuffer(list_size, (void**)&Mapi_AdrList)) {
		BRUTUS_LOG_ERR("No memory");
		return false;
	}
	Mapi_AdrList->cEntries = Brutus_AdrList->length();

	::ADRENTRY *adr;
	bool retval = true;
	for (ULONG n = 0; n < Mapi_AdrList->cEntries; n++) {
		adr = &Mapi_AdrList->aEntries[n];
		retval = retval && adr_brutus_to_mapi_internal_alloc(&(*Brutus_AdrList)[n],
								     adr);
	}

	return retval;
}


bool adr_list_brutus_to_mapi_internal_alloc(const ::BRUTUS::ADRLIST *Brutus_AdrList,
					    ::ADRLIST* const Mapi_AdrList)
{
	if (!Brutus_AdrList)
		return false;

	Mapi_AdrList->cEntries = Brutus_AdrList->length();

	::ADRENTRY *adr;
	bool retval = true;
	for (ULONG n = 0; n < Mapi_AdrList->cEntries; n++) {
		adr = &Mapi_AdrList->aEntries[n];
		retval = retval && adr_brutus_to_mapi_internal_alloc(&(*Brutus_AdrList)[n],
								     adr);
	}

	return retval;
}

bool adr_list_mapi_to_brutus(::ADRLIST *Mapi_AdrList,
			     ::BRUTUS::ADRLIST& Brutus_AdrList,
			     LPMAPISESSION Mapi_Session,
			     bool DeAlloc,
			     PortableServer::POA_ptr Poa)
{
	if (!Mapi_AdrList)
		return false;

	Brutus_AdrList.length(Mapi_AdrList->cEntries);

	bool retval = true;
	for (ULONG n = 0; n < Mapi_AdrList->cEntries; n++)
		retval = retval && spropvalue_array_mapi_to_brutus(Mapi_AdrList->aEntries[n].cValues,
								   Mapi_AdrList->aEntries[n].rgPropVals,
								   Brutus_AdrList[n].rgPropVals,
								   Mapi_Session,
								   false,
								   Poa);

	if (DeAlloc)
		FreePadrlist(Mapi_AdrList);

	return retval;
}

bool brutus_entry_id_is_nil(const ::BRUTUS::ENTRYID* const b_eid)
{
	unsigned long n;
	bool nil = true;

	for (n = 0; n < 4; n++) {
		nil = nil && !!!b_eid->abFlags[n];
		if (!nil)
			break;
	}
	if (nil) {
		for (n = 0; n < b_eid->ab.length(); n++) {
			nil = nil && !!!b_eid->ab[n];
			if (!nil)
				break;
		}
		if (nil)
			return true;
	}

	return false;
}

bool seq_ulong_brutus_to_mapi(const ::BRUTUS::seq_ulong & Brutus_seq_ulong,
			      void *Parent,
			      ULONG *& seq_mapi_ulong)
{
	unsigned long len = Brutus_seq_ulong.length();
	if (!len) {
		seq_mapi_ulong = 0;
		return true;
	}

	if (Parent) {
		if (S_OK != MAPIAllocateMore(len * sizeof(ULONG),
					     Parent,
					     (void**)&seq_mapi_ulong)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(len * sizeof(ULONG),
					       (void**)&seq_mapi_ulong)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	}

	for (unsigned int n=0; n<len; n++)
		seq_mapi_ulong[n] = Brutus_seq_ulong[n];

	return true;
}


bool seq_ulong_mapi_to_brutus(const ULONG len,
			      ULONG *& seq_mapi_ulong,
			      ::BRUTUS::seq_ulong_out Brutus_seq_ulong,
			      bool DeAlloc)
{
	::BRUTUS::seq_ulong_var ulongs;
	try {
		ulongs = new ::BRUTUS::seq_ulong;
		ulongs->length(len);
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		return false;
	}

	for (unsigned long n=0; n<len; n++)
		ulongs[(::CORBA::ULong)n] = seq_mapi_ulong[n];

	Brutus_seq_ulong = ulongs._retn();

	if (DeAlloc)
		MAPIFreeBuffer(seq_mapi_ulong);

	return true;
}

bool seq_octet_brutus_to_mapi(const ::BRUTUS::seq_octet & Brutus_seq_octet,
			      void *Parent,
			      void *& mapi_void)
{
	unsigned long len = Brutus_seq_octet.length();
	if (!len) {
		mapi_void = NULL;
		return true;
	}

	if (Parent) {
		if (S_OK != MAPIAllocateMore(len,
					     Parent,
					     (void**)&mapi_void)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(len,
					       (void**)&mapi_void)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	}

	for (unsigned long n=0; n<len; n++)
		((::CORBA::Octet*)mapi_void)[n] = Brutus_seq_octet[n];

	return true;
}

bool seq_octet_mapi_to_brutus(const ULONG len,
			      ::BYTE *Mapi_seq_octet,
			      ::BRUTUS::seq_octet_out Brutus_seq_octet,
			      bool DeAlloc)
{
	::BRUTUS::seq_octet_var octets;
	try {
		octets = new ::BRUTUS::seq_octet;
		octets->length(len);
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		return false;
	}

	for (unsigned long n=0; n<len; n++)
		octets[(::CORBA::ULong)n] = Mapi_seq_octet[n];
	Brutus_seq_octet = octets._retn();

	if (DeAlloc)
		MAPIFreeBuffer(Mapi_seq_octet);

	return true;
}

bool sTnefProblem_mapi_to_brutus(::STnefProblem *Mapi_Problem,
				 ::BRUTUS::STnefProblem_out Brutus_Problem,
				 bool DeAlloc)
{
	::BRUTUS::STnefProblem_var tprob;
	try {
		tprob = new ::BRUTUS::STnefProblem;
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		return false;
	}

	tprob->ulComponent = Mapi_Problem->ulComponent;
	switch (Mapi_Problem->ulAttribute) {
	case attMAPIProps :
		tprob->ulAttribute = ::BRUTUS::BRUTUS_attMAPIProps;
		break;
	case attAttachment :
		tprob->ulAttribute = ::BRUTUS::BRUTUS_attAttachment;
		break;
	default :
	{
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown ulAttribute from MAPI : %X", Mapi_Problem->ulAttribute);
		BRUTUS_LOG_BUG(msg);

		tprob->ulAttribute = Mapi_Problem->ulAttribute;
	}
	}
	proptag_mapi_to_brutus(Mapi_Problem->ulPropTag, tprob->ulPropTag);
	hresult_to_bresult(Mapi_Problem->scode, tprob->scode);

	Brutus_Problem = tprob._retn();
	if (DeAlloc)
		MAPIFreeBuffer(Mapi_Problem);

	return true;
}


bool sTnefProblem_array_mapi_to_brutus(::STnefProblemArray *Mapi_Problems,
				       ::BRUTUS::STnefProblemArray_out Brutus_Problems,
				       bool DeAlloc)
{
	::BRUTUS::STnefProblemArray_var tprobs;
	try {
		tprobs = new ::BRUTUS::STnefProblemArray;
		tprobs->length(Mapi_Problems->cProblem);
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		return false;
	}

	bool retv = true;
	for (unsigned long n=0; n<Mapi_Problems->cProblem; n++)
		retv = retv && sTnefProblem_mapi_to_brutus(&Mapi_Problems->aProblem[n], tprobs[n]);

	Brutus_Problems = tprobs._retn();
	if (DeAlloc)
		MAPIFreeBuffer(Mapi_Problems);

	return retv;
}

bool statstg_mapi_to_brutus(::STATSTG *Mapi_Stats,
			    ::STATFLAG Flag,
			    ::BRUTUS::STATSTG_out Brutus_StatStg)
{
	::BRUTUS::STATSTG_var retv;
	try {
		retv = new ::BRUTUS::STATSTG;
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		return false;
	}

	if (Flag == STATFLAG_DEFAULT) {
		if (Mapi_Stats->pwcsName)
			retv->pwcsName = unicode_to_utf8((LPCWSTR)Mapi_Stats->pwcsName);
		else
			retv->pwcsName = ::CORBA::string_dup("");
	} else
		retv->pwcsName = ::CORBA::string_dup("");

	switch (Mapi_Stats->type) {
	case STGTY_STORAGE :
		retv->type = ::BRUTUS::BRUTUS_STGTY_STORAGE;
		break;
	case STGTY_STREAM :
		retv->type = ::BRUTUS::BRUTUS_STGTY_STREAM;
		break;
	case STGTY_LOCKBYTES :
		retv->type = ::BRUTUS::BRUTUS_STGTY_LOCKBYTES;
		break;
	case STGTY_PROPERTY :
		retv->type = ::BRUTUS::BRUTUS_STGTY_PROPERTY;
	default:
	{
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown STATSTG.type from MAPI : %X", Mapi_Stats->type);
		BRUTUS_LOG_BUG(msg);

		retv->type = (::BRUTUS::BDEFINE)Mapi_Stats->type;
	}
	}

	retv->cbSize = Mapi_Stats->cbSize.QuadPart;
	filetime_mapi_to_brutus(&Mapi_Stats->mtime, retv->mtime);
	filetime_mapi_to_brutus(&Mapi_Stats->ctime, retv->ctime);
	filetime_mapi_to_brutus(&Mapi_Stats->atime, retv->atime);
	retv->grfMode = (::BRUTUS::BDEFINE)Mapi_Stats->grfMode;

	retv->grfLocksSupported = 0;
	if (Mapi_Stats->grfLocksSupported & LOCK_WRITE) {
		retv->grfLocksSupported |= ::BRUTUS::BRUTUS_LOCK_WRITE;
	}
	if (Mapi_Stats->grfLocksSupported & LOCK_EXCLUSIVE) {
		retv->grfLocksSupported |= ::BRUTUS::BRUTUS_LOCK_EXCLUSIVE;
	}
	if (Mapi_Stats->grfLocksSupported & LOCK_ONLYONCE) {
		retv->grfLocksSupported |= ::BRUTUS::BRUTUS_LOCK_ONLYONCE;
	}

	guid_mapi_to_brutus(&Mapi_Stats->clsid, retv->clsid);
	retv->grfStateBits = (::BRUTUS::BDEFINE)Mapi_Stats->grfStateBits;
	retv->reserved = (::BRUTUS::BDEFINE)Mapi_Stats->reserved;

	Brutus_StatStg = retv._retn();

	return true;
}

bool statstg_brutus_to_mapi(const ::BRUTUS::STATSTG & Brutus_Stats,
			    ::BRUTUS::STATFLAG Flag,
			    ::STATSTG *Mapi_StatStg)
{
	if (Flag == ::BRUTUS::BRUTUS_STATFLAG_DEFAULT) {
		wchar_t *wstr = utf8_to_unicode(NULL, (const char*)Brutus_Stats.pwcsName);
		unsigned long len = 1 + wcslen(wstr);
		Mapi_StatStg->pwcsName = (wchar_t*)CoTaskMemAlloc(sizeof(wchar_t) * len);
		if (!(Mapi_StatStg->pwcsName)) {
			MAPIFreeBuffer(wstr);
			return false;
		}
		wcscpy(Mapi_StatStg->pwcsName, wstr);
		MAPIFreeBuffer(wstr);
	} else Mapi_StatStg->pwcsName = 0;

	switch (Brutus_Stats.type) {
	case ::BRUTUS::BRUTUS_STGTY_STORAGE :
		Mapi_StatStg->type = STGTY_STORAGE;
		break;
	case ::BRUTUS::BRUTUS_STGTY_STREAM :
		Mapi_StatStg->type = STGTY_STREAM;
		break;
	case ::BRUTUS::BRUTUS_STGTY_LOCKBYTES :
		Mapi_StatStg->type = STGTY_LOCKBYTES;
		break;
	case ::BRUTUS::BRUTUS_STGTY_PROPERTY :
		Mapi_StatStg->type = STGTY_PROPERTY;
	default:
	{
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown STATSTG.type from Brutus : %X", Brutus_Stats.type);
		BRUTUS_LOG_BUG(msg);

		Mapi_StatStg->type = (DWORD)Brutus_Stats.type;
	}
	}
	Mapi_StatStg->cbSize.QuadPart = Brutus_Stats.cbSize;
	filetime_brutus_to_mapi_no_alloc(&Brutus_Stats.mtime, Mapi_StatStg->mtime);
	filetime_brutus_to_mapi_no_alloc(&Brutus_Stats.ctime, Mapi_StatStg->ctime);
	filetime_brutus_to_mapi_no_alloc(&Brutus_Stats.atime, Mapi_StatStg->atime);
	Mapi_StatStg->grfMode = (DWORD)Brutus_Stats.grfMode;

	Mapi_StatStg->grfLocksSupported = 0;
	if (Brutus_Stats.grfLocksSupported & ::BRUTUS::BRUTUS_LOCK_WRITE) {
		Mapi_StatStg->grfLocksSupported |= LOCK_WRITE;
	}
	if (Brutus_Stats.grfLocksSupported & ::BRUTUS::BRUTUS_LOCK_EXCLUSIVE) {
		Mapi_StatStg->grfLocksSupported |= LOCK_EXCLUSIVE;
	}
	if (Brutus_Stats.grfLocksSupported & ::BRUTUS::BRUTUS_LOCK_ONLYONCE) {
		Mapi_StatStg->grfLocksSupported |= LOCK_ONLYONCE;
	}

	::BRUTUS::GUID_var b_guid = Brutus_Stats.clsid;
	guid_brutus_to_mapi_no_alloc(b_guid, &Mapi_StatStg->clsid);
	Mapi_StatStg->grfStateBits = (DWORD)Brutus_Stats.grfStateBits;
	Mapi_StatStg->reserved = (DWORD)Brutus_Stats.reserved;

	return true;
}

bool readstate_mapi_to_brutus(::READSTATE *Mapi_ReadState,
			      ::BRUTUS::READSTATE & Brutus_ReadState,
			      bool DeAlloc)
{
	Brutus_ReadState.ulFlags = 0;

	if (!Mapi_ReadState) {
		Brutus_ReadState.pbSourceKey.length(0);
		return true;
	}

	if (Mapi_ReadState->ulFlags & SYNC_READ)
		Brutus_ReadState.ulFlags |= ::BRUTUS::BRUTUS_SYNC_READ;

	Brutus_ReadState.pbSourceKey.length(Mapi_ReadState->cbSourceKey);
	for (unsigned long n = 0; n < Mapi_ReadState->cbSourceKey; n++)
		Brutus_ReadState.pbSourceKey[(::CORBA::ULong)n] = (::CORBA::Octet)Mapi_ReadState->pbSourceKey[n];

	if (DeAlloc)
		MAPIFreeBuffer(Mapi_ReadState);

	return true;
}

bool readstate_brutus_to_mapi(const ::BRUTUS::READSTATE *Brutus_ReadState,
			      void *Parent,
			      ::READSTATE *& Mapi_ReadState)
{
	unsigned long len = Brutus_ReadState->pbSourceKey.length();

	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(::READSTATE),
					     Parent,
					     (void**)&Mapi_ReadState)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::READSTATE),
					       (void**)&Mapi_ReadState)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = Mapi_ReadState;
	}

	Mapi_ReadState->cbSourceKey = len;
	if (!len) {
		Mapi_ReadState->pbSourceKey = NULL;
	} else {
		if (S_OK != MAPIAllocateMore(len,
					     Parent,
					     (void**)&Mapi_ReadState->pbSourceKey)) {
			MAPIFreeBuffer(Parent);
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	}

	if (Brutus_ReadState->ulFlags & ::BRUTUS::BRUTUS_SYNC_READ)
		Mapi_ReadState->ulFlags |= SYNC_READ;

	for (unsigned long n = 0; n < len; n++)
		Mapi_ReadState->pbSourceKey[n] = (BYTE)Brutus_ReadState->pbSourceKey[(::CORBA::ULong)n];

	return true;
}

bool readstate_brutus_to_mapi_internal_alloc(const ::BRUTUS::READSTATE *Brutus_ReadState,
					     void *Parent,
					     ::READSTATE * const Mapi_ReadState)
{
	unsigned long len = Brutus_ReadState->pbSourceKey.length();

	Mapi_ReadState->cbSourceKey = len;
	if (!len) {
		Mapi_ReadState->pbSourceKey = NULL;
	} else if (Parent) {
		if (S_OK != MAPIAllocateMore(len,
					     Parent,
					     (void**)&Mapi_ReadState->pbSourceKey)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(len,
					       (void**)&Mapi_ReadState->pbSourceKey)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	}

	if (Brutus_ReadState->ulFlags & ::BRUTUS::BRUTUS_SYNC_READ)
		Mapi_ReadState->ulFlags |= SYNC_READ;

	for (unsigned long n = 0; n < len; n++)
		Mapi_ReadState->pbSourceKey[n] = (BYTE)Brutus_ReadState->pbSourceKey[(::CORBA::ULong)n];

	return true;
}

bool readstate_array_mapi_to_brutus(ULONG Count,
				    ::READSTATE *Mapi_ReadState,
				    ::BRUTUS::seq_READSTATE_out Brutus_ReadState,
				    bool DeAlloc)
{
	::BRUTUS::seq_READSTATE_var read_state;
	try {
		read_state = new ::BRUTUS::seq_READSTATE;
		if (!Count) {
			read_state->length(0);
			Brutus_ReadState = read_state._retn();
			if (DeAlloc)
				MAPIFreeBuffer(Mapi_ReadState);
			return true;
		}
		read_state->length(Count);
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		return false;
	}

	bool retv = true;
	for (unsigned long n = 0; n < Count; n++)
		retv = retv && readstate_mapi_to_brutus(&Mapi_ReadState[n], read_state[(::CORBA::ULong)n]);

	Brutus_ReadState = read_state._retn();
	if (DeAlloc)
		MAPIFreeBuffer(Mapi_ReadState);

	return retv;
}

bool readstate_array_brutus_to_mapi(const ::BRUTUS::seq_READSTATE *Brutus_ReadStates,
				    void *Parent,
				    ::READSTATE *& Mapi_ReadStates)
{
	if (!Brutus_ReadStates)
		return false;

	ULONG cValues = Brutus_ReadStates->length();
	if (!cValues) {
		Mapi_ReadStates = NULL;
		return true;
	}

	if (Parent) {
		if (S_OK != MAPIAllocateMore(cValues * sizeof(::READSTATE),
					     Parent,
					     (void**)&Mapi_ReadStates)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(cValues * sizeof(::READSTATE),
					       (void**)&Mapi_ReadStates)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = Mapi_ReadStates;
	}

	bool retval = true;
	for (ULONG i = 0; i < cValues; i++)
		retval = retval && readstate_brutus_to_mapi_internal_alloc(&(*Brutus_ReadStates)[(::CORBA::ULong)i],
									   Parent,
									   &Mapi_ReadStates[i]);

	return retval;
}

bool rowentry_brutus_to_mapi(const ::BRUTUS::ROWENTRY *Brutus_Rowentry,
			     void *Parent,
			     ::ROWENTRY *& Mapi_Rowentry)
{
	if (!Brutus_Rowentry)
		return false;

	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(::ROWENTRY),
					     Parent,
					     (void**)&Mapi_Rowentry)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(::ROWENTRY),
					       (void**)&Mapi_Rowentry)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = Mapi_Rowentry;
	}

	ULONG cValues = 0;
	if (!spropvalue_array_brutus_to_mapi(&Brutus_Rowentry->rgPropVals,
					     (void*)Mapi_Rowentry,
					     cValues,
					     Mapi_Rowentry->rgPropVals)) {
		MAPIFreeBuffer((void*)Mapi_Rowentry);
		BRUTUS_LOG_ERR("No memory");
		return false;
	}
	Mapi_Rowentry->cValues = cValues;

	Mapi_Rowentry->ulRowFlags = 0;
	::BRUTUS::BDEFINE flags = Brutus_Rowentry->ulRowFlags;
	if (flags & ::BRUTUS::BRUTUS_ROW_ADD) {
		Mapi_Rowentry->ulRowFlags |= ROW_ADD;
		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_ROW_ADD);
	}
	if (flags & ::BRUTUS::BRUTUS_ROW_MODIFY) {
		Mapi_Rowentry->ulRowFlags |= ROW_MODIFY;
		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_ROW_MODIFY);
	}
	if (flags & ::BRUTUS::BRUTUS_ROW_REMOVE) {
		Mapi_Rowentry->ulRowFlags |= ROW_REMOVE;
		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_ROW_REMOVE);
	}
	if (flags & ::BRUTUS::BRUTUS_ROW_EMPTY) {
		Mapi_Rowentry->ulRowFlags |= ROW_EMPTY;
		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_ROW_EMPTY);
	}
	if (flags) {
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown flag(s) from BRUTUS : %X", flags);
		BRUTUS_LOG_BUG(msg);
	}


	return true;
}

bool rowentry_brutus_to_mapi_internal_alloc(const ::BRUTUS::ROWENTRY *Brutus_Rowentry,
					    void *Parent,
					    ::ROWENTRY * const Mapi_Rowentry)
{
	if (!Brutus_Rowentry)
		return false;

	ULONG cValues = 0;
	if (!spropvalue_array_brutus_to_mapi(&Brutus_Rowentry->rgPropVals,
					     (void*)Mapi_Rowentry,
					     cValues,
					     Mapi_Rowentry->rgPropVals)) {
		MAPIFreeBuffer((void*)Mapi_Rowentry);
		BRUTUS_LOG_ERR("No memory");
		return false;
	}
	Mapi_Rowentry->cValues = cValues;

	Mapi_Rowentry->ulRowFlags = 0;
	::BRUTUS::BDEFINE flags = Brutus_Rowentry->ulRowFlags;
	if (flags & ::BRUTUS::BRUTUS_ROW_ADD) {
		Mapi_Rowentry->ulRowFlags |= ROW_ADD;
		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_ROW_ADD);
	}
	if (flags & ::BRUTUS::BRUTUS_ROW_MODIFY) {
		Mapi_Rowentry->ulRowFlags |= ROW_MODIFY;
		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_ROW_MODIFY);
	}
	if (flags & ::BRUTUS::BRUTUS_ROW_REMOVE) {
		Mapi_Rowentry->ulRowFlags |= ROW_REMOVE;
		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_ROW_REMOVE);
	}
	if (flags & ::BRUTUS::BRUTUS_ROW_EMPTY) {
		Mapi_Rowentry->ulRowFlags |= ROW_EMPTY;
		FLAGS_OFF(::BRUTUS::BDEFINE, flags, ::BRUTUS::BRUTUS_ROW_EMPTY);
	}
	if (flags) {
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown flag(s) from BRUTUS : %X", flags);
		BRUTUS_LOG_BUG(msg);
	}


	return true;
}

bool rowentry_array_brutus_to_mapi(const ::BRUTUS::seq_ROWENTRY *Brutus_RowList,
				   void *Parent,
				   ::ROWLIST *& Mapi_RowList)
{
	if (!Brutus_RowList)
		return false;

	ULONG cValues = Brutus_RowList->length();
	if (!cValues) {
		Mapi_RowList = NULL;
		return true;
	}

	if (Parent) {
		if (S_OK != MAPIAllocateMore(cValues * sizeof(::ROWLIST),
					     Parent,
					     (void**)&Mapi_RowList)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
	} else {
		if (S_OK != MAPIAllocateBuffer(cValues * sizeof(::ROWLIST),
					       (void**)&Mapi_RowList)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		Parent = Mapi_RowList;
	}

	bool retval = true;
	for (ULONG i = 0; i < cValues; i++)
		retval = retval && rowentry_brutus_to_mapi_internal_alloc(&(*Brutus_RowList)[(::CORBA::ULong)i],
									  Parent,
									  &Mapi_RowList->aEntries[i]);

	return retval;
}

bool action_mapi_to_brutus(::ACTION * Mapi_Action,
			   ::BRUTUS::ACTION_out Brutus_Action,
			   LPMAPISESSION Mapi_Session,
			   PortableServer::POA_ptr Poa,
			   bool DeAlloc)
{
	::BRUTUS::ACTION_var action;
	try {
		action = new ::BRUTUS::ACTION;
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		return false;
	}

	switch (Mapi_Action->acttype) {
	case OP_MOVE :
		action->actionType = ::BRUTUS::BRUTUS_OP_MOVE;
		break;
	case OP_COPY :
		action->actionType = ::BRUTUS::BRUTUS_OP_COPY;
		break;
	case OP_REPLY :
		action->actionType = ::BRUTUS::BRUTUS_OP_REPLY;
		break;
	case OP_OOF_REPLY :
		action->actionType = ::BRUTUS::BRUTUS_OP_OOF_REPLY;
		break;
	case OP_DEFER_ACTION :
		action->actionType = ::BRUTUS::BRUTUS_OP_DEFER_ACTION;
		break;
	case OP_BOUNCE :
		action->actionType = ::BRUTUS::BRUTUS_OP_BOUNCE;
		break;
	case OP_FORWARD :
		action->actionType = ::BRUTUS::BRUTUS_OP_FORWARD;
		break;
	case OP_DELEGATE :
		action->actionType = ::BRUTUS::BRUTUS_OP_DELEGATE;
		break;
	case OP_TAG :
		action->actionType = ::BRUTUS::BRUTUS_OP_TAG;
		break;
	case OP_DELETE :
		action->actionType = ::BRUTUS::BRUTUS_OP_DELETE;
		break;
	case OP_MARK_AS_READ :
		action->actionType = ::BRUTUS::BRUTUS_OP_MARK_AS_READ;
		break;
	default:
	{
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown ACTION.acttype from MAPI : %X", Mapi_Action->acttype);
		BRUTUS_LOG_BUG(msg);

		action->actionType = (::BRUTUS::ACTTYPE)Mapi_Action->acttype;
	}
	}

	if (Mapi_Action->ulActionFlavor == DO_NOT_SEND_TO_ORIGINATOR)
		action->ulActionFlavor = ::BRUTUS::BRUTUS_DO_NOT_SEND_TO_ORIGINATOR;
	else
		action->ulActionFlavor = 0;

	if (Mapi_Action->lpRes) {
		::BRUTUS::SRestrictionContainer_var bres;
		if (!srestriction_mapi_to_container(Mapi_Action->lpRes, Mapi_Session, bres.out(), Poa)) {
			BRUTUS_LOG_ERR("Could not convert MAPI SRestriction to Brutus SRestrictionContainer");
			return false;
		}
		action->lpRes = bres._retn();
		Mapi_Action->lpRes = NULL; // responsibility of the memory is taken by the corba object
	} else
		action->lpRes = ::BRUTUS::SRestrictionContainer::_nil();

	if (Mapi_Action->lpPropTagArray->cValues) {
		::BRUTUS::SPropTagArray_var btags;
		if (!proptag_array_mapi_to_brutus(Mapi_Action->lpPropTagArray, btags.out())) {
			BRUTUS_LOG_ERR("Could not convert MAPI SPropTagArray to Brutus SPropTagArray");
			return false;
		}
		action->lpPropTagArray = btags;
	} else
		action->lpPropTagArray.length(0);

	action->ulFlags = Mapi_Action->ulFlags;

	switch (Mapi_Action->acttype) {
	case OP_MOVE :
	case OP_COPY :
	{
		::BRUTUS::actMoveCopy_var act_mc;
			try {
				act_mc = new ::BRUTUS::actMoveCopy;
			}
			catch (std::bad_alloc &) {
				BRUTUS_LOG_ERR("No memory");
				return false;
			}

			if (!entryid_mapi_to_brutus(Mapi_Action->actMoveCopy.cbStoreEntryId,
						    Mapi_Action->actMoveCopy.lpStoreEntryId,
						    act_mc->lpStoreEntryId)) {
				BRUTUS_LOG_ERR("No memory");
				return false;
			}
			if (!entryid_mapi_to_brutus(Mapi_Action->actMoveCopy.cbFldEntryId,
						    Mapi_Action->actMoveCopy.lpFldEntryId,
						    act_mc->lpFldEntryId)) {
				BRUTUS_LOG_ERR("No memory");
				return false;
			}

			action->options.move_copy(act_mc);
			break;
	}
	case OP_REPLY :
	case OP_OOF_REPLY :
	{
		::BRUTUS::actReply_var act_r;
		try {
			act_r = new ::BRUTUS::actReply;
		}
		catch (std::bad_alloc &) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}

		if (!entryid_mapi_to_brutus(Mapi_Action->actReply.cbEntryId,
					    Mapi_Action->actReply.lpEntryId,
					    act_r->lpEntryId)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		if (!guid_mapi_to_brutus(&Mapi_Action->actReply.guidReplyTemplate,
					 act_r->guidReplyTemplate)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}

		action->options.reply(act_r);
		break;
	}
	case OP_DEFER_ACTION :
	{
		::BRUTUS::seq_octet_var b_octets;
		if (!seq_octet_mapi_to_brutus(Mapi_Action->actDeferAction.cbData,
					      Mapi_Action->actDeferAction.pbData,
					      b_octets.out())) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}

		action->options.actDeferAction(b_octets);

		break;
	}
	case OP_BOUNCE :
	{
		switch (Mapi_Action->scBounceCode) {
		case BOUNCE_MESSAGE_SIZE_TOO_LARGE :
			action->options.scBounceCode(::BRUTUS::BRUTUS_BOUNCE_MESSAGE_SIZE_TOO_LARGE);
			break;
		case BOUNCE_FORMS_MISMATCH :
			action->options.scBounceCode(::BRUTUS::BRUTUS_BOUNCE_FORMS_MISMATCH);
			break;
		case BOUNCE_ACCESS_DENIED :
			action->options.scBounceCode(::BRUTUS::BRUTUS_BOUNCE_ACCESS_DENIED );
			break;
		default :
		{
			char msg[128] = {0};
			sprintf_s(msg, sizeof(msg), "Unknown ACTION.scBounceCode from MAPI : %X", Mapi_Action->scBounceCode);
			BRUTUS_LOG_BUG(msg);

			action->options.scBounceCode((::BRUTUS::BDEFINE)Mapi_Action->scBounceCode);
		}
		}

		break;
	}
	case OP_FORWARD :
	case OP_DELEGATE :
	{
		::BRUTUS::ADRLIST_var b_adrl;
		try {
			b_adrl = new ::BRUTUS::ADRLIST;
		}
		catch (std::bad_alloc &) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		if (!adr_list_mapi_to_brutus(Mapi_Action->lpadrlist, b_adrl, Mapi_Session, false, Poa)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}

		action->options.lpadrlist(b_adrl);

		break;
	}
	case OP_TAG :
	{
		::BRUTUS::SPropValue_var b_prop;
		try {
			b_prop = new ::BRUTUS::SPropValue;
		}
		catch (std::bad_alloc &) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}
		if (!spropvalue_mapi_to_brutus(&Mapi_Action->propTag, b_prop, Mapi_Session, false, Poa)) {
			BRUTUS_LOG_ERR("No memory");
			return false;
		}

		action->options.propTag(b_prop);

		break;
	}
	case OP_DELETE :
	case OP_MARK_AS_READ :
		break;
	default:
	{
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown ACTION.acttype from MAPI : %X", Mapi_Action->acttype);
		BRUTUS_LOG_BUG(msg);
	}
	}

	if (DeAlloc)
		MAPIFreeBuffer(Mapi_Action);

	return true;
}

LPWSTR 
ascii_to_unicode(void *Parent,
		 const char *str)
{
	LPWSTR wstr = NULL;

	if (!str)
		return NULL;

	// get buffer size and allocate unicode string buffer
	int wlen = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
	if (Parent) {
		if (S_OK != MAPIAllocateMore((wlen + 1)*sizeof(wchar_t), Parent, (void**)&wstr))
			return NULL;
	} else {
		if (S_OK != MAPIAllocateBuffer((wlen + 1)*sizeof(wchar_t), (void**)&wstr))
			return NULL;
	}
	if (!wstr)
		goto out;

	// convert from ASCII to UNICODE
	if (!MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, wlen)) {
		if (!Parent)
			MAPIFreeBuffer(wstr);
		wstr = NULL;
	}
out:
	return wstr;
}

LPWSTR 
utf8_to_unicode(void *Parent,
		const char *str)
{
	LPWSTR wstr = NULL;

	if (!str)
		return NULL;

	// get buffer size and allocate unicode string buffer
	int wlen = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
	if (Parent) {
		if (S_OK != MAPIAllocateMore((wlen + 1)*sizeof(wchar_t), Parent, (void**)&wstr))
			return NULL;
	} else {
		if (S_OK != MAPIAllocateBuffer((wlen + 1)*sizeof(wchar_t), (void**)&wstr))
			return NULL;
	}
	if (!wstr)
		goto out;

	// convert from UTF8 to UNICODE
	if (!MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, wlen)) {
		if (!Parent)
			MAPIFreeBuffer(wstr);
		wstr = NULL;
	}
out:
	return wstr;
}

/*
 * Return value must be freed with string_free()
 */
char*
unicode_to_utf8(LPCWSTR wstr)
{
	char *utf8_str = NULL;

	if (!wstr)
		return NULL;

	// get buffer size and allocate utf8 string buffer
	int utf8_len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
	utf8_str = ::CORBA::string_alloc(utf8_len - 1);
	if (!utf8_str)
		return NULL;

	// convert to UTF8
	if (!WideCharToMultiByte(CP_UTF8, 0, wstr, -1, utf8_str, utf8_len, NULL, NULL)) {
		::CORBA::string_free(utf8_str);
		utf8_str = NULL;
	}

	::CORBA::String_var retv = utf8_str ? (char*)utf8_str : (const char*)"";

	return retv._retn();
}

static char*
convert_encoding(void *Parent,
		 const char *str,
		 const unsigned long codepage_in,
		 const unsigned long codepage_out)
{
	int buf_size = MultiByteToWideChar(codepage_in, NULL, str, -1, 0, 0 );
	if (!buf_size) 
		return NULL;
	
	wchar_t* unicode_str = new wchar_t[buf_size + 1];
	if (!MultiByteToWideChar(codepage_in, NULL, str, -1, unicode_str, buf_size)) {
		delete[] unicode_str;
		return NULL;
	}
	
	buf_size = WideCharToMultiByte(codepage_out, NULL, unicode_str, -1, 0, 0,0,0 );
	if (!buf_size) {
		delete[] unicode_str;
		return NULL;
	}

	char *cp_str = NULL;
	if (Parent) {
		if (S_OK != MAPIAllocateMore(sizeof(char) * (buf_size + 1), Parent, (void**)&cp_str))
			return NULL;
	} else {
		if (S_OK != MAPIAllocateBuffer(sizeof(char) * (buf_size + 1), (void**)&cp_str))
			return NULL;
	}
	if (!cp_str)
		return NULL;

	if (!WideCharToMultiByte(codepage_out, NULL, unicode_str, -1, cp_str, buf_size, 0, 0 )) {
		delete[] unicode_str;
		MAPIFreeBuffer(cp_str);
		return NULL;
	}

	delete[] unicode_str;
	return cp_str;
}

char*
utf8_to_codepage(void *Parent,
		 const char *str,
		 const unsigned long codepage)
{
	return convert_encoding(Parent, str, CP_UTF8, codepage);
}

char*
codepage_to_utf8(void *Parent,
		 const char *str,
		 const unsigned long codepage)
{
	return convert_encoding(Parent, str, codepage, CP_UTF8);
}

bool
large_int_mapi_to_brutus_server_version(::LARGE_INTEGER *Mapi_LI,
					::BRUTUS::SERVER_VERSION_out Version)
{
	if (!Mapi_LI)
		return false;

	::BRUTUS::SERVER_VERSION_var ver;
	try {
		ver = new ::BRUTUS::SERVER_VERSION;
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		return false;
	}

	LONG hp = (LONG)(Mapi_LI->u.HighPart);
	DWORD lp = (DWORD)(Mapi_LI->u.LowPart);

	ver->MajorVersion = (SHORT) (hp >> 16);
	ver->MinorVersion = (SHORT) (hp & 0x0000FFFF);
	ver->Build = (SHORT) (lp >> 16);
	ver->MinorBuild = (SHORT) (lp & 0x0000FFFF);

	Version = ver._retn();

	return true;
}

const char* 
hresult_to_str(const HRESULT HValue)
{
	switch (HValue) {
	case S_OK :
		return "S_OK";
	case 0x81002746 :
		return "MAPI_E_UNKNOWN_MAILBOX";
	case MAPI_E_CALL_FAILED :
		return "MAPI_E_CALL_FAILED";
	case MAPI_E_NOT_ENOUGH_MEMORY :
		return "MAPI_E_NOT_ENOUGH_MEMORY";
	case MAPI_E_INVALID_PARAMETER :
		return "MAPI_E_INVALID_PARAMETER";
	case MAPI_E_INTERFACE_NOT_SUPPORTED :
		return "MAPI_E_INTERFACE_NOT_SUPPORTED";
	case MAPI_E_NO_ACCESS :
		return "MAPI_E_NO_ACCESS";
	case MAPI_E_NO_SUPPORT :
		return "MAPI_E_NO_SUPPORT";
	case MAPI_E_BAD_CHARWIDTH :
		return "MAPI_E_BAD_CHARWIDTH";
	case MAPI_E_STRING_TOO_LONG :
		return "MAPI_E_STRING_TOO_LONG";
	case MAPI_E_UNKNOWN_FLAGS :
		return "MAPI_E_UNKNOWN_FLAGS";
	case MAPI_E_INVALID_ENTRYID :
		return "MAPI_E_INVALID_ENTRYID";
	case MAPI_E_INVALID_OBJECT :
		return "MAPI_E_INVALID_OBJECT";
	case MAPI_E_OBJECT_CHANGED :
		return "MAPI_E_OBJECT_CHANGED";
	case MAPI_E_OBJECT_DELETED :
		return "MAPI_E_OBJECT_DELETED";
	case MAPI_E_BUSY :
		return "MAPI_E_BUSY";
	case MAPI_E_NOT_ENOUGH_DISK :
		return "MAPI_E_NOT_ENOUGH_DISK";
	case MAPI_E_NOT_ENOUGH_RESOURCES :
		return "MAPI_E_NOT_ENOUGH_RESOURCES";
	case MAPI_E_NOT_FOUND :
		return "MAPI_E_NOT_FOUND";
	case MAPI_E_VERSION :
		return "MAPI_E_VERSION";
	case MAPI_E_LOGON_FAILED :
		return "MAPI_E_LOGON_FAILED";
	case MAPI_E_SESSION_LIMIT :
		return "MAPI_E_SESSION_LIMIT";
	case MAPI_E_USER_CANCEL :
		return "MAPI_E_USER_CANCEL";
	case MAPI_E_UNABLE_TO_ABORT :
		return "MAPI_E_UNABLE_TO_ABORT";
	case MAPI_E_NETWORK_ERROR :
		return "MAPI_E_NETWORK_ERROR";
	case MAPI_E_DISK_ERROR :
		return "MAPI_E_DISK_ERROR";
	case MAPI_E_TOO_COMPLEX :
		return "MAPI_E_TOO_COMPLEX";
	case MAPI_E_BAD_COLUMN :
		return "MAPI_E_BAD_COLUMN";
	case MAPI_E_EXTENDED_ERROR :
		return "MAPI_E_EXTENDED_ERROR";
	case MAPI_E_COMPUTED :
		return "MAPI_E_COMPUTED";
	case MAPI_E_CORRUPT_DATA :
		return "MAPI_E_CORRUPT_DATA";
	case MAPI_E_UNCONFIGURED :
		return "MAPI_E_UNCONFIGURED";
	case MAPI_E_FAILONEPROVIDER :
		return "MAPI_E_FAILONEPROVIDER";
	case MAPI_E_UNKNOWN_CPID :
		return "MAPI_E_UNKNOWN_CPID";
	case MAPI_E_UNKNOWN_LCID :
		return "MAPI_E_UNKNOWN_LCID";
	case MAPI_E_PASSWORD_CHANGE_REQUIRED :
		return "MAPI_E_PASSWORD_CHANGE_REQUIRED";
	case MAPI_E_PASSWORD_EXPIRED :
		return "MAPI_E_PASSWORD_EXPIRED";
	case MAPI_E_INVALID_WORKSTATION_ACCOUNT :
		return "MAPI_E_INVALID_WORKSTATION_ACCOUNT";
	case MAPI_E_INVALID_ACCESS_TIME :
		return "MAPI_E_INVALID_ACCESS_TIME";
	case MAPI_E_ACCOUNT_DISABLED :
		return "MAPI_E_ACCOUNT_DISABLED";
	case MAPI_E_END_OF_SESSION :
		return "MAPI_E_END_OF_SESSION";
	case MAPI_E_UNKNOWN_ENTRYID :
		return "MAPI_E_UNKNOWN_ENTRYID";
	case MAPI_E_MISSING_REQUIRED_COLUMN :
		return "MAPI_E_MISSING_REQUIRED_COLUMN";
	case MAPI_W_NO_SERVICE :
		return "MAPI_W_NO_SERVICE";
	case MAPI_E_BAD_VALUE :
		return "MAPI_E_BAD_VALUE";
	case MAPI_E_INVALID_TYPE :
		return "MAPI_E_INVALID_TYPE";
	case MAPI_E_TYPE_NO_SUPPORT :
		return "MAPI_E_TYPE_NO_SUPPORT";
	case MAPI_E_UNEXPECTED_TYPE :
		return "MAPI_E_UNEXPECTED_TYPE";
	case MAPI_E_TOO_BIG :
		return "MAPI_E_TOO_BIG";
	case MAPI_E_DECLINE_COPY :
		return "MAPI_E_DECLINE_COPY";
	case MAPI_E_UNEXPECTED_ID :
		return "MAPI_E_UNEXPECTED_ID";
	case MAPI_W_ERRORS_RETURNED :
		return "MAPI_W_ERRORS_RETURNED";
	case MAPI_E_UNABLE_TO_COMPLETE :
		return "MAPI_E_UNABLE_TO_COMPLETE";
	case MAPI_E_TIMEOUT :
		return "MAPI_E_TIMEOUT";
	case MAPI_E_TABLE_EMPTY :
		return "MAPI_E_TABLE_EMPTY";
	case MAPI_E_TABLE_TOO_BIG :
		return "MAPI_E_TABLE_TOO_BIG";
	case MAPI_E_INVALID_BOOKMARK :
		return "MAPI_E_INVALID_BOOKMARK";
	case MAPI_W_POSITION_CHANGED :
		return "MAPI_W_POSITION_CHANGED";
	case MAPI_W_APPROX_COUNT :
		return "MAPI_W_APPROX_COUNT";
	case MAPI_E_WAIT :
		return "MAPI_E_WAIT";
	case MAPI_E_CANCEL :
		return "MAPI_E_CANCEL";
	case MAPI_E_NOT_ME :
		return "MAPI_E_NOT_ME";
	case MAPI_W_CANCEL_MESSAGE :
		return "MAPI_W_CANCEL_MESSAGE";
	case MAPI_E_CORRUPT_STORE :
		return "MAPI_E_CORRUPT_STORE";
	case MAPI_E_NOT_IN_QUEUE :
		return "MAPI_E_NOT_IN_QUEUE";
	case MAPI_E_NO_SUPPRESS :
		return "MAPI_E_NO_SUPPRESS";
	case MAPI_E_COLLISION :
		return "MAPI_E_COLLISION";
	case MAPI_E_NOT_INITIALIZED :
		return "MAPI_E_NOT_INITIALIZED";
	case MAPI_E_NON_STANDARD :
		return "MAPI_E_NON_STANDARD";
	case MAPI_E_NO_RECIPIENTS :
		return "MAPI_E_NO_RECIPIENTS";
	case MAPI_E_SUBMITTED :
		return "MAPI_E_SUBMITTED";
	case MAPI_E_HAS_FOLDERS :
		return "MAPI_E_HAS_FOLDERS";
	case MAPI_E_HAS_MESSAGES :
		return "MAPI_E_HAS_MESSAGES";
	case MAPI_E_FOLDER_CYCLE :
		return "MAPI_E_FOLDER_CYCLE";
	case MAPI_W_PARTIAL_COMPLETION :
		return "MAPI_W_PARTIAL_COMPLETION";
	case MAPI_E_AMBIGUOUS_RECIP :
		return "MAPI_E_AMBIGUOUS_RECIP";
	case OLEOBJ_S_CANNOT_DOVERB_NOW :
		return "OLEOBJ_S_CANNOT_DOVERB_NOW";
	case STG_E_INVALIDFUNCTION :
		return "STG_E_INVALIDFUNCTION";
	case STG_E_FILENOTFOUND :
		return "STG_E_FILENOTFOUND";
	case STG_E_PATHNOTFOUND :
		return "STG_E_PATHNOTFOUND";
	case STG_E_TOOMANYOPENFILES :
		return "STG_E_TOOMANYOPENFILES";
	case STG_E_ACCESSDENIED :
		return "STG_E_ACCESSDENIED";
	case STG_E_INVALIDHANDLE :
		return "STG_E_INVALIDHANDLE";
	case STG_E_INSUFFICIENTMEMORY :
		return "STG_E_INSUFFICIENTMEMORY";
	case STG_E_INVALIDPOINTER :
		return "STG_E_INVALIDPOINTER";
	case STG_E_NOMOREFILES :
		return "STG_E_NOMOREFILES";
	case STG_E_DISKISWRITEPROTECTED :
		return "STG_E_DISKISWRITEPROTECTED";
	case STG_E_SEEKERROR :
		return "STG_E_SEEKERROR";
	case STG_E_WRITEFAULT :
		return "STG_E_WRITEFAULT";
	case STG_E_READFAULT :
		return "STG_E_READFAULT";
	case STG_E_SHAREVIOLATION :
		return "STG_E_SHAREVIOLATION";
	case STG_E_LOCKVIOLATION :
		return "STG_E_LOCKVIOLATION";
	case STG_E_FILEALREADYEXISTS :
		return "STG_E_FILEALREADYEXISTS";
	case STG_E_INVALIDPARAMETER :
		return "STG_E_INVALIDPARAMETER";
	case STG_E_MEDIUMFULL :
		return "STG_E_MEDIUMFULL";
	case STG_E_PROPSETMISMATCHED :
		return "STG_E_PROPSETMISMATCHED";
	case STG_E_ABNORMALAPIEXIT :
		return "STG_E_ABNORMALAPIEXIT";
	case STG_E_INVALIDHEADER :
		return "STG_E_INVALIDHEADER";
	case STG_E_INVALIDNAME :
		return "STG_E_INVALIDNAME";
	case STG_E_UNKNOWN :
		return "STG_E_UNKNOWN";
	case STG_E_UNIMPLEMENTEDFUNCTION :
		return "STG_E_UNIMPLEMENTEDFUNCTION";
	case STG_E_INVALIDFLAG :
		return "STG_E_INVALIDFLAG";
	case STG_E_INUSE :
		return "STG_E_INUSE";
	case STG_E_NOTCURRENT :
		return "STG_E_NOTCURRENT";
	case STG_E_REVERTED :
		return "STG_E_REVERTED";
	case STG_E_CANTSAVE :
		return "STG_E_CANTSAVE";
	case STG_E_OLDFORMAT :
		return "STG_E_OLDFORMAT";
	case STG_E_OLDDLL :
		return "STG_E_OLDDLL";
	case STG_E_SHAREREQUIRED :
		return "STG_E_SHAREREQUIRED";
	case STG_E_NOTFILEBASEDSTORAGE :
		return "STG_E_NOTFILEBASEDSTORAGE";
	case STG_E_EXTANTMARSHALLINGS :
		return "STG_E_EXTANTMARSHALLINGS";
	case STG_E_DOCFILECORRUPT :
		return "STG_E_DOCFILECORRUPT";
	case STG_E_BADBASEADDRESS :
		return "STG_E_BADBASEADDRESS";
	case STG_E_INCOMPLETE :
		return "STG_E_INCOMPLETE";
	case STG_E_TERMINATED :
		return "STG_E_TERMINATED";
	case STG_S_CONVERTED :
		return "STG_S_CONVERTED";
	case STG_S_BLOCK :
		return "STG_S_BLOCK";
	case STG_S_RETRYNOW :
		return "STG_S_RETRYNOW";
	case STG_S_MONITORING :
		return "STG_S_MONITORING";
	case STG_S_MULTIPLEOPENS :
		return "STG_S_MULTIPLEOPENS";
	case STG_S_CONSOLIDATIONFAILED :
		return "STG_S_CONSOLIDATIONFAILED";
	case STG_S_CANNOTCONSOLIDATE :
		return "STG_S_CANNOTCONSOLIDATE";
	case E_PENDING :
		return "E_PENDING";
	case SYNC_E_OBJECT_DELETED :
		return "SYNC_E_OBJECT_DELETED";
	case SYNC_E_IGNORE :
		return "SYNC_E_IGNORE";
	case SYNC_E_CONFLICT :
		return "SYNC_E_CONFLICT";
	case SYNC_E_NO_PARENT :
		return "SYNC_E_NO_PARENT";
	case SYNC_E_INCEST :
		return "SYNC_E_INCEST";
	case SYNC_E_UNSYNCHRONIZED :
		return "SYNC_E_UNSYNCHRONIZED";
	case SYNC_W_PROGRESS :
		return "SYNC_W_PROGRESS";
	case SYNC_W_CLIENT_CHANGE_NEWER :
		return "SYNC_W_CLIENT_CHANGE_NEWER";
	case EDK_E_NOT_FOUND :
		return "EDK_E_NOT_FOUND";
	case EDK_E_SHUTDOWN_SERVICE :
		return "EDK_E_SHUTDOWN_SERVICE";
	case EDK_E_ALREADY_EXISTS :
		return "EDK_E_ALREADY_EXISTS";
	case EDK_E_END_OF_FILE :
		return "EDK_E_END_OF_FILE";
	case EDK_E_AMBIGUOUS :
		return "EDK_E_AMBIGUOUS";
	case EDK_E_PARSE :
		return "EDK_E_PARSE";
	default:
		break;
	}

	return "Unknown HRESULT from MAPI";
}

