#include <utility>
#include <gromox/defs.h>
#include <gromox/zcore_client.hpp>
#include <gromox/zcore_rpc.hpp>
#include "php.h"
ec_error_t zclient_logon(const char *username, /*maybenull*/ const char *password, const char *rhost, uint32_t flags, GUID *hsession)
{
	zcreq_logon::view_t q{};
	zcresp_logon r{};

	q.call_id = zcore_callid::logon;
	q.username = deconst(username);
	q.password = deconst(password);
	q.rhost = deconst(rhost);
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hsession = std::move(r.hsession);
	return r.result;
}

ec_error_t zclient_uinfo(const char *username, BINARY *entryid, std::string *pdisplay_name, std::string *px500dn, uint32_t *privilege_bits)
{
	zcreq_uinfo::view_t q{};
	zcresp_uinfo r{};

	q.call_id = zcore_callid::uinfo;
	q.username = deconst(username);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*entryid = std::move(r.entryid);
	*pdisplay_name = std::move(r.pdisplay_name);
	*px500dn = std::move(r.px500dn);
	*privilege_bits = std::move(r.privilege_bits);
	return r.result;
}

ec_error_t zclient_unloadobject(GUID hsession, uint32_t hobject)
{
	zcreq_unloadobject::view_t q{};
	zcresp_unloadobject r{};

	q.call_id = zcore_callid::unloadobject;
	q.hsession = hsession;
	q.hobject = hobject;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_openentry(GUID hsession, BINARY entryid, uint32_t flags, zs_objtype *mapi_type, uint32_t *hobject)
{
	zcreq_openentry::view_t q{};
	zcresp_openentry r{};

	q.call_id = zcore_callid::openentry;
	q.hsession = hsession;
	q.entryid = entryid;
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*mapi_type = std::move(r.mapi_type);
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_openstoreentry(GUID hsession, uint32_t hobject, BINARY entryid, uint32_t flags, zs_objtype *mapi_type, uint32_t *hxobject)
{
	zcreq_openstoreentry::view_t q{};
	zcresp_openstoreentry r{};

	q.call_id = zcore_callid::openstoreentry;
	q.hsession = hsession;
	q.hobject = hobject;
	q.entryid = entryid;
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*mapi_type = std::move(r.mapi_type);
	*hxobject = std::move(r.hxobject);
	return r.result;
}

ec_error_t zclient_openabentry(GUID hsession, BINARY entryid, zs_objtype *mapi_type, uint32_t *hobject)
{
	zcreq_openabentry::view_t q{};
	zcresp_openabentry r{};

	q.call_id = zcore_callid::openabentry;
	q.hsession = hsession;
	q.entryid = entryid;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*mapi_type = std::move(r.mapi_type);
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_resolvename(GUID hsession, const TARRAY_SET *pcond_set, TARRAY_SET *result_set)
{
	zcreq_resolvename::view_t q{};
	zcresp_resolvename r{};

	q.call_id = zcore_callid::resolvename;
	q.hsession = hsession;
	q.pcond_set = deconst(pcond_set);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*result_set = std::move(r.result_set);
	return r.result;
}

ec_error_t zclient_getpermissions(GUID hsession, uint32_t hobject, PERMISSION_SET *perm_set)
{
	zcreq_getpermissions::view_t q{};
	zcresp_getpermissions r{};

	q.call_id = zcore_callid::getpermissions;
	q.hsession = hsession;
	q.hobject = hobject;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*perm_set = std::move(r.perm_set);
	return r.result;
}

ec_error_t zclient_modifypermissions(GUID hsession, uint32_t hfolder, const PERMISSION_SET *pset)
{
	zcreq_modifypermissions::view_t q{};
	zcresp_modifypermissions r{};

	q.call_id = zcore_callid::modifypermissions;
	q.hsession = hsession;
	q.hfolder = hfolder;
	q.pset = deconst(pset);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_modifyrules(GUID hsession, uint32_t hfolder, uint32_t flags, const RULE_LIST *plist)
{
	zcreq_modifyrules::view_t q{};
	zcresp_modifyrules r{};

	q.call_id = zcore_callid::modifyrules;
	q.hsession = hsession;
	q.hfolder = hfolder;
	q.flags = flags;
	q.plist = deconst(plist);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_getabgal(GUID hsession, BINARY *entryid)
{
	zcreq_getabgal::view_t q{};
	zcresp_getabgal r{};

	q.call_id = zcore_callid::getabgal;
	q.hsession = hsession;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*entryid = std::move(r.entryid);
	return r.result;
}

ec_error_t zclient_loadstoretable(GUID hsession, uint32_t *hobject)
{
	zcreq_loadstoretable::view_t q{};
	zcresp_loadstoretable r{};

	q.call_id = zcore_callid::loadstoretable;
	q.hsession = hsession;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_openstore(GUID hsession, BINARY entryid, uint32_t *hobject)
{
	zcreq_openstore::view_t q{};
	zcresp_openstore r{};

	q.call_id = zcore_callid::openstore;
	q.hsession = hsession;
	q.entryid = entryid;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_openprofilesec(GUID hsession, /*maybenull*/ const FLATUID *puid, uint32_t *hobject)
{
	zcreq_openprofilesec::view_t q{};
	zcresp_openprofilesec r{};

	q.call_id = zcore_callid::openprofilesec;
	q.hsession = hsession;
	q.puid = deconst(puid);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_loadhierarchytable(GUID hsession, uint32_t hfolder, uint32_t flags, uint32_t *hobject)
{
	zcreq_loadhierarchytable::view_t q{};
	zcresp_loadhierarchytable r{};

	q.call_id = zcore_callid::loadhierarchytable;
	q.hsession = hsession;
	q.hfolder = hfolder;
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_loadcontenttable(GUID hsession, uint32_t hfolder, uint32_t flags, uint32_t *hobject)
{
	zcreq_loadcontenttable::view_t q{};
	zcresp_loadcontenttable r{};

	q.call_id = zcore_callid::loadcontenttable;
	q.hsession = hsession;
	q.hfolder = hfolder;
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_loadrecipienttable(GUID hsession, uint32_t hmessage, uint32_t *hobject)
{
	zcreq_loadrecipienttable::view_t q{};
	zcresp_loadrecipienttable r{};

	q.call_id = zcore_callid::loadrecipienttable;
	q.hsession = hsession;
	q.hmessage = hmessage;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_loadruletable(GUID hsession, uint32_t hfolder, uint32_t *hobject)
{
	zcreq_loadruletable::view_t q{};
	zcresp_loadruletable r{};

	q.call_id = zcore_callid::loadruletable;
	q.hsession = hsession;
	q.hfolder = hfolder;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_createmessage(GUID hsession, uint32_t hfolder, uint32_t flags, uint32_t *hobject)
{
	zcreq_createmessage::view_t q{};
	zcresp_createmessage r{};

	q.call_id = zcore_callid::createmessage;
	q.hsession = hsession;
	q.hfolder = hfolder;
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_deletemessages(GUID hsession, uint32_t hfolder, const BINARY_ARRAY *pentryids, uint32_t flags)
{
	zcreq_deletemessages::view_t q{};
	zcresp_deletemessages r{};

	q.call_id = zcore_callid::deletemessages;
	q.hsession = hsession;
	q.hfolder = hfolder;
	q.pentryids = deconst(pentryids);
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_copymessages(GUID hsession, uint32_t hsrcfolder, uint32_t hdstfolder, const BINARY_ARRAY *pentryids, uint32_t flags)
{
	zcreq_copymessages::view_t q{};
	zcresp_copymessages r{};

	q.call_id = zcore_callid::copymessages;
	q.hsession = hsession;
	q.hsrcfolder = hsrcfolder;
	q.hdstfolder = hdstfolder;
	q.pentryids = deconst(pentryids);
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_setreadflags(GUID hsession, uint32_t hfolder, const BINARY_ARRAY *pentryids, uint32_t flags)
{
	zcreq_setreadflags::view_t q{};
	zcresp_setreadflags r{};

	q.call_id = zcore_callid::setreadflags;
	q.hsession = hsession;
	q.hfolder = hfolder;
	q.pentryids = deconst(pentryids);
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_createfolder(GUID hsession, uint32_t hparent_folder, uint32_t folder_type, const char *folder_name, const char *folder_comment, uint32_t flags, uint32_t *hobject)
{
	zcreq_createfolder::view_t q{};
	zcresp_createfolder r{};

	q.call_id = zcore_callid::createfolder;
	q.hsession = hsession;
	q.hparent_folder = hparent_folder;
	q.folder_type = folder_type;
	q.folder_name = deconst(folder_name);
	q.folder_comment = deconst(folder_comment);
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_deletefolder(GUID hsession, uint32_t hparent_folder, BINARY entryid, uint32_t flags)
{
	zcreq_deletefolder::view_t q{};
	zcresp_deletefolder r{};

	q.call_id = zcore_callid::deletefolder;
	q.hsession = hsession;
	q.hparent_folder = hparent_folder;
	q.entryid = entryid;
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_emptyfolder(GUID hsession, uint32_t hfolder, uint32_t flags)
{
	zcreq_emptyfolder::view_t q{};
	zcresp_emptyfolder r{};

	q.call_id = zcore_callid::emptyfolder;
	q.hsession = hsession;
	q.hfolder = hfolder;
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_copyfolder(GUID hsession, uint32_t hsrc_folder, BINARY entryid, uint32_t hdst_folder, /*maybenull*/ const char *new_name, uint32_t flags)
{
	zcreq_copyfolder::view_t q{};
	zcresp_copyfolder r{};

	q.call_id = zcore_callid::copyfolder;
	q.hsession = hsession;
	q.hsrc_folder = hsrc_folder;
	q.entryid = entryid;
	q.hdst_folder = hdst_folder;
	q.new_name = deconst(new_name);
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_getstoreentryid(const char *mailbox_dn, BINARY *entryid)
{
	zcreq_getstoreentryid::view_t q{};
	zcresp_getstoreentryid r{};

	q.call_id = zcore_callid::getstoreentryid;
	q.mailbox_dn = deconst(mailbox_dn);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*entryid = std::move(r.entryid);
	return r.result;
}

ec_error_t zclient_entryidfromsourcekey(GUID hsession, uint32_t hstore, BINARY folder_key, /*maybenull*/ const BINARY *pmessage_key, BINARY *entryid)
{
	zcreq_entryidfromsourcekey::view_t q{};
	zcresp_entryidfromsourcekey r{};

	q.call_id = zcore_callid::entryidfromsourcekey;
	q.hsession = hsession;
	q.hstore = hstore;
	q.folder_key = folder_key;
	q.pmessage_key = deconst(pmessage_key);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*entryid = std::move(r.entryid);
	return r.result;
}

ec_error_t zclient_storeadvise(GUID hsession, uint32_t hstore, /*maybenull*/ const BINARY *pentryid, uint32_t event_mask, uint32_t *sub_id)
{
	zcreq_storeadvise::view_t q{};
	zcresp_storeadvise r{};

	q.call_id = zcore_callid::storeadvise;
	q.hsession = hsession;
	q.hstore = hstore;
	q.pentryid = deconst(pentryid);
	q.event_mask = event_mask;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*sub_id = std::move(r.sub_id);
	return r.result;
}

ec_error_t zclient_unadvise(GUID hsession, uint32_t hstore, uint32_t sub_id)
{
	zcreq_unadvise::view_t q{};
	zcresp_unadvise r{};

	q.call_id = zcore_callid::unadvise;
	q.hsession = hsession;
	q.hstore = hstore;
	q.sub_id = sub_id;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_notifdequeue(const NOTIF_SINK *psink, uint32_t timeval, std::vector<ZNOTIFICATION> *notifications)
{
	zcreq_notifdequeue::view_t q{};
	zcresp_notifdequeue r{};

	q.call_id = zcore_callid::notifdequeue;
	q.psink = deconst(psink);
	q.timeval = timeval;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*notifications = std::move(r.notifications);
	return r.result;
}

ec_error_t zclient_queryrows(GUID hsession, uint32_t htable, uint32_t start, uint32_t count, /*maybenull*/ const RESTRICTION *prestriction, const std::optional<std::vector<gromox::proptag_t>> &pproptags, TARRAY_SET *rowset)
{
	zcreq_queryrows::view_t q{};
	zcresp_queryrows r{};

	q.call_id = zcore_callid::queryrows;
	q.hsession = hsession;
	q.htable = htable;
	q.start = start;
	q.count = count;
	q.prestriction = deconst(prestriction);
	q.pproptags = pproptags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*rowset = std::move(r.rowset);
	return r.result;
}

ec_error_t zclient_setcolumns(GUID hsession, uint32_t htable, proptag_cspan pproptags, uint32_t flags)
{
	zcreq_setcolumns::view_t q{};
	zcresp_setcolumns r{};

	q.call_id = zcore_callid::setcolumns;
	q.hsession = hsession;
	q.htable = htable;
	q.pproptags = pproptags;
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_seekrow(GUID hsession, uint32_t htable, uint32_t bookmark, int32_t seek_rows, int32_t *sought_rows)
{
	zcreq_seekrow::view_t q{};
	zcresp_seekrow r{};

	q.call_id = zcore_callid::seekrow;
	q.hsession = hsession;
	q.htable = htable;
	q.bookmark = bookmark;
	q.seek_rows = seek_rows;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*sought_rows = std::move(r.sought_rows);
	return r.result;
}

ec_error_t zclient_sorttable(GUID hsession, uint32_t htable, const SORTORDER_SET *psortset)
{
	zcreq_sorttable::view_t q{};
	zcresp_sorttable r{};

	q.call_id = zcore_callid::sorttable;
	q.hsession = hsession;
	q.htable = htable;
	q.psortset = deconst(psortset);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_getrowcount(GUID hsession, uint32_t htable, uint32_t *count)
{
	zcreq_getrowcount::view_t q{};
	zcresp_getrowcount r{};

	q.call_id = zcore_callid::getrowcount;
	q.hsession = hsession;
	q.htable = htable;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*count = std::move(r.count);
	return r.result;
}

ec_error_t zclient_restricttable(GUID hsession, uint32_t htable, const RESTRICTION *prestriction, uint32_t flags)
{
	zcreq_restricttable::view_t q{};
	zcresp_restricttable r{};

	q.call_id = zcore_callid::restricttable;
	q.hsession = hsession;
	q.htable = htable;
	q.prestriction = deconst(prestriction);
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_findrow(GUID hsession, uint32_t htable, uint32_t bookmark, const RESTRICTION *prestriction, uint32_t flags, uint32_t *row_idx)
{
	zcreq_findrow::view_t q{};
	zcresp_findrow r{};

	q.call_id = zcore_callid::findrow;
	q.hsession = hsession;
	q.htable = htable;
	q.bookmark = bookmark;
	q.prestriction = deconst(prestriction);
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*row_idx = std::move(r.row_idx);
	return r.result;
}

ec_error_t zclient_createbookmark(GUID hsession, uint32_t htable, uint32_t *bookmark)
{
	zcreq_createbookmark::view_t q{};
	zcresp_createbookmark r{};

	q.call_id = zcore_callid::createbookmark;
	q.hsession = hsession;
	q.htable = htable;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*bookmark = std::move(r.bookmark);
	return r.result;
}

ec_error_t zclient_freebookmark(GUID hsession, uint32_t htable, uint32_t bookmark)
{
	zcreq_freebookmark::view_t q{};
	zcresp_freebookmark r{};

	q.call_id = zcore_callid::freebookmark;
	q.hsession = hsession;
	q.htable = htable;
	q.bookmark = bookmark;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_getreceivefolder(GUID hsession, uint32_t hstore, /*maybenull*/ const char *pstrclass, BINARY *entryid)
{
	zcreq_getreceivefolder::view_t q{};
	zcresp_getreceivefolder r{};

	q.call_id = zcore_callid::getreceivefolder;
	q.hsession = hsession;
	q.hstore = hstore;
	q.pstrclass = deconst(pstrclass);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*entryid = std::move(r.entryid);
	return r.result;
}

ec_error_t zclient_modifyrecipients(GUID hsession, uint32_t hmessage, uint32_t flags, const TARRAY_SET *prcpt_list)
{
	zcreq_modifyrecipients::view_t q{};
	zcresp_modifyrecipients r{};

	q.call_id = zcore_callid::modifyrecipients;
	q.hsession = hsession;
	q.hmessage = hmessage;
	q.flags = flags;
	q.prcpt_list = deconst(prcpt_list);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_submitmessage(GUID hsession, uint32_t hmessage)
{
	zcreq_submitmessage::view_t q{};
	zcresp_submitmessage r{};

	q.call_id = zcore_callid::submitmessage;
	q.hsession = hsession;
	q.hmessage = hmessage;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_loadattachmenttable(GUID hsession, uint32_t hmessage, uint32_t *hobject)
{
	zcreq_loadattachmenttable::view_t q{};
	zcresp_loadattachmenttable r{};

	q.call_id = zcore_callid::loadattachmenttable;
	q.hsession = hsession;
	q.hmessage = hmessage;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_openattachment(GUID hsession, uint32_t hmessage, uint32_t attach_id, uint32_t *hobject)
{
	zcreq_openattachment::view_t q{};
	zcresp_openattachment r{};

	q.call_id = zcore_callid::openattachment;
	q.hsession = hsession;
	q.hmessage = hmessage;
	q.attach_id = attach_id;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_createattachment(GUID hsession, uint32_t hmessage, uint32_t *hobject)
{
	zcreq_createattachment::view_t q{};
	zcresp_createattachment r{};

	q.call_id = zcore_callid::createattachment;
	q.hsession = hsession;
	q.hmessage = hmessage;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_deleteattachment(GUID hsession, uint32_t hmessage, uint32_t attach_id)
{
	zcreq_deleteattachment::view_t q{};
	zcresp_deleteattachment r{};

	q.call_id = zcore_callid::deleteattachment;
	q.hsession = hsession;
	q.hmessage = hmessage;
	q.attach_id = attach_id;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_setpropvals(GUID hsession, uint32_t hobject, const TPROPVAL_ARRAY *ppropvals)
{
	zcreq_setpropvals::view_t q{};
	zcresp_setpropvals r{};

	q.call_id = zcore_callid::setpropvals;
	q.hsession = hsession;
	q.hobject = hobject;
	q.ppropvals = deconst(ppropvals);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_getpropvals(GUID hsession, uint32_t hobject, const std::optional<proptag_cspan> &pproptags, TPROPVAL_ARRAY *propvals)
{
	zcreq_getpropvals::view_t q{};
	zcresp_getpropvals r{};

	q.call_id = zcore_callid::getpropvals;
	q.hsession = hsession;
	q.hobject = hobject;
	q.pproptags = pproptags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*propvals = std::move(r.propvals);
	return r.result;
}

ec_error_t zclient_deletepropvals(GUID hsession, uint32_t hobject, proptag_cspan pproptags)
{
	zcreq_deletepropvals::view_t q{};
	zcresp_deletepropvals r{};

	q.call_id = zcore_callid::deletepropvals;
	q.hsession = hsession;
	q.hobject = hobject;
	q.pproptags = pproptags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_setmessagereadflag(GUID hsession, uint32_t hmessage, uint32_t flags)
{
	zcreq_setmessagereadflag::view_t q{};
	zcresp_setmessagereadflag r{};

	q.call_id = zcore_callid::setmessagereadflag;
	q.hsession = hsession;
	q.hmessage = hmessage;
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_openembedded(GUID hsession, uint32_t hattachment, uint32_t flags, uint32_t *hobject)
{
	zcreq_openembedded::view_t q{};
	zcresp_openembedded r{};

	q.call_id = zcore_callid::openembedded;
	q.hsession = hsession;
	q.hattachment = hattachment;
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_getnamedpropids(GUID hsession, uint32_t hstore, const PROPNAME_ARRAY *ppropnames, PROPID_ARRAY *propids)
{
	zcreq_getnamedpropids::view_t q{};
	zcresp_getnamedpropids r{};

	q.call_id = zcore_callid::getnamedpropids;
	q.hsession = hsession;
	q.hstore = hstore;
	q.ppropnames = deconst(ppropnames);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*propids = std::move(r.propids);
	return r.result;
}

ec_error_t zclient_getpropnames(GUID hsession, uint32_t hstore, const PROPID_ARRAY &ppropids, PROPNAME_ARRAY *propnames)
{
	zcreq_getpropnames::view_t q{};
	zcresp_getpropnames r{};

	q.call_id = zcore_callid::getpropnames;
	q.hsession = hsession;
	q.hstore = hstore;
	q.ppropids = ppropids;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*propnames = std::move(r.propnames);
	return r.result;
}

ec_error_t zclient_copyto(GUID hsession, uint32_t hsrcobject, proptag_cspan pexclude_proptags, uint32_t hdstobject, uint32_t flags)
{
	zcreq_copyto::view_t q{};
	zcresp_copyto r{};

	q.call_id = zcore_callid::copyto;
	q.hsession = hsession;
	q.hsrcobject = hsrcobject;
	q.pexclude_proptags = pexclude_proptags;
	q.hdstobject = hdstobject;
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_savechanges(GUID hsession, uint32_t hobject)
{
	zcreq_savechanges::view_t q{};
	zcresp_savechanges r{};

	q.call_id = zcore_callid::savechanges;
	q.hsession = hsession;
	q.hobject = hobject;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_hierarchysync(GUID hsession, uint32_t hfolder, uint32_t *hobject)
{
	zcreq_hierarchysync::view_t q{};
	zcresp_hierarchysync r{};

	q.call_id = zcore_callid::hierarchysync;
	q.hsession = hsession;
	q.hfolder = hfolder;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_contentsync(GUID hsession, uint32_t hfolder, uint32_t *hobject)
{
	zcreq_contentsync::view_t q{};
	zcresp_contentsync r{};

	q.call_id = zcore_callid::contentsync;
	q.hsession = hsession;
	q.hfolder = hfolder;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_configsync(GUID hsession, uint32_t hctx, uint32_t flags, const BINARY *pstate, /*maybenull*/ const RESTRICTION *prestriction, uint8_t *b_changed, uint32_t *count)
{
	zcreq_configsync::view_t q{};
	zcresp_configsync r{};

	q.call_id = zcore_callid::configsync;
	q.hsession = hsession;
	q.hctx = hctx;
	q.flags = flags;
	q.pstate = deconst(pstate);
	q.prestriction = deconst(prestriction);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*b_changed = std::move(r.b_changed);
	*count = std::move(r.count);
	return r.result;
}

ec_error_t zclient_statesync(GUID hsession, uint32_t hctx, BINARY *state)
{
	zcreq_statesync::view_t q{};
	zcresp_statesync r{};

	q.call_id = zcore_callid::statesync;
	q.hsession = hsession;
	q.hctx = hctx;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*state = std::move(r.state);
	return r.result;
}

ec_error_t zclient_syncmessagechange(GUID hsession, uint32_t hctx, uint8_t *b_new, TPROPVAL_ARRAY *proplist)
{
	zcreq_syncmessagechange::view_t q{};
	zcresp_syncmessagechange r{};

	q.call_id = zcore_callid::syncmessagechange;
	q.hsession = hsession;
	q.hctx = hctx;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*b_new = std::move(r.b_new);
	*proplist = std::move(r.proplist);
	return r.result;
}

ec_error_t zclient_syncfolderchange(GUID hsession, uint32_t hctx, TPROPVAL_ARRAY *proplist)
{
	zcreq_syncfolderchange::view_t q{};
	zcresp_syncfolderchange r{};

	q.call_id = zcore_callid::syncfolderchange;
	q.hsession = hsession;
	q.hctx = hctx;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*proplist = std::move(r.proplist);
	return r.result;
}

ec_error_t zclient_syncreadstatechanges(GUID hsession, uint32_t hctx, STATE_ARRAY *states)
{
	zcreq_syncreadstatechanges::view_t q{};
	zcresp_syncreadstatechanges r{};

	q.call_id = zcore_callid::syncreadstatechanges;
	q.hsession = hsession;
	q.hctx = hctx;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*states = std::move(r.states);
	return r.result;
}

ec_error_t zclient_syncdeletions(GUID hsession, uint32_t hctx, uint32_t flags, BINARY_ARRAY *bins)
{
	zcreq_syncdeletions::view_t q{};
	zcresp_syncdeletions r{};

	q.call_id = zcore_callid::syncdeletions;
	q.hsession = hsession;
	q.hctx = hctx;
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*bins = std::move(r.bins);
	return r.result;
}

ec_error_t zclient_hierarchyimport(GUID hsession, uint32_t hfolder, uint32_t *hobject)
{
	zcreq_hierarchyimport::view_t q{};
	zcresp_hierarchyimport r{};

	q.call_id = zcore_callid::hierarchyimport;
	q.hsession = hsession;
	q.hfolder = hfolder;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_contentimport(GUID hsession, uint32_t hfolder, uint32_t *hobject)
{
	zcreq_contentimport::view_t q{};
	zcresp_contentimport r{};

	q.call_id = zcore_callid::contentimport;
	q.hsession = hsession;
	q.hfolder = hfolder;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_configimport(GUID hsession, uint32_t hctx, uint8_t sync_type, const BINARY *pstate)
{
	zcreq_configimport::view_t q{};
	zcresp_configimport r{};

	q.call_id = zcore_callid::configimport;
	q.hsession = hsession;
	q.hctx = hctx;
	q.sync_type = sync_type;
	q.pstate = deconst(pstate);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_stateimport(GUID hsession, uint32_t hctx, BINARY *state)
{
	zcreq_stateimport::view_t q{};
	zcresp_stateimport r{};

	q.call_id = zcore_callid::stateimport;
	q.hsession = hsession;
	q.hctx = hctx;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*state = std::move(r.state);
	return r.result;
}

ec_error_t zclient_importmessage(GUID hsession, uint32_t hctx, uint32_t flags, const TPROPVAL_ARRAY *pproplist, uint32_t *hobject)
{
	zcreq_importmessage::view_t q{};
	zcresp_importmessage r{};

	q.call_id = zcore_callid::importmessage;
	q.hsession = hsession;
	q.hctx = hctx;
	q.flags = flags;
	q.pproplist = deconst(pproplist);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hobject = std::move(r.hobject);
	return r.result;
}

ec_error_t zclient_importfolder(GUID hsession, uint32_t hctx, const TPROPVAL_ARRAY *pproplist)
{
	zcreq_importfolder::view_t q{};
	zcresp_importfolder r{};

	q.call_id = zcore_callid::importfolder;
	q.hsession = hsession;
	q.hctx = hctx;
	q.pproplist = deconst(pproplist);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_importdeletion(GUID hsession, uint32_t hctx, uint32_t flags, const BINARY_ARRAY *pbins)
{
	zcreq_importdeletion::view_t q{};
	zcresp_importdeletion r{};

	q.call_id = zcore_callid::importdeletion;
	q.hsession = hsession;
	q.hctx = hctx;
	q.flags = flags;
	q.pbins = deconst(pbins);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_importreadstates(GUID hsession, uint32_t hctx, const STATE_ARRAY *pstates)
{
	zcreq_importreadstates::view_t q{};
	zcresp_importreadstates r{};

	q.call_id = zcore_callid::importreadstates;
	q.hsession = hsession;
	q.hctx = hctx;
	q.pstates = deconst(pstates);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_getsearchcriteria(GUID hsession, uint32_t hfolder, BINARY_ARRAY *folder_array, /*mayoutnull*/ RESTRICTION **prestriction, uint32_t *search_stat)
{
	zcreq_getsearchcriteria::view_t q{};
	zcresp_getsearchcriteria r{};

	q.call_id = zcore_callid::getsearchcriteria;
	q.hsession = hsession;
	q.hfolder = hfolder;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*folder_array = std::move(r.folder_array);
	*prestriction = std::move(r.prestriction);
	*search_stat = std::move(r.search_stat);
	return r.result;
}

ec_error_t zclient_setsearchcriteria(GUID hsession, uint32_t hfolder, uint32_t flags, const BINARY_ARRAY *pfolder_array, /*maybenull*/ const RESTRICTION *prestriction)
{
	zcreq_setsearchcriteria::view_t q{};
	zcresp_setsearchcriteria r{};

	q.call_id = zcore_callid::setsearchcriteria;
	q.hsession = hsession;
	q.hfolder = hfolder;
	q.flags = flags;
	q.pfolder_array = deconst(pfolder_array);
	q.prestriction = deconst(prestriction);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_messagetorfc822(GUID hsession, uint32_t hmessage, BINARY *eml_bin)
{
	zcreq_messagetorfc822::view_t q{};
	zcresp_messagetorfc822 r{};

	q.call_id = zcore_callid::messagetorfc822;
	q.hsession = hsession;
	q.hmessage = hmessage;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*eml_bin = std::move(r.eml_bin);
	return r.result;
}

ec_error_t zclient_rfc822tomessage(GUID hsession, uint32_t hmessage, uint32_t mxf_flags, const BINARY *peml_bin)
{
	zcreq_rfc822tomessage::view_t q{};
	zcresp_rfc822tomessage r{};

	q.call_id = zcore_callid::rfc822tomessage;
	q.hsession = hsession;
	q.hmessage = hmessage;
	q.mxf_flags = mxf_flags;
	q.peml_bin = deconst(peml_bin);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_messagetoical(GUID hsession, uint32_t hmessage, BINARY *ical_bin)
{
	zcreq_messagetoical::view_t q{};
	zcresp_messagetoical r{};

	q.call_id = zcore_callid::messagetoical;
	q.hsession = hsession;
	q.hmessage = hmessage;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*ical_bin = std::move(r.ical_bin);
	return r.result;
}

ec_error_t zclient_icaltomessage(GUID hsession, uint32_t hmessage, const BINARY *pical_bin)
{
	zcreq_icaltomessage::view_t q{};
	zcresp_icaltomessage r{};

	q.call_id = zcore_callid::icaltomessage;
	q.hsession = hsession;
	q.hmessage = hmessage;
	q.pical_bin = deconst(pical_bin);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_messagetovcf(GUID hsession, uint32_t hmessage, BINARY *vcf_bin)
{
	zcreq_messagetovcf::view_t q{};
	zcresp_messagetovcf r{};

	q.call_id = zcore_callid::messagetovcf;
	q.hsession = hsession;
	q.hmessage = hmessage;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*vcf_bin = std::move(r.vcf_bin);
	return r.result;
}

ec_error_t zclient_vcftomessage(GUID hsession, uint32_t hmessage, const BINARY *pvcf_bin)
{
	zcreq_vcftomessage::view_t q{};
	zcresp_vcftomessage r{};

	q.call_id = zcore_callid::vcftomessage;
	q.hsession = hsession;
	q.hmessage = hmessage;
	q.pvcf_bin = deconst(pvcf_bin);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_setpasswd(const char *username, const char *passwd, const char *new_passwd)
{
	zcreq_setpasswd::view_t q{};
	zcresp_setpasswd r{};

	q.call_id = zcore_callid::setpasswd;
	q.username = deconst(username);
	q.passwd = deconst(passwd);
	q.new_passwd = deconst(new_passwd);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_linkmessage(GUID hsession, BINARY search_entryid, BINARY message_entryid)
{
	zcreq_linkmessage::view_t q{};
	zcresp_linkmessage r{};

	q.call_id = zcore_callid::linkmessage;
	q.hsession = hsession;
	q.search_entryid = search_entryid;
	q.message_entryid = message_entryid;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_checksession(GUID hsession)
{
	zcreq_checksession::view_t q{};
	zcresp_checksession r{};

	q.call_id = zcore_callid::checksession;
	q.hsession = hsession;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	return r.result;
}

ec_error_t zclient_imtomessage2(GUID session, uint32_t folder, uint32_t data_type, const char *im_data, LONG_ARRAY *msg_handles)
{
	zcreq_imtomessage2::view_t q{};
	zcresp_imtomessage2 r{};

	q.call_id = zcore_callid::imtomessage2;
	q.session = session;
	q.folder = folder;
	q.data_type = data_type;
	q.im_data = deconst(im_data);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*msg_handles = std::move(r.msg_handles);
	return r.result;
}

ec_error_t zclient_essdn_to_username(const char *essdn, char **username)
{
	zcreq_essdn_to_username::view_t q{};
	zcresp_essdn_to_username r{};

	q.call_id = zcore_callid::essdn_to_username;
	q.essdn = deconst(essdn);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*username = std::move(r.username);
	return r.result;
}

ec_error_t zclient_logon_token(const char *token, const char *rhost, GUID *hsession)
{
	zcreq_logon_token::view_t q{};
	zcresp_logon_token r{};

	q.call_id = zcore_callid::logon_token;
	q.token = deconst(token);
	q.rhost = deconst(rhost);
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hsession = std::move(r.hsession);
	return r.result;
}

ec_error_t zclient_getuserfreebusy(GUID hsession, BINARY entryid, time_t starttime, time_t endtime, std::vector<freebusy_event> *fb_events)
{
	zcreq_getuserfreebusy::view_t q{};
	zcresp_getuserfreebusy r{};

	q.call_id = zcore_callid::getuserfreebusy;
	q.hsession = hsession;
	q.entryid = entryid;
	q.starttime = starttime;
	q.endtime = endtime;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*fb_events = std::move(r.fb_events);
	return r.result;
}

ec_error_t zclient_getuserfreebusyical(GUID hsession, BINARY entryid, time_t starttime, time_t endtime, BINARY *ical_bin)
{
	zcreq_getuserfreebusyical::view_t q{};
	zcresp_getuserfreebusyical r{};

	q.call_id = zcore_callid::getuserfreebusyical;
	q.hsession = hsession;
	q.entryid = entryid;
	q.starttime = starttime;
	q.endtime = endtime;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*ical_bin = std::move(r.ical_bin);
	return r.result;
}

ec_error_t zclient_logon_np(const char *username, const char *password, const char *rhost, uint32_t flags, GUID *hsession)
{
	zcreq_logon_np::view_t q{};
	zcresp_logon_np r{};

	q.call_id = zcore_callid::logon_np;
	q.username = deconst(username);
	q.password = deconst(password);
	q.rhost = deconst(rhost);
	q.flags = flags;
	if (!zclient_do_rpc(&q, &r))
		return ecRpcFailed;
	if (r.result != ecSuccess)
		return r.result;
	*hsession = std::move(r.hsession);
	return r.result;
}

