Fix a bug in OpenProfile - use mapi_context instead of session for memory allocation pointer and remove session checks
libmapi/simple_mapi.po \
libmapi/freebusy.po \
libmapi/x500.po \
+ libmapi/fxparser.po \
ndr_mapi.po \
gen_ndr/ndr_exchange.po \
gen_ndr/ndr_exchange_c.po \
@echo "Linking $@"
@$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
+###################
+# check_fasttransfer test app.
+###################
+
+check_fasttransfer: bin/check_fasttransfer
+
+check_fasttransfer-install: check_fasttransfer
+ $(INSTALL) -d $(DESTDIR)$(bindir)
+ $(INSTALL) -m 0755 bin/check_fasttransfer $(DESTDIR)$(bindir)
+
+check_fasttransfer-uninstall:
+ rm -f $(DESTDIR)$(bindir)/check_fasttransfer
+
+check_fasttransfer-clean::
+ rm -f bin/check_fasttransfer
+ rm -f testprogs/check_fasttransfer.o
+ rm -f testprogs/check_fasttransfer.gcno
+ rm -f testprogs/check_fasttransfer.gcda
+
+clean:: check_fasttransfer-clean
+
+bin/check_fasttransfer: testprogs/check_fasttransfer.o \
+ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION) \
+ mapiproxy/libmapistore.$(SHLIBEXT).$(PACKAGE_VERSION)
+ @echo "Linking $@"
+ @$(CC) -o $@ $^ $(LIBS) $(LDFLAGS) -lpopt
###################
# python code
# e.g. OPENCHANGE_VERSION_RELEASE_NICKNAME=Nicky Nickname #
# -> "0.7 (Nicky Nickname)" #
#############################################################
-OPENCHANGE_VERSION_RELEASE_NICKNAME=Nomad
+OPENCHANGE_VERSION_RELEASE_NICKNAME=Transporter
#############################################################
# e.g. OPENCHANGE_VERSION_RELEASE_VERSION=0.8.2 #
# -> "0.8.2 (Nicky Nickname)" #
#############################################################
-OPENCHANGE_VERSION_RELEASE_NUMBER=0.10
+OPENCHANGE_VERSION_RELEASE_NUMBER=0.11
# Written by Jelmer Vernooij <jelmer@openchange.org>
AC_PREREQ(2.57)
-AC_INIT(openchange, 0.10, [openchange@openchange.org])
+AC_INIT(openchange, 0.11, [openchange@openchange.org])
AC_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE
AC_DEFINE(_GNU_SOURCE, 1, [Use GNU extensions])
OC_RULE_ADD(mapiprofile, TOOLS)
OC_RULE_ADD(openchangemapidump, TOOLS)
OC_RULE_ADD(schemaIDGUID, TOOLS)
+
+ OC_RULE_ADD(check_fasttransfer, TORTURE)
fi
AC_SUBST(MAPISTORE_TEST)
# ./setup/provision --domain=OPENCHANGE --realm=OPENCHANGE.LOCAL \
--adminpass=0Chas7secret --server-role='domain controller'
-If you need to add a user, run the following command from Samba4
-source directory and setup arguments so it fullfill your needs:
+If you need to add a user, run the following command from Samba4 source
+directory (replacing <username> and <password> with appropriate entries):
+# ./bin/samba-tool newuser <username> <password>
+
+If you are using a Samba4 alpha13 or earlier release, use:
# ./bin/net newuser <username> <password>
typedef [bitmap8bit] bitmap {
SUPPRESS_RECEIPT = 0x01,
CLEAR_READ_FLAG = 0x04,
- MAPI_DEFERRED_ERRORS = 0x08,
GENERATE_RECEIPT_ONLY = 0x10,
CLEAR_RN_PENDING = 0x20,
CLEAR_NRN_PENDING = 0x40
typedef [public,nodiscriminant,flag(NDR_NOALIGN)] union {
[case(AUX_TYPE_PERF_REQUESTID)] AUX_PERF_REQUESTID AUX_PERF_REQUESTID;
- [case(AUX_TYPE_PERF_CLIENTDINFO)] AUX_PERF_CLIENTINFO AUX_PERF_CLIENTINFO;
+ // [case(AUX_TYPE_PERF_CLIENTDINFO)] AUX_PERF_CLIENTINFO AUX_PERF_CLIENTINFO;
[case(AUX_TYPE_PERF_SERVERINFO)] AUX_PERF_SERVERINFO AUX_PERF_SERVERINFO;
[case(AUX_TYPE_PERF_SESSIONINFO)] AUX_PERF_SESSIONINFO AUX_PERF_SESSIONINFO;
[case(AUX_TYPE_PERF_DEFMDB_SUCCESS)] AUX_PERF_DEFMDB_SUCCESS AUX_PERF_DEFMDB_SUCCESS;
typedef [public,nodiscriminant,flag(NDR_NOALIGN)] union {
[case(AUX_TYPE_PERF_REQUESTID)] AUX_PERF_REQUESTID AUX_PERF_REQUESTID;
- [case(AUX_TYPE_PERF_CLIENTDINFO)] AUX_PERF_CLIENTINFO AUX_PERF_CLIENTINFO;
+ // [case(AUX_TYPE_PERF_CLIENTDINFO)] AUX_PERF_CLIENTINFO AUX_PERF_CLIENTINFO;
[case(AUX_TYPE_PERF_SERVERINFO)] AUX_PERF_SERVERINFO AUX_PERF_SERVERINFO;
[case(AUX_TYPE_PERF_SESSIONINFO_2)] AUX_PERF_SESSIONINFO_V2 AUX_PERF_SESSIONINFO_V2; /* V2 specific */
[case(AUX_TYPE_PERF_DEFMDB_SUCCESS)] AUX_PERF_DEFMDB_SUCCESS AUX_PERF_DEFMDB_SUCCESS;
[in,out][range(0x0,0x1008)] uint32 *pcbAuxOut,
[out] uint32 *pulTransTime
);
+
+ /*****************/
+ /* Function 0xc */
+ void EcUnknown0xC();
+
+ /*****************/
+ /* Function 0xd */
+ void EcUnknown0xD();
+
+ /*****************/
+ /* Function 0xe */
+ [public] MAPISTATUS EcDoAsyncConnectEx(
+ [in] policy_handle *handle,
+ [out] policy_handle *asyn_handle
+ );
+
+}
+
+[
+ uuid("5261574a-4572-206e-b268-6b199213b4e4"),
+ pointer_default(unique),
+ endpoint("ncacn_ip_tcp:"),
+ version(0.01)
+] interface exchange_async_emsmdb
+{
+ [public] MAPISTATUS EcDoAsyncWaitEx(
+ [in] policy_handle *async_handle,
+ [in] uint32 ulFlagsIn,
+ [out] uint32 *pulFlagsOut
+ );
}
[
break;
case MAPI_FOLDER_UNICODE:
request.FolderName.lpszW = name;
- size += strlen(name) * 2 + 2;
+ size += get_utf8_utf16_conv_length(name);
break;
}
break;
case MAPI_FOLDER_UNICODE:
request.FolderComment.lpszW = comment;
- size += strlen(comment) * 2 + 2;
+ size += get_utf8_utf16_conv_length(comment);
break;
}
} else {
size += strlen(NewFolderName) + 1;
} else {
request.NewFolderName.lpszW = NewFolderName;
- size += strlen(NewFolderName) * 2 + 2;
+ size += get_utf8_utf16_conv_length(NewFolderName);
}
size += strlen(NewFolderName) + 1;
} else {
request.NewFolderName.lpszW = NewFolderName;
- size += strlen(NewFolderName) * 2 + 2;
+ size += get_utf8_utf16_conv_length(NewFolderName);
}
/* Fill the MAPI_REQ request */
size += sizeof (request.nameid[i].kind.lid);
break;
case MNID_STRING:
- size += strlen(request.nameid[i].kind.lpwstr.Name) * 2 + 2;
+ size += get_utf8_utf16_conv_length(request.nameid[i].kind.lpwstr.Name);
size += sizeof (uint8_t);
break;
default:
* append here property tags that can be fetched with
* ResolveNames but shouldn't be included in ModifyRecipients rows
*/
- request.properties = get_MAPITAGS_SRow(mem_ctx, &SRowSet->aRow[0]);
- count = SRowSet->aRow[0].cValues - 1;
- request.prop_count = MAPITAGS_delete_entries(request.properties, count, 17,
+ request.properties = get_MAPITAGS_SRow(mem_ctx, &SRowSet->aRow[0], &count);
+ request.prop_count = MAPITAGS_delete_entries(request.properties, count, 19,
PR_ENTRYID,
PR_DISPLAY_NAME,
PR_DISPLAY_NAME_UNICODE,
PR_ADDRTYPE_UNICODE,
PR_ADDRTYPE_ERROR,
PR_SEND_INTERNET_ENCODING,
- PR_SEND_INTERNET_ENCODING_ERROR);
+ PR_SEND_INTERNET_ENCODING_ERROR,
+ PR_SEND_RICH_INFO,
+ PR_SEND_RICH_INFO_ERROR);
size += request.prop_count * sizeof(uint32_t);
request.cValues = SRowSet->cRows;
size += sizeof(uint16_t);
break;
case (0x208):
RecipientRow->EmailAddress.lpszW = (const char *) find_SPropValue_data(aRow, PR_SMTP_ADDRESS_UNICODE);
- size += strlen(RecipientRow->EmailAddress.lpszW) * 2 + 2;
+ size += get_utf8_utf16_conv_length(RecipientRow->EmailAddress.lpszW);
break;
default:
break;
break;
case (0x210):
RecipientRow->DisplayName.lpszW = (const char *) find_SPropValue_data(aRow, PR_DISPLAY_NAME_UNICODE);
- size += strlen(RecipientRow->DisplayName.lpszW) * 2 + 2;
+ size += get_utf8_utf16_conv_length(RecipientRow->DisplayName.lpszW);
break;
default:
break;
break;
case (0x220):
RecipientRow->TransmittableDisplayName.lpszW = (const char *) find_SPropValue_data(aRow, PR_TRANSMITTABLE_DISPLAY_NAME_UNICODE);
- size += strlen(RecipientRow->TransmittableDisplayName.lpszW) * 2 + 2;
+ size += get_utf8_utf16_conv_length(RecipientRow->TransmittableDisplayName.lpszW);
break;
default:
break;
break;
case (0x600):
RecipientRow->SimpleDisplayName.lpszW = (const char *) find_SPropValue_data(aRow, PR_7BIT_DISPLAY_NAME_UNICODE);
- size += strlen(RecipientRow->SimpleDisplayName.lpszW) * 2 + 2;
+ size += get_utf8_utf16_conv_length(RecipientRow->SimpleDisplayName.lpszW);
break;
default:
break;
/**
\details Notify the store of a new message to be processed
+ \param obj_store the store that the message is in (logon object)
\param obj_folder the folder that the message is in
\param obj_msg the message to be processed
\param MessageClass the message class of the message to be processed
\sa GetReceiveFolder, GetReceiveFolderTable
*/
-_PUBLIC_ enum MAPISTATUS TransportNewMail(mapi_object_t *obj_folder, mapi_object_t *obj_msg,
+_PUBLIC_ enum MAPISTATUS TransportNewMail(mapi_object_t *obj_store, mapi_object_t *obj_folder,
+ mapi_object_t *obj_msg,
const char *MessageClass, uint32_t MessageFlags)
{
struct mapi_request *mapi_request;
uint8_t logon_id;
/* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
OPENCHANGE_RETVAL_IF(!obj_msg, MAPI_E_INVALID_PARAMETER, NULL);
OPENCHANGE_RETVAL_IF(!MessageClass, MAPI_E_INVALID_PARAMETER, NULL);
mapi_request->length = size;
mapi_request->mapi_req = mapi_req;
mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
- mapi_request->handles[0] = mapi_object_get_handle(obj_folder);
+ mapi_request->handles[0] = mapi_object_get_handle(obj_store);
status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
enum MAPISTATUS retval;
OPENCHANGE_RETVAL_IF(!mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
- OPENCHANGE_RETVAL_IF(!mapi_ctx->session, MAPI_E_NOT_INITIALIZED, NULL);
OPENCHANGE_RETVAL_IF(!mapi_ctx->ldb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
- mem_ctx = (TALLOC_CTX *) mapi_ctx->session;
+ mem_ctx = (TALLOC_CTX *) mapi_ctx;
/* find the profile in ldb store */
retval = ldb_load_profile(mem_ctx, mapi_ctx->ldb_ctx, profile, profname, password);
0x8c6a1102 PR_EMS_AB_TAGGED_X509_CERT
0x8c6b001e PR_EMS_AB_PERSONAL_TITLE
0x8c6c001e PR_EMS_AB_LANGUAGE_ISO639
-0x8c6d001e PR_EMS_AB_OBJECT_GUID
+0x8c6d0102 PR_EMS_AB_OBJECT_GUID
0x8c8e001e PR_EMS_AB_PHONETIC_GIVEN_NAME
0x8c8f001e PR_EMS_AB_PHONETIC_SURNAME
0x8c90001e PR_EMS_AB_PHONETIC_DEPARTMENT_NAME
mparse "";
mparse "ndr_print.depth = 1;";
mparse "ndr_print.print = ndr_print_debug_helper;";
+ mparse "ndr_print.no_newline = false;";
mparse "ndr_print_MAPISTATUS(&ndr_print, function, mapi_code);";
deindent;
mparse "}";
--- /dev/null
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Brad Hards <bradh@frogmouth.net> 2010.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "libmapi/libmapi.h"
+#include "libmapi/libmapi_private.h"
+#include "libmapi/fxparser.h"
+
+#ifdef ENABLE_ASSERTS
+#include <assert.h>
+#define OC_ASSERT(x) assert(x)
+#else
+#define OC_ASSERT(x)
+#endif
+
+/**
+ \file fxparser.c
+
+ \brief Fast Transfer stream parser
+ */
+
+static bool pull_uint8_t(struct fx_parser_context *parser, uint8_t *val)
+{
+ if ((parser->idx) + 1 > parser->data.length) {
+ val = 0;
+ return false;
+ }
+ *val = parser->data.data[parser->idx];
+ (parser->idx)++;
+ return true;
+}
+
+static bool pull_uint16_t(struct fx_parser_context *parser, uint16_t *val)
+{
+ if ((parser->idx) + 2 > parser->data.length) {
+ val = 0;
+ return false;
+ }
+ *val = parser->data.data[parser->idx];
+ (parser->idx)++;
+ *val += parser->data.data[parser->idx] << 8;
+ (parser->idx)++;
+ return true;
+}
+
+static bool pull_uint32_t(struct fx_parser_context *parser, uint32_t *val)
+{
+ if ((parser->idx) + 4 > parser->data.length) {
+ val = 0;
+ return false;
+ }
+ *val = parser->data.data[parser->idx];
+ (parser->idx)++;
+ *val += parser->data.data[parser->idx] << 8;
+ (parser->idx)++;
+ *val += parser->data.data[parser->idx] << 16;
+ (parser->idx)++;
+ *val += parser->data.data[parser->idx] << 24;
+ (parser->idx)++;
+ return true;
+}
+
+static bool pull_tag(struct fx_parser_context *parser)
+{
+ bool result;
+ result = pull_uint32_t(parser, &(parser->tag));
+ if (!result) {
+ printf("bad pull of tag\n");
+ }
+ return result;
+}
+
+static bool pull_uint8_data(struct fx_parser_context *parser, uint8_t **data_read)
+{
+ for (; parser->offset < parser->length; ++(parser->offset)) {
+ /* printf("parser %i of %i\n", parser->offset, parser->length); */
+ if (!pull_uint8_t(parser, (uint8_t*)&((*data_read)[parser->offset]))) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool pull_int64_t(struct fx_parser_context *parser, int64_t *val)
+{
+ int64_t tmp;
+ if ((parser->idx) + 8 > parser->data.length) {
+ *val = 0;
+ return false;
+ }
+ *val = parser->data.data[parser->idx];
+ (parser->idx)++;
+
+ tmp = parser->data.data[parser->idx];
+ *val += (tmp << 8);
+ (parser->idx)++;
+
+ tmp = parser->data.data[parser->idx];
+ *val += (tmp << 16);
+ (parser->idx)++;
+
+ tmp = parser->data.data[parser->idx];
+ *val += (tmp << 24);
+ (parser->idx)++;
+
+ tmp = parser->data.data[parser->idx];
+ *val += (tmp << 32);
+ (parser->idx)++;
+
+ tmp = parser->data.data[parser->idx];
+ *val += (tmp << 40);
+ (parser->idx)++;
+
+ tmp = parser->data.data[parser->idx];
+ *val += (tmp << 48);
+ (parser->idx)++;
+
+ tmp = parser->data.data[parser->idx];
+ *val += (tmp << 56);
+ (parser->idx)++;
+
+ return true;
+}
+
+static bool pull_double(struct fx_parser_context *parser, double *val)
+{
+ return pull_int64_t(parser, (int64_t *)val);
+}
+
+static bool pull_guid(struct fx_parser_context *parser, struct GUID *guid)
+{
+ int i;
+
+ if ((parser->idx) + 16 > parser->data.length) {
+ GUID_all_zero(guid);
+ return false;
+ }
+ pull_uint32_t(parser, &(guid->time_low));
+ pull_uint16_t(parser, &(guid->time_mid));
+ pull_uint16_t(parser, &(guid->time_hi_and_version));
+ pull_uint8_t(parser, &(guid->clock_seq[0]));
+ pull_uint8_t(parser, &(guid->clock_seq[1]));
+ for (i = 0; i < 6; ++i) {
+ pull_uint8_t(parser, &(guid->node[i]));
+ }
+ return true;
+}
+
+static bool fetch_ucs2_data(struct fx_parser_context *parser, uint32_t numbytes, smb_ucs2_t **data_read)
+{
+ if ((parser->idx) + numbytes > parser->data.length) {
+ // printf("insufficient data in fetch_ucs2_data (%i requested, %zi available)\n", numbytes, (parser->data.length - parser->idx));
+ return false;
+ }
+
+ *data_read = talloc_array(parser->mem_ctx, smb_ucs2_t, numbytes/2);
+ memcpy(*data_read, &(parser->data.data[parser->idx]), numbytes);
+ parser->idx += numbytes;
+ return true;
+}
+
+static bool fetch_ucs2_nullterminated(struct fx_parser_context *parser, smb_ucs2_t **data_read)
+{
+ uint32_t idx_local = parser->idx;
+ while (idx_local < parser->data.length -1) {
+ smb_ucs2_t val = 0x0000;
+ val += parser->data.data[idx_local];
+ idx_local++;
+ val += parser->data.data[idx_local] << 8;
+ idx_local++;
+ if (val == 0x0000) {
+ break;
+ }
+ }
+ return fetch_ucs2_data(parser, idx_local-(parser->idx), data_read);
+}
+
+/*
+ pull a property value from the blob, starting at position idx
+*/
+static bool fetch_property_value(struct fx_parser_context *parser, DATA_BLOB *buf, struct SPropValue *prop, uint32_t *len)
+{
+ switch(prop->ulPropTag & 0xFFFF) {
+ case PT_SHORT:
+ {
+ pull_uint16_t(parser, &(prop->value.i));
+ break;
+ }
+ case PT_LONG:
+ {
+ pull_uint32_t(parser, &(prop->value.l));
+ break;
+ }
+ case PT_DOUBLE:
+ {
+ pull_double(parser, (double *)&(prop->value.dbl));
+ break;
+ }
+ case PT_BOOLEAN:
+ {
+ pull_uint8_t(parser, &(prop->value.b));
+ /* special case for fast transfer, 2 bytes instead of one */
+ (parser->idx)++;
+ break;
+ }
+ case PT_I8:
+ {
+ int64_t val;
+ pull_int64_t(parser, &(val));
+ prop->value.d = val;
+ break;
+ }
+ case PT_STRING8:
+ {
+ char *ptr = 0;
+ if (parser->length == 0) {
+ pull_uint32_t(parser, &(parser->length));
+ parser->offset = 0;
+ prop->value.lpszA = talloc_array(parser->mem_ctx, char, parser->length + 1);
+ }
+ for (; parser->offset < parser->length; ++(parser->offset)) {
+ if (!pull_uint8_t(parser, (uint8_t*)&(prop->value.lpszA[parser->offset]))) {
+ return false;
+ }
+ }
+ ptr = (char*)prop->value.lpszA;
+ ptr += parser->length;
+ *ptr = '\0';
+ break;
+ }
+ case PT_UNICODE:
+ {
+ /* TODO: rethink this to handle split buffers */
+ smb_ucs2_t *ucs2_data = NULL;
+ if (parser->length == 0) {
+ pull_uint32_t(parser, &(parser->length));
+ ucs2_data = talloc_array(parser->mem_ctx, smb_ucs2_t, parser->length/2);
+ parser->offset = 0;
+ }
+ char *utf8_data = NULL;
+ size_t utf8_len;
+ if (!fetch_ucs2_data(parser, parser->length, &ucs2_data)) {
+ return false;
+ }
+ pull_ucs2_talloc(parser->mem_ctx, &utf8_data, ucs2_data, &utf8_len);
+ prop->value.lpszW = utf8_data;
+ break;
+ }
+ case PT_SYSTIME:
+ {
+ struct FILETIME filetime = {0,0};
+ pull_uint32_t(parser, &(filetime.dwLowDateTime));
+ pull_uint32_t(parser, &(filetime.dwHighDateTime));
+ prop->value.ft = filetime;
+ break;
+ }
+ case PT_CLSID:
+ {
+ int i = 0;
+ prop->value.lpguid = talloc_zero(parser->mem_ctx, struct FlatUID_r);
+ for (i = 0; i < 16; ++i) {
+ pull_uint8_t(parser, &(prop->value.lpguid->ab[i]));
+ }
+ break;
+ }
+ case PT_SVREID:
+ case PT_BINARY:
+ {
+ if (parser->length == 0) {
+ pull_uint32_t(parser, &(prop->value.bin.cb));
+ parser->length = prop->value.bin.cb;
+ prop->value.bin.lpb = talloc_array(parser->mem_ctx, uint8_t, parser->length + 1);
+ parser->offset = 0;
+ }
+ if (!pull_uint8_data(parser, &(prop->value.bin.lpb))) {
+ return false;
+ }
+ break;
+ }
+ case PT_OBJECT:
+ {
+ pull_uint32_t(parser, &(prop->value.object));
+ break;
+ }
+ case PT_MV_BINARY:
+ {
+ /* TODO: handle partial count / length */
+ uint32_t i;
+ pull_uint32_t(parser, &(prop->value.MVbin.cValues));
+ prop->value.MVbin.lpbin = talloc_array(parser->mem_ctx, struct Binary_r, prop->value.MVbin.cValues);
+ for (i = 0; i < prop->value.MVbin.cValues; i++) {
+ pull_uint32_t(parser, &(prop->value.MVbin.lpbin[i].cb));
+ parser->length = prop->value.MVbin.lpbin[i].cb;
+ prop->value.MVbin.lpbin[i].lpb = talloc_array(parser->mem_ctx, uint8_t, parser->length + 1);
+ parser->offset = 0;
+ if (!pull_uint8_data(parser, &(prop->value.MVbin.lpbin[i].lpb))) {
+ return false;
+ }
+ }
+ break;
+ }
+ default:
+ printf("unhandled conversion case in fetch_property_value(): 0x%x\n", (prop->ulPropTag & 0xFFFF));
+ OPENCHANGE_ASSERT();
+ }
+ return true;
+}
+
+static void pull_named_property(struct fx_parser_context *parser)
+{
+ uint8_t type = 0;
+ pull_guid(parser, &(parser->namedprop.lpguid));
+ /* printf("guid : %s\n", GUID_string(parser->mem_ctx, &(parser->namedprop.lpguid))); */
+ pull_uint8_t(parser, &type);
+ if (type == 0) {
+ parser->namedprop.ulKind = MNID_ID;
+ pull_uint32_t(parser, &(parser->namedprop.kind.lid));
+ /* printf("LID dispid: 0x%08x\n", parser->namedprop.kind.lid); */
+ } else if (type == 1) {
+ smb_ucs2_t *ucs2_data = NULL;
+ size_t utf8_len;
+ parser->namedprop.ulKind = MNID_STRING;
+ fetch_ucs2_nullterminated(parser, &ucs2_data);
+ pull_ucs2_talloc(parser->mem_ctx, (char**)&(parser->namedprop.kind.lpwstr.Name), ucs2_data, &(utf8_len));
+ parser->namedprop.kind.lpwstr.NameSize = utf8_len;
+ /* printf("named: %s\n", parser->namedprop.kind.lpwstr.Name); */
+ } else {
+ printf("unknown named property kind: 0x%02x\n", parser->namedprop.ulKind);
+ OPENCHANGE_ASSERT();
+ }
+ if (parser->op_namedprop) {
+ parser->op_namedprop(parser->lpProp.ulPropTag, parser->namedprop, parser->priv);
+ }
+}
+
+/**
+ \details set a callback function for marker output
+*/
+_PUBLIC_ void fxparser_set_marker_callback(struct fx_parser_context *parser, fxparser_marker_callback_t marker_callback)
+{
+ parser->op_marker = marker_callback;
+}
+
+/**
+ \details set a callback function for delete properties output
+*/
+_PUBLIC_ void fxparser_set_delprop_callback(struct fx_parser_context *parser, fxparser_delprop_callback_t delprop_callback)
+{
+ parser->op_delprop = delprop_callback;
+}
+
+/**
+ \details set a callback function for named properties output
+*/
+_PUBLIC_ void fxparser_set_namedprop_callback(struct fx_parser_context *parser, fxparser_namedprop_callback_t namedprop_callback)
+{
+ parser->op_namedprop = namedprop_callback;
+}
+
+/**
+ \details set a callback function for property output
+*/
+_PUBLIC_ void fxparser_set_property_callback(struct fx_parser_context *parser, fxparser_property_callback_t property_callback)
+{
+ parser->op_property = property_callback;
+}
+
+/**
+ \details initialise a fast transfer parser
+*/
+_PUBLIC_ struct fx_parser_context* fxparser_init(TALLOC_CTX *mem_ctx, void *priv)
+{
+ struct fx_parser_context *parser = talloc_zero(mem_ctx, struct fx_parser_context);
+
+ parser->mem_ctx = mem_ctx;
+ parser->data = data_blob_talloc_named(parser->mem_ctx, NULL, 0, "fast transfer parser");
+ parser->state = ParserState_Entry;
+ parser->idx = 0;
+ parser->lpProp.ulPropTag = 0;
+ parser->lpProp.dwAlignPad = 0;
+ parser->lpProp.value.l = 0;
+ parser->length = 0;
+ parser->priv = priv;
+
+ return parser;
+}
+
+/**
+ \details parse a fast transfer buffer
+*/
+_PUBLIC_ void fxparser_parse(struct fx_parser_context *parser, DATA_BLOB *fxbuf)
+{
+ data_blob_append(parser->mem_ctx, &(parser->data), fxbuf->data, fxbuf->length);
+ parser->enough_data = true;
+ while((parser->idx < parser->data.length) && parser->enough_data) {
+ switch(parser->state) {
+ case ParserState_Entry:
+ {
+ pull_tag(parser);
+ /* printf("tag: 0x%08x\n", parser->tag); */
+ parser->state = ParserState_HaveTag;
+ break;
+ }
+ case ParserState_HaveTag:
+ {
+ switch (parser->tag) {
+ case PR_START_TOP_FLD:
+ case PR_START_SUB_FLD:
+ case PR_END_FOLDER:
+ case PR_START_MESSAGE:
+ case PR_START_FAI_MSG:
+ case PR_END_MESSAGE:
+ case PR_START_RECIP:
+ case PR_END_RECIP:
+ case PR_NEW_ATTACH:
+ case PR_END_ATTACH:
+ case PR_START_EMBED:
+ case PR_END_EMBED:
+ if (parser->op_marker) {
+ parser->op_marker(parser->tag, parser->priv);
+ }
+ parser->state = ParserState_Entry;
+ break;
+ case PR_FX_DEL_PROP:
+ {
+ uint32_t tag;
+ if (pull_uint32_t(parser, &tag)) {
+ if (parser->op_delprop) {
+ parser->op_delprop(tag, parser->priv);
+ }
+ parser->state = ParserState_Entry;
+ } else {
+ parser->enough_data = false;
+ }
+ break;
+ }
+ default:
+ {
+ /* standard property thing */
+ parser->lpProp.ulPropTag = parser->tag;
+ parser->lpProp.dwAlignPad = 0;
+ if ((parser->lpProp.ulPropTag >> 16) & 0x8000) {
+ /* this is a named property */
+ // printf("tag: 0x%08x\n", parser->tag);
+ // TODO: this should probably be a separate parser state
+ // TODO: this needs to return the named property
+ pull_named_property(parser);
+ }
+ parser->state = ParserState_HavePropTag;
+ }
+ }
+ break;
+ }
+ case ParserState_HavePropTag:
+ {
+ if (fetch_property_value(parser, &(parser->data), &(parser->lpProp), &(parser->length))) {
+ // printf("position %i of %zi\n", parser->idx, parser->data.length);
+ if (parser->op_property) {
+ parser->op_property(parser->lpProp, parser->priv);
+ }
+ parser->state = ParserState_Entry;
+ parser->length = 0;
+ } else {
+ parser->enough_data = false;
+ }
+ break;
+ }
+ }
+ }
+ {
+ // Remove the part of the buffer that we've used
+ uint32_t remainder_len = parser->data.length - parser->idx;
+ DATA_BLOB remainder = data_blob_talloc_named(parser->mem_ctx, &(parser->data.data[parser->idx]), remainder_len, "fast transfer parser");
+ data_blob_free(&(parser->data));
+ parser->data = remainder;
+ parser->idx = 0;
+ }
+}
--- /dev/null
+/*
+ OpenChange MAPI implementation.
+
+ Copyright (C) Brad Hards <bradh@openchange.org> 2010
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LIBMAPI_FXPARSER_H__
+#define __LIBMAPI_FXPARSER_H__
+
+/* This header is private to the parser. If you use this directly, you may suffer API or ABI breakage.
+
+ We mean it.
+*/
+
+enum fx_parser_state { ParserState_Entry, ParserState_HaveTag, ParserState_HavePropTag };
+
+struct fx_parser_context {
+ TALLOC_CTX *mem_ctx;
+ DATA_BLOB data; /* the data we have (so far) to parse */
+ uint32_t idx; /* where we are up to in the data blob */
+ enum fx_parser_state state;
+ struct SPropValue lpProp; /* the current property tag and value we are parsing */
+ struct MAPINAMEID namedprop; /* the current named property we are parsing */
+ uint32_t length; /* the total length of the property we're parsing (for variable length props such as strings */
+ uint32_t offset; /* the current offset in the variable length property (how much of the length do we already have */
+ bool enough_data;
+ uint32_t tag;
+ void *priv;
+
+ /* callbacks for parser actions */
+ enum MAPISTATUS (*op_marker)(uint32_t, void *);
+ enum MAPISTATUS (*op_delprop)(uint32_t, void *);
+ enum MAPISTATUS (*op_namedprop)(uint32_t, struct MAPINAMEID, void *);
+ enum MAPISTATUS (*op_property)(struct SPropValue, void *);
+};
+
+#endif
enum MAPISTATUS GetOwningServers(mapi_object_t *, mapi_object_t *, uint16_t *, uint16_t *, char **);
enum MAPISTATUS GetStoreState(mapi_object_t *, uint32_t *);
enum MAPISTATUS GetOutboxFolder(mapi_object_t *, mapi_id_t *);
-enum MAPISTATUS TransportNewMail(mapi_object_t *, mapi_object_t *,const char *, uint32_t);
+enum MAPISTATUS TransportNewMail(mapi_object_t *, mapi_object_t *, mapi_object_t *,const char *, uint32_t);
/* The following public definitions come from libmapi/IStoreFolder.c */
enum MAPISTATUS OpenMessage(mapi_object_t *, mapi_id_t, mapi_id_t, mapi_object_t *, uint8_t);
/* The following public definitions come from libmapi/socket/netif.c */
int get_interfaces(struct iface_struct *, int);
+/* The following public definitions come from libmapi/fxparser.c */
+struct fx_parser_context;
+typedef enum MAPISTATUS (*fxparser_marker_callback_t)(uint32_t, void *);
+typedef enum MAPISTATUS (*fxparser_delprop_callback_t)(uint32_t, void *);
+typedef enum MAPISTATUS (*fxparser_namedprop_callback_t)(uint32_t, struct MAPINAMEID, void *);
+typedef enum MAPISTATUS (*fxparser_property_callback_t)(struct SPropValue, void *);
+
+struct fx_parser_context *fxparser_init(TALLOC_CTX *, void *);
+void fxparser_set_marker_callback(struct fx_parser_context *, fxparser_marker_callback_t);
+void fxparser_set_delprop_callback(struct fx_parser_context *, fxparser_delprop_callback_t);
+void fxparser_set_namedprop_callback(struct fx_parser_context *, fxparser_namedprop_callback_t);
+void fxparser_set_property_callback(struct fx_parser_context *, fxparser_property_callback_t);
+void fxparser_parse(struct fx_parser_context *, DATA_BLOB *);
+
__END_DECLS
#undef _PRINTF_ATTRIBUTE
enum MAPISTATUS mapi_object_bookmark_find(mapi_object_t *, uint32_t,struct SBinary_short *);
/* The following private definitions come from libmapi/property.c */
-enum MAPITAGS *get_MAPITAGS_SRow(TALLOC_CTX *, struct SRow *);
+enum MAPITAGS *get_MAPITAGS_SRow(TALLOC_CTX *, struct SRow *, uint32_t *);
uint32_t MAPITAGS_delete_entries(enum MAPITAGS *, uint32_t, uint32_t, ...);
size_t get_utf8_utf16_conv_length(const char *);
break;
case MNID_STRING:
mapi_nameid->nameid[count].kind.lpwstr.Name = mapi_nameid_tags[i].Name;
- mapi_nameid->nameid[count].kind.lpwstr.NameSize = strlen(mapi_nameid_tags[i].Name) * 2 + 2;
+ mapi_nameid->nameid[count].kind.lpwstr.NameSize = get_utf8_utf16_conv_length(mapi_nameid_tags[i].Name);
break;
}
mapi_nameid->count++;
break;
case MNID_STRING:
mapi_nameid->nameid[count].kind.lpwstr.Name = mapi_nameid_tags[i].Name;
- mapi_nameid->nameid[count].kind.lpwstr.NameSize = strlen(mapi_nameid_tags[i].Name) * 2 + 2;
+ mapi_nameid->nameid[count].kind.lpwstr.NameSize = get_utf8_utf16_conv_length(mapi_nameid_tags[i].Name);
break;
}
mapi_nameid->count++;
break;
case MNID_STRING:
mapi_nameid->nameid[count].kind.lpwstr.Name = mapi_nameid_tags[i].Name;
- mapi_nameid->nameid[count].kind.lpwstr.NameSize = strlen(mapi_nameid_tags[i].Name) * 2 + 2;
+ mapi_nameid->nameid[count].kind.lpwstr.NameSize = get_utf8_utf16_conv_length(mapi_nameid_tags[i].Name);
break;
}
mapi_nameid->count++;
mapi_nameid->nameid[count].ulKind = MNID_STRING;
GUID_from_string(OLEGUID, &(mapi_nameid->nameid[count].lpguid));
mapi_nameid->nameid[count].kind.lpwstr.Name = Name;
- mapi_nameid->nameid[count].kind.lpwstr.NameSize = strlen(Name) * 2 + 2;
+ mapi_nameid->nameid[count].kind.lpwstr.NameSize = get_utf8_utf16_conv_length(Name);
mapi_nameid->count++;
return MAPI_E_SUCCESS;
break;
case MNID_STRING:
mapi_nameid->nameid[count].kind.lpwstr.Name = mapi_nameid_tags[i].Name;
- mapi_nameid->nameid[count].kind.lpwstr.NameSize = strlen(mapi_nameid_tags[i].Name) * 2 + 2;
+ mapi_nameid->nameid[count].kind.lpwstr.NameSize = get_utf8_utf16_conv_length(mapi_nameid_tags[i].Name);
break;
}
mapi_nameid->count++;
#define MAPI_CREATE 0x2
/* SaveChanges flags */
-#define KEEP_OPEN_READONLY 0x1
-#define KEEP_OPEN_READWRITE 0x2
-#define FORCE_SAVE 0x4
-/* #define MAPI_DEFERRED_ERRORS 0x8 (already defined in the IDL */
+#define KEEP_OPEN_READONLY 0x09
+#define KEEP_OPEN_READWRITE 0x0A
+#define FORCE_SAVE 0x0C
/* OpenMessage flags */
#define MAPI_MODIFY 0x1
data = get_SPropValue_data(&lpProp);
printf("%s%s: 0x%x\n", sep?sep:"", proptag, (*(const uint16_t *)data));
break;
+ case PT_LONG:
+ case PT_OBJECT:
+ data = get_SPropValue_data(&lpProp);
+ printf("%s%s: %u\n", sep?sep:"", proptag, (*(const uint32_t *)data));
+ break;
+ case PT_DOUBLE:
+ data = get_SPropValue_data(&lpProp);
+ printf("%s%s: %f\n", sep?sep:"", proptag, (*(const double *)data));
+ break;
case PT_BOOLEAN:
data = get_SPropValue_data(&lpProp);
printf("%s%s: 0x%x\n", sep?sep:"", proptag, (*(const uint8_t *)data));
case PT_STRING8:
case PT_UNICODE:
data = get_SPropValue_data(&lpProp);
- printf("%s%s: %s\n", sep?sep:"", proptag, (data && (*(const uint32_t *)data) != MAPI_E_NOT_FOUND) ? (const char *)data : "NULL");
+ printf("%s%s:", sep?sep:"", proptag);
+ if (data && ((*(const uint16_t *)data) == 0x0000)) {
+ /* its an empty string */
+ printf("\n");
+ } else if (data && ((*(const uint32_t *)data) != MAPI_E_NOT_FOUND)) {
+ /* its a valid string */
+ printf(" %s\n", (const char *)data);
+ } else {
+ /* its a null or otherwise problematic string */
+ printf(" (NULL)\n");
+ }
break;
case PT_SYSTIME:
mapidump_date_SPropValue(lpProp, proptag, sep);
data = get_SPropValue_data(&lpProp);
printf("%s%s_ERROR: 0x%.8x\n", sep?sep:"", proptag, (*(const uint32_t *)data));
break;
- case PT_LONG:
- data = get_SPropValue_data(&lpProp);
- printf("%s%s: %u\n", sep?sep:"", proptag, (*(const uint32_t *)data));
+ case PT_CLSID:
+ {
+ const uint8_t *ab = get_SPropValue_data(&lpProp);
+ printf("%s%s: ", sep?sep:"", proptag);
+ for (i = 0; i < 15; ++i) {
+ printf("%02x ", ab[i]);
+ }
+ printf("%x\n", ab[15]);
break;
+ }
+ case PT_SVREID:
case PT_BINARY:
data = get_SPropValue_data(&lpProp);
- printf("%s%s:\n", sep?sep:"", proptag);
- dump_data(0, ((const struct Binary_r *)data)->lpb, ((const struct Binary_r *)data)->cb);
+ if (data) {
+ printf("%s%s:\n", sep?sep:"", proptag);
+ dump_data(0, ((const struct Binary_r *)data)->lpb, ((const struct Binary_r *)data)->cb);
+ } else {
+ printf("%s%s: (NULL)\n", sep?sep:"", proptag);
+ }
break;
case PT_MV_LONG:
LongArray_r = (const struct LongArray_r *) get_SPropValue_data(&lpProp);
}
}
}
-
}
}
Create a MAPITAGS array from a SRow entry
*/
-enum MAPITAGS *get_MAPITAGS_SRow(TALLOC_CTX *mem_ctx, struct SRow *aRow)
+enum MAPITAGS *get_MAPITAGS_SRow(TALLOC_CTX *mem_ctx,
+ struct SRow *aRow,
+ uint32_t *actual_count)
{
enum MAPITAGS *mapitags;
uint32_t count, idx;
}
}
mapitags[idx] = 0;
+ *actual_count = idx;
+
return mapitags;
}
return (const void *)lpProps->value.lpguid;
case PT_BINARY:
return (const void *)&lpProps->value.bin;
+ case PT_OBJECT:
+ return (const void *)&lpProps->value.object;
case PT_MV_SHORT:
return (const void *)(struct ShortArray_r *)&lpProps->value.MVi;
case PT_MV_LONG:
case PT_STRING8:
return strlen(lpProp->value.lpszA) + 1;
case PT_UNICODE:
- return strlen(lpProp->value.lpszW) * 2 + 2;
+ return get_utf8_utf16_conv_length(lpProp->value.lpszW);
case PT_SYSTIME:
return sizeof (struct FILETIME);
case PT_BINARY:
case PT_UNICODE:
mapi_sprop->value.lpszW = sprop->value.lpszW;
if (!mapi_sprop->value.lpszW) return 0;
- return get_utf8_utf16_conv_length(mapi_sprop->value.lpszW);
+ return (get_utf8_utf16_conv_length(mapi_sprop->value.lpszW));
case PT_SYSTIME:
mapi_sprop->value.ft.dwLowDateTime = sprop->value.ft.dwLowDateTime;
mapi_sprop->value.ft.dwHighDateTime = sprop->value.ft.dwHighDateTime;
case PT_UNICODE:
sprop->value.lpszW = mapi_sprop->value.lpszW;
if (!sprop->value.lpszW) return 0;
- return (strlen(mapi_sprop->value.lpszW) * 2 + 2);
+ return (get_utf8_utf16_conv_length(mapi_sprop->value.lpszW));
case PT_SYSTIME:
sprop->value.ft.dwLowDateTime = mapi_sprop->value.ft.dwLowDateTime;
sprop->value.ft.dwHighDateTime = mapi_sprop->value.ft.dwHighDateTime;
/**
\details add a SPropValue structure to a SRow array
- \param aRow pointer to the SRow array where SPropBalue should be
+ \param aRow pointer to the SRow array where spropvalue should be
appended
\param spropvalue reference to the SPropValue structure to add to
aRow
#ifndef __LEX_H_
#define __LEX_H_
-void error_message (struct ocpf_context *, const char *, ...) __attribute__ ((format (printf, 2, 3)));
+void ocpf_error_message (struct ocpf_context *, const char *, ...) __attribute__ ((format (printf, 2, 3)));
extern int error_flag;
PT_UNICODE { return kw_PT_UNICODE; }
PT_SHORT { return kw_PT_SHORT; }
PT_LONG { return kw_PT_LONG; }
+PT_DOUBLE { return kw_PT_DOUBLE; }
PT_I8 { return kw_PT_I8; }
PT_SYSTIME { return kw_PT_SYSTIME; }
PT_BOOLEAN { return kw_PT_BOOLEAN; }
}
return BOOLEAN;
}
+F-?[0-9]"."[0-9]+e[-+]?[0-9]+ {
+ struct ocpf_context *ctx = yyextra;
+ char *y = yytext + 1;
+ char *e;
+ yylval->dbl = strtod((const char *)y, &e);
+ if (e == y) {
+ ocpf_error_message(ctx, "malformed constant (%s)", yytext);
+ } else {
+ return DOUBLE;
+ }
+ }
T[0-9]{4}-[0-9]{2}-[0-9]{2}[ ][0-9]{2}\:[0-9]{2}\:[0-9]{2} {
yylval->date = strdup((const char *)yytext + 1);
return SYSTIME;
char *e, *y = yytext;
yylval->i = strtoul((const char *)y, &e, 0);
if (e == y)
- error_message(ctx, "malformed constant (%s)", yytext);
+ ocpf_error_message(ctx, "malformed constant (%s)", yytext);
else
return UINT8;
}
char *e, *y = yytext;
yylval->l = strtoul((const char *)y, &e, 0);
if (e == y)
- error_message(ctx, "malformed constant (%s)", yytext);
+ ocpf_error_message(ctx, "malformed constant (%s)", yytext);
else
return INTEGER;
y = (yytext[0] == 'S') ? yytext + 1 : yytext;
yylval->s = strtoul((const char *)y, &e, 0);
if (e == y)
- error_message(ctx, "malformed constant (%s)", yytext);
+ ocpf_error_message(ctx, "malformed constant (%s)", yytext);
else
return SHORT;
}
y = (yytext[0] == 'L') ? yytext + 1 : yytext;
yylval->l = strtoul((const char *)y, &e, 0);
if(e == y)
- error_message(ctx, "malformed constant (%s)", yytext);
+ ocpf_error_message(ctx, "malformed constant (%s)", yytext);
else
return INTEGER;
}
char *e, *y = yytext + 1;
yylval->d = strtoull((const char *)y, &e, 0);
if(e == y)
- error_message(ctx, "malformed constant (%s)", yytext);
+ ocpf_error_message(ctx, "malformed constant (%s)", yytext);
else
return I8;
}
. {
struct ocpf_context *ctx = yyextra;
- error_message(ctx, "Ignoring char(%c)\n", *yytext);
+ ocpf_error_message(ctx, "Ignoring char(%c)\n", *yytext);
}
%%
-void error_message(struct ocpf_context *ctx, const char *format, ...)
+void ocpf_error_message(struct ocpf_context *ctx, const char *format, ...)
{
va_list args;
static void
unterminated(struct ocpf_context *ctx, const char *type, unsigned int start_lineno)
{
- error_message(ctx, "unterminated %s, possibly started on line %d\n", type, start_lineno);
+ ocpf_error_message(ctx, "unterminated %s, possibly started on line %d\n", type, start_lineno);
fflush(0);
}
\ No newline at end of file
uint16_t s;
uint32_t l;
uint64_t d;
+ double dbl;
char *name;
char *nameW;
char *date;
%token <s> SHORT
%token <l> INTEGER
%token <d> I8
+%token <dbl> DOUBLE
%token <name> IDENTIFIER
%token <name> STRING
%token <nameW> UNICODE
%token kw_PT_SHORT
%token kw_PT_LONG
%token kw_PT_I8
+%token kw_PT_DOUBLE
%token kw_PT_SYSTIME
%token kw_PT_MV_LONG
%token kw_PT_MV_BINARY
ocpf_type_add(ctx,$2);
ctx->typeset++;
} else {
- error_message(ctx, "%s", "duplicated TYPE\n");
+ ocpf_error_message(ctx, "%s", "duplicated TYPE\n");
return -1;
}
}
ocpf_folder_add(ctx, $2, 0, NULL);
ctx->folderset = true;
} else {
- error_message(ctx, "%s", "duplicated FOLDER\n");
+ ocpf_error_message(ctx, "%s", "duplicated FOLDER\n");
}
}
| kw_FOLDER I8
ocpf_folder_add(ctx, NULL, $2, NULL);
ctx->folderset = true;
} else {
- error_message(ctx,"%s", "duplicated FOLDER\n");
+ ocpf_error_message(ctx,"%s", "duplicated FOLDER\n");
}
}
| kw_FOLDER VAR
ocpf_folder_add(ctx, NULL, 0, $2);
ctx->folderset = true;
} else {
- error_message(ctx,"%s", "duplicated FOLDER\n");
+ ocpf_error_message(ctx,"%s", "duplicated FOLDER\n");
}
}
;
| INTEGER { ctx->lpProp.l = $1; ctx->ltype = PT_LONG; }
| BOOLEAN { ctx->lpProp.b = $1; ctx->ltype = PT_BOOLEAN; }
| I8 { ctx->lpProp.d = $1; ctx->ltype = PT_I8; }
+ | DOUBLE { ctx->lpProp.dbl = $1, ctx->ltype = PT_DOUBLE; }
| SYSTIME
{
ocpf_add_filetime($1, &ctx->lpProp.ft);
binary_content : UINT8
{
if ($1 > 0xFF) {
- error_message(ctx,"Invalid Binary constant: 0x%x > 0xFF\n", $1);
+ ocpf_error_message(ctx,"Invalid Binary constant: 0x%x > 0xFF\n", $1);
}
if (!ctx->bin.cb) {
ctx->bin.cb);
ctx->lpProp.MVbin.cValues += 1;
- talloc_free(ctx->bin.lpb);
ctx->bin.cb = 0;
}
;
memset(&ctx->nprop, 0, sizeof (struct ocpf_nprop));
ctx->nprop.propType = PT_LONG;
}
+ | kw_PT_DOUBLE
+ {
+ memset(&ctx->nprop, 0, sizeof (struct ocpf_nprop));
+ ctx->nprop.propType = PT_DOUBLE;
+ }
| kw_PT_I8
{
memset(&ctx->nprop, 0, sizeof (struct ocpf_nprop));
case PT_LONG:
*value = talloc_memdup(ctx, (const void *)&lpProp.l, sizeof (uint32_t));
return OCPF_SUCCESS;
+ case PT_DOUBLE:
+ *value = talloc_memdup(ctx, (const void *)&lpProp.dbl, sizeof (uint64_t));
+ return OCPF_SUCCESS;
case PT_BOOLEAN:
*value = talloc_memdup(ctx, (const void *)&lpProp.b, sizeof (uint8_t));
return OCPF_SUCCESS;
NTTIME nt;
struct tm tm;
+ memset(&tm, 0, sizeof(struct tm));
if (!strptime(date, DATE_FORMAT, &tm)) {
printf("Invalid data format: Tyyy-mm-dd hh:mm:ss (e.g.: T2008-03-06 23:30:00");
return OCPF_ERROR;
--- /dev/null
+{
+ ocpf_bison1
+ Memcheck:Addr1
+ fun:__GI_strlen
+ fun:talloc_strdup
+ ...
+ fun:ocpf_yyparse
+ fun:ocpf_parse
+}
+
+{
+ ocpf_bison2
+ Memcheck:Addr1
+ fun:memcpy
+ fun:__talloc_strlendup
+ ...
+ fun:ocpf_yyparse
+ fun:ocpf_parse
+}
line = talloc_asprintf(ctx, "%d\n", *((const uint32_t *)value));
*found = true;
break;
+ case PT_DOUBLE:
+ line = talloc_asprintf(ctx, "F%e\n", *((const double *)value));
+ *found = true;
+ break;
case PT_BOOLEAN:
line = talloc_asprintf(ctx, "B\"%s\"\n", (*((const uint8_t *)value) == true) ? "true" : "false");
*found = true;
NTSTATUS dcerpc_server_exchange_store_information_init(void);
NTSTATUS dcerpc_server_exchange_nsp_init(void);
NTSTATUS dcerpc_server_exchange_emsmdb_init(void);
+NTSTATUS dcerpc_server_exchange_async_emsmdb_init(void);
NTSTATUS dcerpc_server_exchange_unknown_init(void);
/* definitions from samba4: librpc/ndr/ndr_table.c */
void dcesrv_EcDoRpcExt(struct dcesrv_call_state *, TALLOC_CTX *,struct EcDoRpcExt *);
enum MAPISTATUS dcesrv_EcDoConnectEx(struct dcesrv_call_state *, TALLOC_CTX *, struct EcDoConnectEx *);
enum MAPISTATUS dcesrv_EcDoRpcExt2(struct dcesrv_call_state *, TALLOC_CTX *, struct EcDoRpcExt2 *);
+void dcesrv_EcUnknown0xC(struct dcesrv_call_state *, TALLOC_CTX *, struct EcUnknown0xC *);
+void dcesrv_EcUnknown0xD(struct dcesrv_call_state *, TALLOC_CTX *, struct EcUnknown0xD *);
+enum MAPISTATUS dcesrv_EcDoAsyncConnectEx(struct dcesrv_call_state *, TALLOC_CTX *, struct EcDoAsyncConnectEx *);
void dcesrv_unknown_dummy(struct dcesrv_call_state *, TALLOC_CTX *,struct unknown_dummy *);
+/* AsyncEMSMDB protocol function */
+enum MAPISTATUS dcesrv_EcDoAsyncWaitEx(struct dcesrv_call_state *, TALLOC_CTX *, struct EcDoAsyncWaitEx *);
+
__END_DECLS
#endif /* ! __DCESRV_MAPIPROXY_PROTO_H__ */
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
+/*
+ EcDoUnknown0xc
+ */
+void dcesrv_EcUnknown0xC(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct EcUnknown0xC *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/*
+ EcDoAsyncConnectEx
+ */
+void dcesrv_EcUnknown0xD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct EcUnknown0xD *r)
+{
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/*
+ EcDoAsyncConnectEx
+ */
+enum MAPISTATUS dcesrv_EcDoAsyncConnectEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct EcDoAsyncConnectEx *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+/*
+ endpoint server for the exchange_async_emsmdb pipe
+ */
+enum MAPISTATUS dcesrv_EcDoAsyncWaitEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct EcDoAsyncWaitEx *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
/*
endpoint server for the exchange_unknown pipe
*/
add attributes required to access OpenChange server. The underlying
concept is that system administrators may want to give access to Samba
shares to a specific user but do not want him to access OpenChange
-server.<strong>The user must have been created using <i>samba4 newuser
-script</i></strong> prior you run this command. Run under the root
-account:
+server.<strong>The user must have been created using the Samba4
+<i>samba-tool newuser</i> script</strong> before you run this command.
+Run under the root account:
\code
# ./setup/openchange_newuser --create <username>
\endcode
talloc_free(guid);
ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
- LDB_SCOPE_SUBTREE, attrs, filter);
+ LDB_SCOPE_SUBTREE, attrs, "%s", filter);
MAPISTORE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPISTORE_ERROR, mem_ctx);
*propID = ldb_msg_find_attr_as_uint(res->msgs[0], "mapped_id", 0);
r->out.picxr = talloc_zero(mem_ctx, uint32_t);
*r->out.picxr = 0;
+ /* The following server version is not supported by Outlook 2010 */
r->out.rgwServerVersion[0] = 0x6;
r->out.rgwServerVersion[1] = 0x1141;
r->out.rgwServerVersion[2] = 0x5;
+ /* This one is but requires EcDoConnectEx/EcDoRpcExt2/Async
+ * EMSMDB implementation */
+
+ /* r->out.rgwServerVersion[0] = 0x8; */
+ /* r->out.rgwServerVersion[1] = 0x82B4; */
+ /* r->out.rgwServerVersion[2] = 0x3; */
+
r->out.rgwClientVersion[0] = r->in.rgwClientVersion[0];
r->out.rgwClientVersion[1] = r->in.rgwClientVersion[1];
r->out.rgwClientVersion[2] = r->in.rgwClientVersion[2];
}
-/**
- \details exchange_emsmdb EcDoRpc (0x2) function
-
- \param dce_call pointer to the session context
- \param mem_ctx pointer to the memory context
- \param r pointer to the EcDoRpc request data
-
- \return MAPI_E_SUCCESS on success
- */
-static enum MAPISTATUS dcesrv_EcDoRpc(struct dcesrv_call_state *dce_call,
- TALLOC_CTX *mem_ctx,
- struct EcDoRpc *r)
+static struct mapi_response *EcDoRpc_process_transaction(TALLOC_CTX *mem_ctx,
+ struct emsmdbp_context *emsmdbp_ctx,
+ struct mapi_request *mapi_request)
{
- struct exchange_emsmdb_session *session;
- struct emsmdbp_context *emsmdbp_ctx = NULL;
- struct mapi_request *mapi_request;
- struct mapi_response *mapi_response;
- enum MAPISTATUS retval;
- uint32_t handles_length;
- uint16_t size = 0;
- uint32_t i;
- uint32_t idx;
- bool found = false;
-
- DEBUG(3, ("exchange_emsmdb: EcDoRpc (0x2)\n"));
+ enum MAPISTATUS retval;
+ struct mapi_response *mapi_response;
+ uint32_t handles_length;
+ uint16_t size = 0;
+ uint32_t i;
+ uint32_t idx;
- /* Step 0. Ensure incoming user is authenticated */
- if (!NTLM_AUTH_IS_OK(dce_call)) {
- DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
- return MAPI_E_LOGON_FAILED;
- }
-
- /* Retrieve the emsmdbp_context from the session management system */
- for (session = emsmdb_session; session; session = session->next) {
- if ((mpm_session_cmp(session->session, dce_call)) == true) {
- emsmdbp_ctx = (struct emsmdbp_context *)session->session->private_data;
- found = true;
- }
- }
- OPENCHANGE_RETVAL_IF(found == false, MAPI_E_LOGON_FAILED, NULL);
+ /* Sanity checks */
+ if (!emsmdbp_ctx) return NULL;
+ if (!mapi_request) return NULL;
- mapi_request = r->in.mapi_request;
+ /* Allocate mapi_response */
mapi_response = talloc_zero(mem_ctx, struct mapi_response);
mapi_response->handles = mapi_request->handles;
- /* Step 1. Idle requests case */
+ /* Step 1. Handle Idle requests case */
if (mapi_request->mapi_len <= 2) {
mapi_response->mapi_len = 2;
- goto end;
+ return mapi_response;
}
-
+
/* Step 2. Process serialized MAPI requests */
mapi_response->mapi_repl = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REPL);
for (i = 0, idx = 0, size = 0; mapi_request->mapi_req[i].opnum != 0; i++) {
mapi_response->length = size + sizeof (mapi_response->length);
mapi_response->mapi_len = mapi_response->length + handles_length;
- /* Step 5. Fill EcDoRpc reply */
-end:
+ return mapi_response;
+}
+
+
+/**
+ \details exchange_emsmdb EcDoRpc (0x2) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the EcDoRpc request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static enum MAPISTATUS dcesrv_EcDoRpc(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct EcDoRpc *r)
+{
+ struct exchange_emsmdb_session *session;
+ struct emsmdbp_context *emsmdbp_ctx = NULL;
+ struct mapi_request *mapi_request;
+ struct mapi_response *mapi_response;
+ bool found = false;
+
+ DEBUG(3, ("exchange_emsmdb: EcDoRpc (0x2)\n"));
+
+ /* Step 0. Ensure incoming user is authenticated */
+ if (!NTLM_AUTH_IS_OK(dce_call)) {
+ DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
+ return MAPI_E_LOGON_FAILED;
+ }
+
+ /* Retrieve the emsmdbp_context from the session management system */
+ for (session = emsmdb_session; session; session = session->next) {
+ if ((mpm_session_cmp(session->session, dce_call)) == true) {
+ emsmdbp_ctx = (struct emsmdbp_context *)session->session->private_data;
+ found = true;
+ }
+ }
+ OPENCHANGE_RETVAL_IF(found == false, MAPI_E_LOGON_FAILED, NULL);
+
+ /* Step 1. Process EcDoRpc requests */
+ mapi_request = r->in.mapi_request;
+ mapi_response = EcDoRpc_process_transaction(mem_ctx, emsmdbp_ctx, mapi_request);
+
+ /* Step 2. Fill EcDoRpc reply */
r->out.handle = r->in.handle;
r->out.size = r->in.size;
r->out.offset = r->in.offset;
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
+/**
+ \details exchange_emsmdb EcDoRpcExt2 (0xB) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the EcDoRpcExt2 request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static enum MAPISTATUS dcesrv_EcDoRpcExt2(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct EcDoRpcExt2 *r)
+{
+ struct exchange_emsmdb_session *session;
+ struct emsmdbp_context *emsmdbp_ctx = NULL;
+ struct mapi2k7_request mapi2k7_request;
+ struct mapi_response *mapi_response;
+ struct RPC_HEADER_EXT RPC_HEADER_EXT;
+ struct ndr_pull *ndr_pull = NULL;
+ struct ndr_push *ndr_uncomp_rgbOut;
+ struct ndr_push *ndr_comp_rgbOut;
+ struct ndr_push *ndr_rgbOut;
+ uint32_t pulFlags = 0x0;
+ uint32_t pulTransTime = 0;
+ DATA_BLOB rgbIn;
+ bool found = false;
+
+ DEBUG(3, ("exchange_emsmdb: EcDoRpcExt2 (0xB)\n"));
+
+ /* Step 0. Ensure incoming user is authenticated */
+ if (!NTLM_AUTH_IS_OK(dce_call)) {
+ DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
+ return MAPI_E_LOGON_FAILED;
+ }
+
+ /* Retrieve the emsmdbp_context from the session management system */
+ for (session = emsmdb_session; session; session = session->next) {
+ if ((mpm_session_cmp(session->session, dce_call)) == true) {
+ emsmdbp_ctx = (struct emsmdbp_context *)session->session->private_data;
+ found = true;
+ }
+ }
+ OPENCHANGE_RETVAL_IF(found == false, MAPI_E_LOGON_FAILED, NULL);
+
+ /* Extract mapi_request from rgbIn */
+ rgbIn.data = r->in.rgbIn;
+ rgbIn.length = r->in.cbIn;
+ ndr_pull = ndr_pull_init_blob(&rgbIn, mem_ctx);
+ ndr_set_flags(&ndr_pull->flags, LIBNDR_FLAG_NOALIGN|LIBNDR_FLAG_REF_ALLOC);
+ ndr_pull_mapi2k7_request(ndr_pull, NDR_SCALARS|NDR_BUFFERS, &mapi2k7_request);
+ talloc_free(ndr_pull);
+
+ mapi_response = EcDoRpc_process_transaction(mem_ctx, emsmdbp_ctx, mapi2k7_request.mapi_request);
+ talloc_free(mapi2k7_request.mapi_request);
+
+ /* Fill EcDoRpcExt2 reply */
+ r->out.handle = r->in.handle;
+ r->out.pulFlags = &pulFlags;
+
+ /* Push MAPI response into a DATA blob */
+ ndr_uncomp_rgbOut = ndr_push_init_ctx(mem_ctx);
+ ndr_set_flags(&ndr_uncomp_rgbOut->flags, LIBNDR_FLAG_NOALIGN);
+ ndr_push_mapi_response(ndr_uncomp_rgbOut, NDR_SCALARS|NDR_BUFFERS, mapi_response);
+ talloc_free(mapi_response);
+
+ /* Obfuscate content */
+ ndr_comp_rgbOut = ndr_uncomp_rgbOut;
+ obfuscate_data(ndr_comp_rgbOut->data, ndr_comp_rgbOut->offset, 0xA5);
+
+ /* Build RPC_HEADER_EXT header for MAPI response DATA blob */
+ RPC_HEADER_EXT.Version = 0x0000;
+ RPC_HEADER_EXT.Flags = RHEF_XorMagic|RHEF_Last;
+ RPC_HEADER_EXT.Size = ndr_comp_rgbOut->offset;
+ RPC_HEADER_EXT.SizeActual = ndr_comp_rgbOut->offset;
+
+ /* Push the constructed blob */
+ ndr_rgbOut = ndr_push_init_ctx(mem_ctx);
+ ndr_set_flags(&ndr_rgbOut->flags, LIBNDR_FLAG_NOALIGN);
+ ndr_push_RPC_HEADER_EXT(ndr_rgbOut, NDR_SCALARS|NDR_BUFFERS, &RPC_HEADER_EXT);
+ ndr_push_bytes(ndr_rgbOut, ndr_comp_rgbOut->data, ndr_comp_rgbOut->offset);
+
+ /* Push MAPI response into a DATA blob */
+ r->out.rgbOut = ndr_rgbOut->data;
+ r->out.pcbOut = &ndr_rgbOut->offset;
+
+ r->out.rgbAuxOut = NULL;
+ *r->out.pcbAuxOut = 0;
+ r->out.pulTransTime = &pulTransTime;
+
+ return MAPI_E_SUCCESS;
+}
+
+/**
+ \details exchange_emsmdb EcUnknown0xC (0xc) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the EcUnknown0xC request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static void dcesrv_EcUnknown0xC(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct EcUnknown0xC *r)
+{
+ DEBUG(3, ("exchange_emsmdb: EcUnknown0xC (0xc) not implemented\n"));
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_emsmdb EcUnknown0xD (0xc) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the EcUnknown0xD request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static void dcesrv_EcUnknown0xD(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct EcUnknown0xD *r)
+{
+ DEBUG(3, ("exchange_emsmdb: EcUnknown0xC (0xd) not implemented\n"));
+ DCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/**
+ \details exchange_emsmdb EcGetMoreRpc (0xe) function
+
+ \param dce_call pointer to the session context
+ \param mem_ctx pointer to the memory context
+ \param r pointer to the EcDoAsyncConnectExt request data
+
+ \return MAPI_E_SUCCESS on success
+ */
+static enum MAPISTATUS dcesrv_EcDoAsyncConnectEx(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct EcDoAsyncConnectEx *r)
+{
+ DEBUG(3, ("exchange_emsmdb: EcDoAsyncConnectEx (0xe) not implemented\n"));
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+
+ return MAPI_E_SUCCESS;
+}
+
/**
\details Dispatch incoming EMSMDB call to the correct OpenChange
retval = dcesrv_EcDoConnectEx(dce_call, mem_ctx, (struct EcDoConnectEx *)r);
return NT_STATUS_NET_WRITE_FAULT;
break;
+ case NDR_ECDORPCEXT2:
+ retval = dcesrv_EcDoRpcExt2(dce_call, mem_ctx, (struct EcDoRpcExt2 *)r);
+ break;
+ case NDR_ECUNKNOWN0XC:
+ dcesrv_EcUnknown0xC(dce_call, mem_ctx, (struct EcUnknown0xC *)r);
+ break;
+ case NDR_ECUNKNOWN0XD:
+ dcesrv_EcUnknown0xD(dce_call, mem_ctx, (struct EcUnknown0xD *)r);
+ break;
+ case NDR_ECDOASYNCCONNECTEX:
+ dcesrv_EcDoAsyncConnectEx(dce_call, mem_ctx, (struct EcDoAsyncConnectEx *)r);
+ break;
}
return NT_STATUS_OK;
ndr->depth++;
ndr_print_uint32(ndr, "picxr", *r->out.picxr);
ndr->depth--;
- ndr_print_ptr(ndr, "szDNPrefix", r->out.szDNPrefix);
+ ndr_print_ptr(ndr, "szDNPrefix", r->out.szDisplayName);
ndr->depth++;
- ndr_print_ptr(ndr, "szDNPrefix", *r->out.szDNPrefix);
- ndr->depth++;
- if (*r->out.szDNPrefix) {
+ if (r->out.szDNPrefix && *r->out.szDNPrefix) {
+ ndr_print_ptr(ndr, "szDNPrefix", *r->out.szDNPrefix);
+ ndr->depth++;
ndr_print_string(ndr, "szDNPrefix", *r->out.szDNPrefix);
+ ndr->depth--;
}
ndr->depth--;
- ndr->depth--;
ndr_print_ptr(ndr, "szDisplayName", r->out.szDisplayName);
ndr->depth++;
- ndr_print_ptr(ndr, "szDisplayName", *r->out.szDisplayName);
- ndr->depth++;
- if (*r->out.szDisplayName) {
+ if (r->out.szDisplayName && *r->out.szDisplayName) {
+ ndr_print_ptr(ndr, "szDisplayName", *r->out.szDisplayName);
+ ndr->depth++;
ndr_print_string(ndr, "szDisplayName", *r->out.szDisplayName);
+ ndr->depth--;
}
ndr->depth--;
- ndr->depth--;
ndr->print(ndr, "%s: ARRAY(%d)", "rgwServerVersion", (int)3);
ndr->depth++;
for (cntr_rgwServerVersion_0=0;cntr_rgwServerVersion_0<3;cntr_rgwServerVersion_0++) {
ndr->depth++;
ndr_print_uint32(ndr, "pulTimeStamp", *r->out.pulTimeStamp);
ndr->depth--;
- ndr_print_mapi2k7_AuxInfo(ndr, "rgbAuxOut", r->out.rgbAuxOut);
+ ndr_print_ptr(ndr, "rgbAuxOut", r->out.rgbAuxOut);
+ if (r->out.rgbAuxOut && r->out.pcbAuxOut) {
+ ndr->depth++;
+ ndr_print_mapi2k7_AuxInfo(ndr, "rgbAuxOut", r->out.rgbAuxOut);
+ ndr->depth--;
+ }
ndr_print_ptr(ndr, "pcbAuxOut", r->out.pcbAuxOut);
ndr->depth++;
ndr_print_uint32(ndr, "pcbAuxOut", *r->out.pcbAuxOut);
ndr->depth++;
ndr_print_uint32(ndr, "pcbOut", *r->out.pcbOut);
ndr->depth--;
- ndr->print(ndr, "%s: ARRAY(%d)", "rgbAuxOut", (int)*r->out.pcbAuxOut);
- ndr->depth++;
- for (cntr_rgbAuxOut_0=0;cntr_rgbAuxOut_0<*r->out.pcbAuxOut;cntr_rgbAuxOut_0++) {
- char *idx_0=NULL;
- if (asprintf(&idx_0, "[%d]", cntr_rgbAuxOut_0) != -1) {
- ndr_print_uint32(ndr, "rgbAuxOut", r->out.rgbAuxOut[cntr_rgbAuxOut_0]);
- free(idx_0);
+ if (r->out.rgbAuxOut && r->out.pcbAuxOut) {
+ ndr->print(ndr, "%s: ARRAY(%d)", "rgbAuxOut", (int)*r->out.pcbAuxOut);
+ ndr->depth++;
+ for (cntr_rgbAuxOut_0=0;cntr_rgbAuxOut_0<*r->out.pcbAuxOut;cntr_rgbAuxOut_0++) {
+ char *idx_0=NULL;
+ if (asprintf(&idx_0, "[%d]", cntr_rgbAuxOut_0) != -1) {
+ ndr_print_uint32(ndr, "rgbAuxOut", r->out.rgbAuxOut[cntr_rgbAuxOut_0]);
+ free(idx_0);
+ }
}
+ } else {
+ ndr->print(ndr, "%s: NULL", "rgbAuxOut");
}
ndr->depth--;
ndr_print_ptr(ndr, "pcbAuxOut", r->out.pcbAuxOut);
fi
# If you have a samba checkout (even not up-to-date), you can make this a lot faster using --reference, e.g.
-# GIT_REFERENCE="--reference $HOME/samba-master"
-GIT_REPO=git://git.samba.org/samba.git
-# If you have an up-to-date checkout, you could also use something like
-# GIT_REPO=$HOME/samba-master
+# SAMBA_GIT_REFERENCE="--reference $HOME/samba-master"
+if test x"$SAMBA_GIT_REPO" = x""; then
+ SAMBA_GIT_REPO=git://git.samba.org/samba.git
+fi
# Set SAMBA_PREFIX to wherever you want to install to. Defaults to /usr/local/samba, as if you did the build manually
if test x"$SAMBA_PREFIX" = x""; then
SAMBA_PREFIX="/usr/local/samba"
fi
-# hack to work around waf build bug
-export CC="ccache gcc -I$SAMBA_PREFIX/include"
+# use ccache for faster rebuild, where available
+if which ccache 2>/dev/null; then
+ export CC="ccache gcc"
+else
+ export CC="gcc"
+fi
export PKG_CONFIG_PATH=$SAMBA_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH
pythondir=`python -c "from distutils import sysconfig; print sysconfig.get_python_lib(0,0,'/')"`
fi
echo "Step1: Fetching Samba4 latest GIT revision"
- git clone $GIT_REPO $GIT_REFERENCE samba4
+ git clone $SAMBA_GIT_REPO $SAMBA_GIT_REFERENCE samba4
error_check $? "Step1"
echo "Step2: Creating openchange local copy"
./autogen-waf.sh
error_check $? "$lib autogen"
-
- ./configure --prefix=$SAMBA_PREFIX --enable-developer --bundled-libraries=NONE
+ echo ./configure -C --prefix=$SAMBA_PREFIX --enable-developer --bundled-libraries=NONE
+ ./configure -C --prefix=$SAMBA_PREFIX --enable-developer --bundled-libraries=NONE
error_check $? "$lib configure"
- make
+ $MAKE -j
error_check $? "$lib make"
if test -w `dirname $SAMBA_PREFIX`; then
- make install
+ $MAKE install
error_check $? "$lib make install"
else
- sudo make install
+ sudo $MAKE install
error_check $? "$lib sudo make install"
fi
- make distclean
+ $MAKE distclean
error_check $? "$lib make distclean"
popd
pushd samba4/source4
error_check $? "samba4 setup"
- ./configure.developer --prefix=$SAMBA_PREFIX
+ ./configure.developer -C --prefix=$SAMBA_PREFIX
error_check $? "samba4 configure"
echo "Step2: Compile Samba4 (Source)"
- $MAKE
+ $MAKE -j
error_check $? "samba4 make"
popd
--- /dev/null
+/*
+ Test fast transfer operations and parser
+
+ OpenChange Project
+
+ Copyright (C) Brad Hards <bradh@openchange.org> 2010
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "libmapi/libmapi.h"
+#include "mapiproxy/libmapistore/mapistore.h"
+
+#include <samba/popt.h>
+#include <ldb.h>
+#include <talloc.h>
+
+#ifndef PRIx64
+#if __WORDSIZE == 64
+ #define PRIx64 "lx"
+#else
+ #define PRIx64 "llx"
+#endif
+#endif
+
+static void popt_openchange_version_callback(poptContext con,
+ enum poptCallbackReason reason,
+ const struct poptOption *opt,
+ const char *arg,
+ const void *data)
+{
+ switch (opt->val) {
+ case 'V':
+ printf("Version %s\n", OPENCHANGE_VERSION_STRING);
+ exit (0);
+ }
+}
+
+struct poptOption popt_openchange_version[] = {
+ { NULL, '\0', POPT_ARG_CALLBACK, (void *)popt_openchange_version_callback, '\0', NULL, NULL },
+ { "version", 'V', POPT_ARG_NONE, NULL, 'V', "Print version ", NULL },
+ POPT_TABLEEND
+};
+
+#define POPT_OPENCHANGE_VERSION { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_openchange_version, 0, "Common openchange options:", NULL },
+#define DEFAULT_PROFDB "%s/.openchange/profiles.ldb"
+
+/* These callbacks are for deserialising the fast transfer stream to a mapistore instance */
+struct parent_fid {
+ struct parent_fid *prev;
+ struct parent_fid *next;
+ uint64_t fid;
+};
+
+struct mapistore_output_ctx {
+ struct mapistore_context *mstore_ctx;
+ uint32_t mapistore_context_id;
+ uint64_t root_fid;
+ struct parent_fid *parent_fids; /* stack */
+ uint64_t current_id;
+ uint8_t current_output_type;
+ struct SRow *proplist; /* the properties on the "current" object */
+};
+
+static enum MAPISTATUS mapistore_marker(uint32_t marker, void *priv)
+{
+ struct mapistore_output_ctx *mapistore = priv;
+
+ if (mapistore->proplist) {
+ struct parent_fid *it;
+ printf("parent_fids: ");
+ for (it = mapistore->parent_fids; it->next; it = it->next) {
+ printf("0x%016"PRIx64",", it->fid);
+ }
+ printf("\n");
+ if (mapistore->current_id == mapistore->root_fid) {
+ /* This is the top level folder */
+ mapistore_setprops(mapistore->mstore_ctx, mapistore->mapistore_context_id,
+ mapistore->root_fid, mapistore->current_output_type,
+ mapistore->proplist);
+ } else if (mapistore->current_output_type == MAPISTORE_FOLDER) {
+ struct parent_fid *element = talloc_zero(mapistore->mstore_ctx, struct parent_fid);
+ mapistore_mkdir(mapistore->mstore_ctx, mapistore->mapistore_context_id,
+ mapistore->parent_fids->fid, mapistore->current_id,
+ mapistore->proplist);
+ element->fid = mapistore->current_id;
+ DLIST_ADD(mapistore->parent_fids, element);
+ } else {
+ mapistore_createmessage(mapistore->mstore_ctx, mapistore->mapistore_context_id,
+ mapistore->parent_fids->fid, mapistore->current_id);
+ mapistore_setprops(mapistore->mstore_ctx, mapistore->mapistore_context_id,
+ mapistore->current_id, mapistore->current_output_type,
+ mapistore->proplist);
+ mapistore_savechangesmessage(mapistore->mstore_ctx, mapistore->mapistore_context_id,
+ mapistore->current_id, 0);
+ }
+ talloc_free(mapistore->proplist);
+ mapistore->proplist = 0;
+ (mapistore->current_id)++;
+ }
+
+ switch (marker) {
+ case PR_START_TOP_FLD:
+ {
+ /* start collecting properties */
+ struct SPropValue one_prop;
+ struct parent_fid *element = talloc_zero(mapistore->mstore_ctx, struct parent_fid);
+ mapistore->proplist = talloc_zero(mapistore->mstore_ctx, struct SRow);
+ one_prop.ulPropTag = PR_FID;
+ one_prop.dwAlignPad = 0;
+ one_prop.value.d = mapistore->root_fid;
+ SRow_addprop(mapistore->proplist, one_prop);
+ one_prop.ulPropTag = PR_FOLDER_TYPE;
+ one_prop.value.l = MAPISTORE_FOLDER;
+ SRow_addprop(mapistore->proplist, one_prop);
+ mapistore->current_id = mapistore->root_fid;
+ mapistore->parent_fids = talloc_zero(mapistore->mstore_ctx, struct parent_fid);
+ element->fid = mapistore->current_id;
+ DLIST_ADD(mapistore->parent_fids, element);
+ mapistore->current_output_type = MAPISTORE_FOLDER;
+ break;
+ }
+ case PR_START_SUB_FLD:
+ mapistore->proplist = talloc_zero(mapistore->mstore_ctx, struct SRow);
+ mapistore->current_output_type = MAPISTORE_FOLDER;
+ break;
+ case PR_START_MESSAGE:
+ mapistore->proplist = talloc_zero(mapistore->mstore_ctx, struct SRow);
+ mapistore->current_output_type = MAPISTORE_MESSAGE;
+ break;
+ case PR_START_FAI_MSG:
+ case PR_START_RECIP:
+ case PR_START_EMBED:
+ case PR_NEW_ATTACH:
+ break;
+ case PR_END_FOLDER:
+ DLIST_REMOVE(mapistore->parent_fids, mapistore->parent_fids);
+ break;
+ case PR_END_MESSAGE:
+ case PR_END_RECIP:
+ case PR_END_ATTACH:
+ case PR_END_EMBED:
+ break;
+ default:
+ printf("***unhandled *** TODO: Marker: %s (0x%08x)\n", get_proptag_name(marker), marker);
+ }
+ return MAPI_E_SUCCESS;
+}
+
+static enum MAPISTATUS mapistore_delprop(uint32_t proptag, void *priv)
+{
+ printf("TODO: DelProps: 0x%08x (%s)\n", proptag, get_proptag_name(proptag));
+ return MAPI_E_SUCCESS;
+}
+
+static enum MAPISTATUS mapistore_namedprop(uint32_t proptag, struct MAPINAMEID nameid, void *priv)
+{
+ TALLOC_CTX *mem_ctx;
+ // struct mapistore_output_ctx *mapistore = priv;
+ mem_ctx = talloc_init("process_namedprop");
+ printf("TODO: Named Property: 0x%08x has GUID %s and ", proptag, GUID_string(mem_ctx, &(nameid.lpguid)));
+ if (nameid.ulKind == MNID_ID) {
+ printf("dispId 0x%08x\n", nameid.kind.lid);
+ } else if (nameid.ulKind == MNID_STRING) {
+ printf("name %s\n", nameid.kind.lpwstr.Name);
+ }
+ talloc_free(mem_ctx);
+ return MAPI_E_SUCCESS;
+}
+
+static enum MAPISTATUS mapistore_property(struct SPropValue prop, void *priv)
+{
+ struct mapistore_output_ctx *mapistore = priv;
+ SRow_addprop(mapistore->proplist, prop);
+ return MAPI_E_SUCCESS;
+}
+
+/* These callbacks are for the "dump-data" mode, so they don't do much */
+
+static enum MAPISTATUS dump_marker(uint32_t marker, void *priv)
+{
+ printf("Marker: %s (0x%08x)\n", get_proptag_name(marker), marker);
+ return MAPI_E_SUCCESS;
+}
+
+static enum MAPISTATUS dump_delprop(uint32_t proptag, void *priv)
+{
+ printf("DelProps: 0x%08x (%s)\n", proptag, get_proptag_name(proptag));
+ return MAPI_E_SUCCESS;
+}
+
+static enum MAPISTATUS dump_namedprop(uint32_t proptag, struct MAPINAMEID nameid, void *priv)
+{
+ TALLOC_CTX *mem_ctx;
+ mem_ctx = talloc_init("process_namedprop");
+ printf("Named Property: 0x%08x has GUID %s and ", proptag, GUID_string(mem_ctx, &(nameid.lpguid)));
+ if (nameid.ulKind == MNID_ID) {
+ printf("dispId 0x%08x\n", nameid.kind.lid);
+ } else if (nameid.ulKind == MNID_STRING) {
+ printf("name %s\n", nameid.kind.lpwstr.Name);
+ }
+ talloc_free(mem_ctx);
+ return MAPI_E_SUCCESS;
+}
+
+static enum MAPISTATUS dump_property(struct SPropValue prop, void *priv)
+{
+ mapidump_SPropValue(prop, "\t");
+ return MAPI_E_SUCCESS;
+}
+
+int main(int argc, const char *argv[])
+{
+ TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
+ struct mapi_context *mapi_ctx;
+ struct mapi_session *session = NULL;
+ struct mapi_profile *profile;
+ mapi_object_t obj_store;
+ mapi_object_t obj_folder;
+ mapi_object_t obj_fx_context;
+ mapi_id_t id_folder;
+
+ uint16_t progressCount;
+ uint16_t totalStepCount;
+ int transfers = 0;
+ enum TransferStatus fxTransferStatus;
+ DATA_BLOB transferdata;
+ struct fx_parser_context *parser;
+ struct mapistore_output_ctx output_ctx;
+ poptContext pc;
+ int opt;
+ const char *opt_profdb = NULL;
+ char *opt_profname = NULL;
+ const char *opt_password = NULL;
+ uint32_t opt_maxsize = 0;
+ const char *opt_mapistore = NULL;
+ bool opt_showprogress = false;
+ bool opt_dumpdata = false;
+ const char *opt_debug = NULL;
+
+ enum {OPT_PROFILE_DB=1000, OPT_PROFILE, OPT_PASSWORD, OPT_MAXDATA, OPT_SHOWPROGRESS, OPT_MAPISTORE, OPT_DEBUG, OPT_DUMPDATA};
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ {"database", 'f', POPT_ARG_STRING, NULL, OPT_PROFILE_DB, "set the profile database path", "PATH"},
+ {"profile", 'p', POPT_ARG_STRING, NULL, OPT_PROFILE, "set the profile name", "PROFILE"},
+ {"password", 'P', POPT_ARG_STRING, NULL, OPT_PASSWORD, "set the profile password", "PASSWORD"},
+ {"maxdata", 0, POPT_ARG_INT, NULL, OPT_MAXDATA, "the maximum transfer data size", "SIZE"},
+ {"showprogress", 0, POPT_ARG_NONE, NULL, OPT_SHOWPROGRESS, "enable progress display", NULL},
+ {"mapistore", 0, POPT_ARG_STRING, NULL, OPT_MAPISTORE, "serialise to mapistore", "FILESYSTEM_PATH"},
+ {"debuglevel", 'd', POPT_ARG_STRING, NULL, OPT_DEBUG, "set the debug level", "LEVEL"},
+ {"dump-data", 0, POPT_ARG_NONE, NULL, OPT_DUMPDATA, "dump the transfer data", NULL},
+ POPT_OPENCHANGE_VERSION
+ { NULL, 0, POPT_ARG_NONE, NULL, 0, NULL, NULL }
+ };
+
+ mem_ctx = talloc_named(NULL, 0, "check_fasttransfer");
+
+ pc = poptGetContext("check_fasttransfer", argc, argv, long_options, 0);
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_PROFILE_DB:
+ opt_profdb = poptGetOptArg(pc);
+ break;
+ case OPT_PROFILE:
+ opt_profname = talloc_strdup(mem_ctx, (char *)poptGetOptArg(pc));
+ break;
+ case OPT_PASSWORD:
+ opt_password = poptGetOptArg(pc);
+ break;
+ case OPT_MAXDATA:
+ opt_maxsize = *poptGetOptArg(pc);
+ break;
+ case OPT_SHOWPROGRESS:
+ opt_showprogress = true;
+ break;
+ case OPT_MAPISTORE:
+ opt_mapistore = poptGetOptArg(pc);
+ break;
+ case OPT_DEBUG:
+ opt_debug = poptGetOptArg(pc);
+ break;
+ case OPT_DUMPDATA:
+ opt_dumpdata = true;
+ break;
+ }
+ }
+
+ /**
+ * Sanity checks
+ */
+
+ if (!opt_profdb) {
+ opt_profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB, getenv("HOME"));
+ }
+
+ /**
+ * Initialize MAPI subsystem
+ */
+
+ retval = MAPIInitialize(&mapi_ctx, opt_profdb);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("MAPIInitialize", retval);
+ exit (1);
+ }
+
+ /* debug options */
+ SetMAPIDumpData(mapi_ctx, opt_dumpdata);
+
+ if (opt_debug) {
+ SetMAPIDebugLevel(mapi_ctx, atoi(opt_debug));
+ }
+
+ /* if no profile is supplied use the default one */
+ if (!opt_profname) {
+ retval = GetDefaultProfile(mapi_ctx, &opt_profname);
+ if (retval != MAPI_E_SUCCESS) {
+ printf("No profile specified and no default profile found\n");
+ exit (1);
+ }
+ }
+
+ retval = MapiLogonEx(mapi_ctx, &session, opt_profname, opt_password);
+ talloc_free(opt_profname);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("MapiLogonEx", retval);
+ exit (1);
+ }
+ profile = session->profile;
+
+ /* Open the default message store */
+ mapi_object_init(&obj_store);
+ mapi_object_init(&obj_folder);
+ /* mapi_object_init(&obj_table); */
+ mapi_object_init(&obj_fx_context);
+
+ retval = OpenMsgStore(session, &obj_store);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("OpenMsgStore", retval);
+ exit (1);
+ }
+
+ /* Open the top level folder */
+ retval = GetDefaultFolder(&obj_store, &id_folder, olFolderTopInformationStore);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("GetReceiveFolder", retval);
+ exit (1);
+ }
+
+ retval = OpenFolder(&obj_store, id_folder, &obj_folder);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("OpenFolder", retval);
+ exit (1);
+ }
+
+ retval = FXCopyFolder(&obj_folder, FastTransferCopyFolder_CopySubfolders, FastTransfer_Unicode, &obj_fx_context);
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("FXCopyFolder", retval);
+ exit (1);
+ }
+
+ if (opt_mapistore) {
+ char *root_folder;
+ // TODO: check the path is valid / exists / can be opened, etc.
+ // TODO: maybe allow a URI instead of path.
+ output_ctx.root_fid = 0x0000000000010001;
+ output_ctx.current_id = output_ctx.root_fid;
+ root_folder = talloc_asprintf(mem_ctx, "fsocpf://%s/0x%016"PRIx64, opt_mapistore, output_ctx.root_fid);
+ parser = fxparser_init(mem_ctx, &output_ctx);
+ retval = mapistore_set_mapping_path(opt_mapistore);
+ if (retval != MAPISTORE_SUCCESS) {
+ mapi_errstr("mapistore_set_mapping_path", retval);
+ exit (1);
+ }
+
+ output_ctx.mstore_ctx = mapistore_init(mem_ctx, NULL);
+ if (!(output_ctx.mstore_ctx)) {
+ mapi_errstr("mapistore_init", retval);
+ exit (1);
+ }
+
+ retval = mapistore_add_context(output_ctx.mstore_ctx, root_folder, &(output_ctx.mapistore_context_id));
+ if (retval != MAPISTORE_SUCCESS) {
+ DEBUG(0, ("%s\n", mapistore_errstr(retval)));
+ exit (1);
+ }
+
+ output_ctx.proplist = 0;
+
+ fxparser_set_marker_callback(parser, mapistore_marker);
+ fxparser_set_delprop_callback(parser, mapistore_delprop);
+ fxparser_set_namedprop_callback(parser, mapistore_namedprop);
+ fxparser_set_property_callback(parser, mapistore_property);
+ } else if (opt_dumpdata) {
+ parser = fxparser_init(mem_ctx, NULL);
+ fxparser_set_marker_callback(parser, dump_marker);
+ fxparser_set_delprop_callback(parser, dump_delprop);
+ fxparser_set_namedprop_callback(parser, dump_namedprop);
+ fxparser_set_property_callback(parser, dump_property);
+ } else {
+ parser = fxparser_init(mem_ctx, NULL);
+ }
+
+ do {
+ retval = FXGetBuffer(&obj_fx_context, opt_maxsize, &fxTransferStatus, &progressCount, &totalStepCount, &transferdata);
+ transfers++;
+ if (retval != MAPI_E_SUCCESS) {
+ mapi_errstr("FXGetBuffer", retval);
+ exit (1);
+ }
+
+ if (opt_showprogress) {
+ printf("progress: (%d/%d)\n", progressCount, totalStepCount);
+ printf("status: 0x%04x\n", fxTransferStatus);
+ }
+
+ fxparser_parse(parser, &transferdata);
+ } while ((fxTransferStatus == TransferStatus_Partial) || (fxTransferStatus == TransferStatus_NoRoom));
+
+ printf("total transfers: %i\n", transfers);
+
+ if (opt_mapistore) {
+ retval = mapistore_del_context(output_ctx.mstore_ctx, output_ctx.mapistore_context_id);
+ if (retval != MAPISTORE_SUCCESS) {
+ mapi_errstr("mapistore_del_context", retval);
+ exit (1);
+ }
+
+ retval = mapistore_release(output_ctx.mstore_ctx);
+ if (retval != MAPISTORE_SUCCESS) {
+ mapi_errstr("mapistore_release", retval);
+ exit (1);
+ }
+ }
+
+ talloc_free(parser);
+
+ mapi_object_release(&obj_fx_context);
+
+ mapi_object_release(&obj_folder);
+ mapi_object_release(&obj_store);
+ MAPIUninitialize(mapi_ctx);
+
+ talloc_free(mem_ctx);
+
+ return 0;
+}
const char *from = NULL;
const char *normalizedsubject = NULL;
const char *subject_prefix = NULL;
+ const char *subject = NULL;
const char *thread_topic = NULL;
const char *msgid;
DATA_BLOB body;
from = (const char *) octool_get_propval(aRow, PR_SENT_REPRESENTING_NAME);
subject_prefix = (const char *) octool_get_propval(aRow, PR_SUBJECT_PREFIX);
normalizedsubject = (const char *) octool_get_propval(aRow, PR_NORMALIZED_SUBJECT);
+ subject = (const char*) octool_get_propval(aRow, PR_SUBJECT);
thread_topic = (const char *) octool_get_propval(aRow, PR_CONVERSATION_TOPIC);
msgid = (const char *) octool_get_propval(aRow, PR_INTERNET_MESSAGE_ID);
len = fwrite(line, strlen(line), 1, fp);
}
talloc_free(line);
+ } else {
+ line = talloc_asprintf(mem_ctx, "Subject: %s\n", subject);
+ if (line) {
+ len = fwrite(line, strlen(line), 1, fp);
+ }
+ talloc_free(line);
}
if (thread_topic) {
rowset.aRow[i].lpProps[1].value.d,
&obj_message, 0);
if (GetLastError() == MAPI_E_SUCCESS) {
- SPropTagArray = set_SPropTagArray(mem_ctx, 0x15,
+ SPropTagArray = set_SPropTagArray(mem_ctx, 0x19,
PR_INTERNET_MESSAGE_ID,
PR_INTERNET_MESSAGE_ID_UNICODE,
PR_CONVERSATION_TOPIC,
PR_DISPLAY_BCC_UNICODE,
PR_HASATTACH,
PR_SUBJECT_PREFIX,
- PR_NORMALIZED_SUBJECT);
+ PR_SUBJECT_PREFIX_UNICODE,
+ PR_NORMALIZED_SUBJECT,
+ PR_NORMALIZED_SUBJECT_UNICODE,
+ PR_SUBJECT,
+ PR_SUBJECT_UNICODE);
retval = GetProps(&obj_message, SPropTagArray, &lpProps, &count);
MAPIFreeBuffer(SPropTagArray);
if (retval != MAPI_E_SUCCESS) {
NotInExchange2010 = 0x1, /*!< This test is not applicable to Exchange 2010 */
NotInExchange2010SP0 = 0x2, /*!< This test is not applicable to Exchange 2010
Service Pack 0, but is applicable to later versions */
+ ExpectedFail = 0x8000, /*!< This test is expected to fail */
LastTestApplicabilityFlag = 0xFFFF
};
-
+/**
+ List of possible test results
+*/
+enum TestResult {
+ Pass, /*!< The test was expected to pass, and it did */
+ Fail, /*!< The test was expected to pass, but it failed */
+ UnexpectedPass, /*!< The test was expected to fail, but it passed instead */
+ ExpectedFailure /*!< The test was expected to fail, and it did */
+};
#include "utils/mapitest/proto.h"
struct mapitest_unit *prev; /*!< The previous test in the list */
struct mapitest_unit *next; /*!< The next test in the list */
char *name; /*!< The name of the test */
- char *reason; /*!< Why this test was skipped (if applicable) */
+ char *reason; /*!< Why this test was skipped or failed (if applicable) */
};
/**
There should be one entry in the failure_info list for each failure.
*/
struct mapitest_stat {
- uint32_t success; /*!< Number of tests in this suite that passed */
- uint32_t failure; /*!< Number of tests in this suite that failed */
- uint32_t skipped; /*!< Number of tests in this suite that were skipped */
- struct mapitest_unit *failure_info; /*!< List of names of the tests that failed */
- struct mapitest_unit *skip_info; /*!< List of names of the tests that were skipped, and why */
- bool enabled; /*!< Whether this statistics structure is valid */
+ uint32_t success; /*!< Number of tests in this suite that passed */
+ uint32_t failure; /*!< Number of tests in this suite that failed */
+ uint32_t skipped; /*!< Number of tests in this suite that were skipped */
+ uint32_t x_fail; /*!< Number of tests in this suite that were expected failures */
+ struct mapitest_unit *failure_info; /*!< List of names of the tests that failed */
+ struct mapitest_unit *skip_info; /*!< List of names of the tests that were skipped, and why */
+ bool enabled; /*!< Whether this statistics structure is valid */
};
/**
#define MT_DIRNAME_TEST "[MT] Test Folder1"
#define MT_MAIL_SUBJECT "[MT] Sample E-MAIL"
-#define MT_MAIL_ATTACH "[MT]_Sample_Attachment.txt"
-#define MT_MAIL_ATTACH2 "[MT]_Sample_Attachment2.txt"
+#define MT_MAIL_ATTACH "Attach1.txt"
+#define MT_MAIL_ATTACH2 "Attach2.txt"
#define MODULE_TITLE "[MODULE] %s\n"
#define MODULE_TITLE_DELIM '#'
#define MT_ERROR "[ERROR]: %s\n"
#define MT_STAT_FAILED_TITLE "[STAT] FAILED TEST CASES\n"
-#define MT_STAT_FAILURE "* %-35s: %s\n"
+#define MT_STAT_RESULT "* %-35s: %s (%s)\n"
#define MT_STAT_SKIPPED_TITLE "[STAT] SKIPPED TEST CASES\n"
-#define MT_STAT_SKIPPED "* %-35s: %s (%s)\n"
#define MT_SUMMARY_TITLE "[STAT] TEST SUMMARY\n"
#include "utils/mapitest/mapitest.h"
+#include <assert.h>
+
/**
\file
mapitest statistics functions
stat->success = 0;
stat->failure = 0;
stat->skipped = 0;
+ stat->x_fail = 0;
stat->failure_info = NULL;
stat->skip_info = NULL;
stat->enabled = false;
*/
_PUBLIC_ uint32_t mapitest_stat_add_result(struct mapitest_suite *suite,
const char *name,
- bool result)
+ enum TestResult testresult)
{
struct mapitest_unit *el = NULL;
/* Sanity check */
if (!suite || !suite->stat || !name) return MAPITEST_ERROR;
- if (result == true) {
+ if (testresult == Pass) {
suite->stat->success++;
} else {
- suite->stat->failure++;
el = talloc_zero((TALLOC_CTX *) suite->stat, struct mapitest_unit);
el->name = talloc_strdup((TALLOC_CTX *)el, (char *)name);
- el->reason = 0;
+
+ if (testresult == Fail) {
+ suite->stat->failure++;
+ el->reason = talloc_strdup((TALLOC_CTX *) el, "Unexpected Fail");
+ } else if (testresult == ExpectedFail) {
+ suite->stat->x_fail++;
+ el->reason = talloc_strdup((TALLOC_CTX *) el, "Expected Fail");
+ } else if (testresult == UnexpectedPass) {
+ suite->stat->failure++;
+ el->reason = talloc_strdup((TALLOC_CTX *) el, "Unexpected Pass");
+ } else {
+ assert(0); /* this indicates that we're passing a bad enum into this function */
+ }
DLIST_ADD_END(suite->stat->failure_info, el, struct mapitest_unit *);
}
int32_t num_passed_tests = 0;
int32_t num_failed_tests = 0;
int32_t num_skipped_tests = 0;
+ int32_t num_xfail_tests = 0;
mapitest_print_title(mt, MT_STAT_SKIPPED_TITLE, MODULE_TITLE_DELIM);
for (suite = mt->mapi_suite; suite; suite = suite->next) {
num_skipped_tests += suite->stat->skipped;
if (suite->stat->skipped) {
for (el = suite->stat->skip_info; el; el = el->next) {
- mapitest_print(mt, MT_STAT_SKIPPED, suite->name, el->name, el->reason);
+ mapitest_print(mt, MT_STAT_RESULT, suite->name, el->name, el->reason);
}
}
}
if (suite->stat->enabled == true) {
num_passed_tests += suite->stat->success;
num_failed_tests += suite->stat->failure;
- if (suite->stat->failure) {
+ num_xfail_tests += suite->stat->x_fail;
+ if (suite->stat->failure || suite->stat->x_fail) {
for (el = suite->stat->failure_info; el; el = el->next) {
- mapitest_print(mt, MT_STAT_FAILURE, suite->name, el->name);
+ mapitest_print(mt, MT_STAT_RESULT, suite->name, el->name, el->reason);
}
}
}
mapitest_print(mt, "Number of passing tests: %i\n", num_passed_tests);
mapitest_print(mt, "Number of failing tests: %i\n", num_failed_tests);
mapitest_print(mt, "Number of skipped tests: %i\n", num_skipped_tests);
+ mapitest_print(mt, "Number of expected fails: %i\n", num_xfail_tests);
mapitest_print_test_title_end(mt);
return num_failed_tests;
return true;
}
+static bool run_test(struct mapitest *mt, struct mapitest_suite *suite, struct mapitest_test *el)
+{
+ bool (*fn)(struct mapitest *);
+ bool ret = false;
+
+ if (!mapitest_suite_test_is_applicable(mt, el)) {
+ mapitest_stat_add_skipped_test(suite, el->name, el->flags);
+ } else {
+ errno = 0;
+ mapitest_print_test_title_start(mt, el->name);
+
+ fn = el->fn;
+ ret = fn(mt);
+
+ if (el->flags & ExpectedFail) {
+ if (ret) {
+ mapitest_stat_add_result(suite, el->name, UnexpectedPass);
+ } else {
+ mapitest_stat_add_result(suite, el->name, ExpectedFail);
+ }
+ } else {
+ if (ret) {
+ mapitest_stat_add_result(suite, el->name, Pass);
+ } else {
+ mapitest_stat_add_result(suite, el->name, Fail);
+ }
+ }
+ mapitest_print_test_title_end(mt);
+ mapitest_print_test_result(mt, el->name, ret);
+ }
+ return ret;
+}
+
/**
\details run a test from a suite given its name
{
struct mapitest_test *el;
bool ret;
- bool (*fn)(struct mapitest *);
if (!suite || !name) return false;
for (el = suite->tests; el; el = el->next) {
if (!strcmp(el->name, name)) {
- if (!mapitest_suite_test_is_applicable(mt, el)) {
- mapitest_stat_add_skipped_test(suite, el->name, el->flags);
- return true;
- }
- errno = 0;
- mapitest_print_test_title_start(mt, el->name);
- fn = el->fn;
- ret = fn(mt);
-
- mapitest_stat_add_result(suite, el->name, ret);
- mapitest_print_test_title_end(mt);
- mapitest_print_test_result(mt, el->name, ret);
+ ret = run_test(mt, suite, el);
return ret;
}
}
return ret;
}
+static void run_tests_in_suite(struct mapitest *mt, struct mapitest_suite *suite)
+{
+ struct mapitest_test *el;
+
+ for (el = suite->tests; el; el = el->next) {
+ run_test(mt, suite, el);
+ }
+}
/**
\details all tests from all suites
\return true on success, otherwise -1
*/
-_PUBLIC_ bool mapitest_run_all(struct mapitest *mt)
+_PUBLIC_ void mapitest_run_all(struct mapitest *mt)
{
struct mapitest_suite *suite;
- struct mapitest_test *el;
- bool (*fn)(struct mapitest *);
- bool ret = false;
+
for (suite = mt->mapi_suite; suite; suite = suite->next) {
if ((mt->online == suite->online) || (suite->online == false)) {
mapitest_print_module_title_start(mt, suite->name);
- for (el = suite->tests; el; el = el->next) {
- if (!mapitest_suite_test_is_applicable(mt, el)) {
- mapitest_stat_add_skipped_test(suite, el->name, el->flags);
- } else {
- errno = 0;
- mapitest_print_test_title_start(mt, el->name);
-
- fn = el->fn;
- ret = fn(mt);
-
- mapitest_stat_add_result(suite, el->name, ret);
- mapitest_print_test_title_end(mt);
- mapitest_print_test_result(mt, el->name, ret);
- }
- }
+ run_tests_in_suite(mt, suite);
mapitest_print_module_title_end(mt);
}
}
- return ret;
}
suite = mapitest_suite_init(mt, "LZXPRESS", "lzxpress algorithm test suite", false);
- mapitest_suite_add_test(suite, "VALIDATE-001", "Validate LZXPRESS implementation using sample file 001", mapitest_lzxpress_validate_test_001);
+ mapitest_suite_add_test_flagged(suite, "VALIDATE-001", "Validate LZXPRESS implementation using sample file 001", mapitest_lzxpress_validate_test_001, ExpectedFail);
mapitest_suite_register(mt, suite);
SRowSet = talloc_zero(mem_ctx, struct SRowSet);
retval = nspi_GetSpecialTable(nspi_ctx, mem_ctx, 0x2, &SRowSet);
MAPIFreeBuffer(SRowSet);
- if (GetLastError() != MAPI_E_SUCCESS) {
+ if (retval != MAPI_E_SUCCESS) {
talloc_free(mem_ctx);
return false;
}
retval = nspi_UpdateStat(nspi_ctx, mem_ctx, &plDelta);
mapitest_print_retval(mt, "NspiUpdateStat");
- if (GetLastError() != MAPI_E_SUCCESS) {
+ if (retval != MAPI_E_SUCCESS) {
talloc_free(mem_ctx);
return false;
}
MAPIFreeBuffer(lpProp);
MAPIFreeBuffer(SRowSet);
MAPIFreeBuffer(SPropTagArray);
- mapitest_print_retval(mt, "NspiGetMatches");
- if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval_clean(mt, "NspiGetMatches", retval);
+ if (retval != MAPI_E_SUCCESS) {
MAPIFreeBuffer(MIds);
talloc_free(mem_ctx);
return false;
SRowSet = talloc_zero(mem_ctx, struct SRowSet);
retval = nspi_QueryRows(nspi_ctx, mem_ctx, NULL, MIds, 1, &SRowSet);
MAPIFreeBuffer(SRowSet);
- mapitest_print_retval(mt, "NspiQueryRows");
- if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval_clean(mt, "NspiQueryRows", retval);
+ if (retval != MAPI_E_SUCCESS) {
MAPIFreeBuffer(MIds);
talloc_free(mem_ctx);
return false;
struct SPropValue pTarget;
struct SPropTagArray *pPropTags;
struct SRowSet *SRowSet;
+ struct emsmdb_context *emsmdb;
+ bool ret = true;
mem_ctx = talloc_named(NULL, 0, "mapitest_nspi_SeekEntries");
nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
+ emsmdb = (struct emsmdb_context *) mt->session->emsmdb->ctx;
SRowSet = talloc_zero(mem_ctx, struct SRowSet);
pTarget.ulPropTag = PR_DISPLAY_NAME;
pTarget.dwAlignPad = 0x0;
- pTarget.value.lpszA = mt->mapi_ctx->session->profile->username;
+ pTarget.value.lpszA = emsmdb->info.szDisplayName;
pPropTags = set_SPropTagArray(mem_ctx, 0x1, PR_ACCOUNT);
+ retval = nspi_SeekEntries(nspi_ctx, mem_ctx, SortTypeDisplayName, &pTarget, pPropTags, NULL, &SRowSet);
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
+ mapitest_print_retval_clean(mt, "NspiSeekEntries", retval);
+ MAPIFreeBuffer(SRowSet);
+ MAPIFreeBuffer(pPropTags);
+
+ SRowSet = talloc_zero(mem_ctx, struct SRowSet);
+
+ pTarget.ulPropTag = PR_DISPLAY_NAME_UNICODE;
+ pTarget.dwAlignPad = 0x0;
+ pTarget.value.lpszA = emsmdb->info.szDisplayName;
+ pPropTags = set_SPropTagArray(mem_ctx, 0x1, PR_ACCOUNT);
retval = nspi_SeekEntries(nspi_ctx, mem_ctx, SortTypeDisplayName, &pTarget, pPropTags, NULL, &SRowSet);
- if (GetLastError() != MAPI_E_SUCCESS) {
- mapitest_print_retval(mt, "NspiSeekEntries");
- talloc_free(pPropTags);
- talloc_free(SRowSet);
- talloc_free(mem_ctx);
- return false;
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
}
- mapitest_print_retval(mt, "NspiSeekEntries");
+ mapitest_print_retval_clean(mt, "NspiSeekEntries", retval);
MAPIFreeBuffer(SRowSet);
MAPIFreeBuffer(pPropTags);
+
talloc_free(mem_ctx);
- return true;
+ return ret;
}
struct SPropTagArray *SPropTagArray;
struct SPropValue *lpProp;
struct Restriction_r Filter;
+ bool ret = true;
mem_ctx = talloc_named(NULL, 0, "mapitest_nspi_GetMatches");
nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
MAPIFreeBuffer(SRowSet);
MAPIFreeBuffer(SPropTagArray);
MAPIFreeBuffer(MIds);
- mapitest_print_retval(mt, "NspiGetMatches");
- if (GetLastError() != MAPI_E_SUCCESS) {
- talloc_free(mem_ctx);
- return false;
+ mapitest_print_retval_clean(mt, "NspiGetMatches", retval);
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
}
talloc_free(mem_ctx);
- return true;
+ return ret;
}
struct SPropValue *lpProp = NULL;
struct SPropTagArray *MIds = NULL;
struct SPropTagArray *ppMIds = NULL;
+ bool ret = true;
mem_ctx = talloc_named(NULL, 0, "mapitest_nspi_ResortRestriction");
nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
MAPIFreeBuffer(lpProp);
MAPIFreeBuffer(SPropTagArray);
MAPIFreeBuffer(SRowSet);
- mapitest_print_retval(mt, "NspiGetMatches");
- if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval_clean(mt, "NspiGetMatches", retval);
+ if (retval != MAPI_E_SUCCESS) {
MAPIFreeBuffer(MIds);
talloc_free(mem_ctx);
return false;
ppMIds = talloc_zero(mem_ctx, struct SPropTagArray);
retval = nspi_ResortRestriction(nspi_ctx, mem_ctx, SortTypeDisplayName, MIds, &ppMIds);
- mapitest_print_retval(mt, "NspiResortRestriction");
- if (GetLastError() != MAPI_E_SUCCESS) {
- MAPIFreeBuffer(MIds);
- MAPIFreeBuffer(ppMIds);
- talloc_free(mem_ctx);
- return false;
+ mapitest_print_retval_clean(mt, "NspiResortRestriction", retval);
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
}
MAPIFreeBuffer(MIds);
MAPIFreeBuffer(ppMIds);
talloc_free(mem_ctx);
- return true;
+ return ret;
}
MAPIFreeBuffer(MId);
talloc_free(mem_ctx);
- mapitest_print_retval(mt, "NspiDNToMId");
+ mapitest_print_retval_clean(mt, "NspiDNToMId", retval);
- if (GetLastError() != MAPI_E_SUCCESS) {
- return false;
+ if (retval == MAPI_E_SUCCESS) {
+ return true;
+ } else {
+ return false;
}
-
- return true;
}
MAPIFreeBuffer((char **)pNames.Strings);
mapitest_print_retval(mt, "NspiDNToMId");
- if (GetLastError() != MAPI_E_SUCCESS) {
+ if (retval != MAPI_E_SUCCESS) {
MAPIFreeBuffer(MId);
talloc_free(mem_ctx);
return false;
SRowSet = talloc_zero(mem_ctx, struct SRowSet);
SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_EMS_AB_NETWORK_ADDRESS);
retval = nspi_GetProps(nspi_ctx, mem_ctx, SPropTagArray, MId, &SRowSet);
- mapitest_print_retval(mt, "NspiGetProps");
+ mapitest_print_retval_clean(mt, "NspiGetProps", retval);
MAPIFreeBuffer(SPropTagArray);
MAPIFreeBuffer(MId);
MAPIFreeBuffer(SRowSet);
talloc_free(mem_ctx);
- if (GetLastError() != MAPI_E_SUCCESS) {
- return false;
+ if (retval == MAPI_E_SUCCESS) {
+ return true;
+ } else {
+ return false;
}
-
- return true;
}
MAPIFreeBuffer(lpProp);
MAPIFreeBuffer(SPropTagArray);
MAPIFreeBuffer(SRowSet);
- mapitest_print_retval(mt, "NspiGetMatches");
- if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval_clean(mt, "NspiGetMatches", retval);
+ if (retval != MAPI_E_SUCCESS) {
MAPIFreeBuffer(MIds);
talloc_free(mem_ctx);
return false;
}
retval = nspi_CompareMIds(nspi_ctx, mem_ctx, MIds->aulPropTag[0], MIds->aulPropTag[1], &plResult);
- mapitest_print_retval(mt, "NspiCompareMIds");
+ mapitest_print_retval_clean(mt, "NspiCompareMIds", retval);
MAPIFreeBuffer(MIds);
- if (GetLastError() != MAPI_E_SUCCESS) {
+ if (retval != MAPI_E_SUCCESS) {
talloc_free(mem_ctx);
return false;
}
struct SPropTagArray *SPropTagArray;
struct SPropValue *lpProp;
struct Restriction_r Filter;
+ const char *original_office_location;
+ bool ret = true;
mem_ctx = talloc_named(NULL, 0, "mapitest_nspi_ModProps");
nspi_ctx = (struct nspi_context *) mt->session->nspi->ctx;
MAPIFreeBuffer(lpProp);
MAPIFreeBuffer(SRowSet);
MAPIFreeBuffer(SPropTagArray);
- mapitest_print_retval(mt, "NspiGetMatches");
- if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval_clean(mt, "nspi_GetMatches", retval);
+ if (retval != MAPI_E_SUCCESS) {
MAPIFreeBuffer(MIds);
talloc_free(mem_ctx);
return false;
/* Query the rows */
SRowSet = talloc_zero(mem_ctx, struct SRowSet);
retval = nspi_QueryRows(nspi_ctx, mem_ctx, NULL, MIds, 1, &SRowSet);
- MAPIFreeBuffer(SRowSet);
- mapitest_print_retval(mt, "NspiQueryRows");
- if (GetLastError() != MAPI_E_SUCCESS) {
+ mapitest_print_retval_clean(mt, "nspi_QueryRows", retval);
+ if (retval != MAPI_E_SUCCESS) {
MAPIFreeBuffer(MIds);
+ MAPIFreeBuffer(SRowSet);
talloc_free(mem_ctx);
return false;
}
+ if (SRowSet->cRows != 1) {
+ mapitest_print(mem_ctx, "unexpected number of rows: %i\n", SRowSet->cRows);
+ MAPIFreeBuffer(MIds);
+ MAPIFreeBuffer(SRowSet);
+ talloc_free(mem_ctx);
+ return false;
+ }
+ original_office_location = (const char *)find_SPropValue_data(&(SRowSet->aRow[0]), PR_OFFICE_LOCATION);
+ mapitest_print(mt, "original PR_OFFICE_LOCATION value: %s\n", original_office_location);
/* Build the SRow and SPropTagArray for NspiModProps */
pRow = talloc_zero(mem_ctx, struct SRow);
- modProp.ulPropTag = PR_DISPLAY_NAME_UNICODE;
- modProp.value.lpszW = "mapitest ModProps";
+ modProp.ulPropTag = PR_OFFICE_LOCATION;
+ modProp.value.lpszA = "[MT] office location";
SRow_addprop(pRow, modProp);
- pPropTags = set_SPropTagArray(mem_ctx, 0x1, PR_DISPLAY_NAME_UNICODE);
+ pPropTags = set_SPropTagArray(mem_ctx, 0x1, PR_OFFICE_LOCATION);
+ retval = nspi_ModProps(nspi_ctx, mem_ctx, MIds->aulPropTag[0], pPropTags, pRow);
+ mapitest_print_retval_clean(mt, "nspi_ModProps", retval);
+ MAPIFreeBuffer(pRow);
+
+ if (retval != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(MIds);
+ MAPIFreeBuffer(pPropTags);
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* Check that the property was set correctly */
+ SRowSet = talloc_zero(mem_ctx, struct SRowSet);
+ retval = nspi_QueryRows(nspi_ctx, mem_ctx, NULL, MIds, 1, &SRowSet);
+ mapitest_print_retval_clean(mt, "nspi_QueryRows", retval);
+ if (retval != MAPI_E_SUCCESS) {
+ MAPIFreeBuffer(MIds);
+ MAPIFreeBuffer(SRowSet);
+ talloc_free(mem_ctx);
+ return false;
+ }
+ if (SRowSet->cRows != 1) {
+ mapitest_print(mem_ctx, "unexpected number of rows: %i\n", SRowSet->cRows);
+ MAPIFreeBuffer(MIds);
+ MAPIFreeBuffer(SRowSet);
+ talloc_free(mem_ctx);
+ return false;
+ }
+ if (strcmp((const char *)find_SPropValue_data(&(SRowSet->aRow[0]), PR_OFFICE_LOCATION), "[MT] office location") != 0) {
+ mapitest_print(mt, "PR_OFFICE_LOCATION string value mismatch: %s", (const char *)find_SPropValue_data(&(SRowSet->aRow[0]), PR_OFFICE_LOCATION));
+ ret = false;
+ } else {
+ mapitest_print(mt, "correctly set PR_OFFICE_LOCATION\n");
+ }
+
+ /* try to reset the office location back to the original value */
+ pRow = talloc_zero(mem_ctx, struct SRow);
+ modProp.ulPropTag = PR_OFFICE_LOCATION;
+ modProp.value.lpszA = original_office_location;
+ SRow_addprop(pRow, modProp);
retval = nspi_ModProps(nspi_ctx, mem_ctx, MIds->aulPropTag[0], pPropTags, pRow);
- mapitest_print_retval(mt, "NspiModProps");
+ mapitest_print_retval_clean(mt, "nspi_ModProps (reset original value)", retval);
+ if (retval != MAPI_E_SUCCESS) {
+ ret = false;
+ }
+
MAPIFreeBuffer(MIds);
MAPIFreeBuffer(pPropTags);
MAPIFreeBuffer(pRow);
- talloc_free(mem_ctx);
- /* Assuming true for the moment */
- return true;
+ talloc_free(mem_ctx);
+
+ return ret;
}
SRowSet = talloc_zero(mem_ctx, struct SRowSet);
retval = nspi_GetSpecialTable(nspi_ctx, mem_ctx, 0x0, &SRowSet);
MAPIFreeBuffer(SRowSet);
- mapitest_print_retval(mt, "NspiGetSpecialTable (Hierarchy Table)");
+ mapitest_print_retval_clean(mt, "NspiGetSpecialTable (Hierarchy Table)", retval);
- if (GetLastError() != MAPI_E_SUCCESS) {
+ if (retval != MAPI_E_SUCCESS) {
talloc_free(mem_ctx);
return false;
}
SRowSet = talloc_zero(mt->mem_ctx, struct SRowSet);
retval = nspi_GetSpecialTable(nspi_ctx, mem_ctx, 0x2, &SRowSet);
MAPIFreeBuffer(SRowSet);
- mapitest_print_retval(mt, "NspiGetSpecialTable (Address Creation Template)");
+ mapitest_print_retval_clean(mt, "NspiGetSpecialTable (Address Creation Template)", retval);
talloc_free(mem_ctx);
- if (GetLastError() != MAPI_E_SUCCESS) {
- return false;
+ if (retval == MAPI_E_SUCCESS) {
+ return true;
+ } else {
+ return false;
}
-
- return true;
}
retval = nspi_GetTemplateInfo(nspi_ctx, mem_ctx,
TI_TEMPLATE|TI_SCRIPT|TI_EMT|TI_HELPFILE_NAME|TI_HELPFILE_CONTENTS,
0, NULL, &ppData);
- mapitest_print_retval(mt, "NspiGetTemplateInfo");
+ mapitest_print_retval_clean(mt, "NspiGetTemplateInfo", retval);
MAPIFreeBuffer(ppData);
talloc_free(mem_ctx);
- if (GetLastError() != MAPI_E_SUCCESS) {
- return false;
- }
- return true;
+ if (retval == MAPI_E_SUCCESS) {
+ return true;
+ } else {
+ return false;
+ }
}
lpEntryIds->lpbin = NULL;
retval = nspi_ModLinkAtt(nspi_ctx, false, PR_EMS_AB_REPORTS, 0x0, lpEntryIds);
- mapitest_print_retval(mt, "NspiModLinkAtt");
+ mapitest_print_retval_clean(mt, "NspiModLinkAtt", retval);
MAPIFreeBuffer(lpEntryIds);
- /* Assuming true for the moment */
- return true;
+ if (retval == MAPI_E_SUCCESS) {
+ return true;
+ } else {
+ return false;
+ }
}
retval = nspi_QueryColumns(nspi_ctx, mem_ctx, true, &SPropTagArray);
if (retval != MAPI_E_SUCCESS) {
- mapitest_print_retval(mt, "NspiQueryColumns");
+ mapitest_print_retval_clean(mt, "NspiQueryColumns", retval);
MAPIFreeBuffer(SPropTagArray);
talloc_free(mem_ctx);
return false;
if (SPropTagArray) {
mapitest_print(mt, "* %d columns returned\n", SPropTagArray->cValues);
- mapitest_print_retval(mt, "NspiQueryColumns");
+ mapitest_print_retval_clean(mt, "NspiQueryColumns", retval);
MAPIFreeBuffer(SPropTagArray);
}
talloc_free(mem_ctx);
ppReturnedPropTags = talloc_zero(mem_ctx, struct SPropTagArray);
ppNames = talloc_zero(mem_ctx, struct PropertyNameSet_r);
retval = nspi_GetNamesFromIDs(nspi_ctx, mem_ctx, NULL, NULL, &ppReturnedPropTags, &ppNames);
- mapitest_print_retval(mt, "NspiGetNamesFromIDs");
+ mapitest_print_retval_clean(mt, "NspiGetNamesFromIDs", retval);
MAPIFreeBuffer(ppReturnedPropTags);
MAPIFreeBuffer(ppNames);
talloc_free(mem_ctx);
- if (GetLastError() != MAPI_E_SUCCESS) {
- return false;
+ if (retval == MAPI_E_SUCCESS) {
+ return true;
+ } else {
+ return false;
}
-
- return true;
}
ppReturnedPropTags = talloc_zero(mem_ctx, struct SPropTagArray);
ppNames = talloc_zero(mem_ctx, struct PropertyNameSet_r);
retval = nspi_GetNamesFromIDs(nspi_ctx, mem_ctx, NULL, NULL, &ppReturnedPropTags, &ppNames);
- mapitest_print_retval(mt, "NspiGetNamesFromIDs");
+ mapitest_print_retval_clean(mt, "NspiGetNamesFromIDs", retval);
MAPIFreeBuffer(ppReturnedPropTags);
if ( (retval != MAPI_E_SUCCESS) || !ppNames ) {
ppReturnedPropTags = talloc_zero(mem_ctx, struct SPropTagArray);
retval = nspi_GetIDsFromNames(nspi_ctx, mem_ctx, true, ppNames->cNames, ppNames->aNames, &ppReturnedPropTags);
- mapitest_print_retval(mt, "NspiGetIDsFromNames");
+ mapitest_print_retval_clean(mt, "NspiGetIDsFromNames", retval);
MAPIFreeBuffer(ppReturnedPropTags);
MAPIFreeBuffer(ppNames);
talloc_free(mem_ctx);
- if (retval != MAPI_E_SUCCESS) {
- return false;
+ if (retval == MAPI_E_SUCCESS) {
+ return true;
+ } else {
+ return false;
}
-
- errno = retval;
- return true;
}
SRowSet = talloc_zero(mt->mem_ctx, struct SRowSet);
retval = ResolveNames(mt->session, (const char **)username, SPropTagArray, &SRowSet, &flaglist, 0);
- if (GetLastError() != MAPI_E_SUCCESS) {
- mapitest_print_retval(mt, "NspiResolveNames");
+ if (retval != MAPI_E_SUCCESS) {
+ mapitest_print_retval_clean(mt, "NspiResolveNames", retval);
MAPIFreeBuffer(SPropTagArray);
talloc_free(flaglist);
talloc_free(SRowSet);
/* NspiResolveNamesW (0x14) */
retval = ResolveNames(mt->session, (const char **)username, SPropTagArray, &SRowSet, &flaglist, MAPI_UNICODE);
MAPIFreeBuffer(SPropTagArray);
- if (GetLastError() != MAPI_E_SUCCESS) {
- mapitest_print_retval(mt, "NspiResolveNamesW");
+ mapitest_print_retval_clean(mt, "NspiResolveNamesW", retval);
+ if (retval != MAPI_E_SUCCESS) {
talloc_free(flaglist);
talloc_free(SRowSet);
return false;
}
talloc_free(flaglist);
talloc_free(SRowSet);
- mapitest_print_retval(mt, "NspiResolveNamesW");
return true;
}
ulFlags = TABLE_START;
do {
retval = GetGALTable(mt->session, SPropTagArray, &SRowSet, count, ulFlags);
- mapitest_print_retval(mt, "GetGALTable");
+ mapitest_print_retval_clean(mt, "GetGALTable", retval);
if ((!SRowSet) || (!(SRowSet->aRow))) {
ret = false;
goto cleanup;
*/
_PUBLIC_ bool mapitest_oxcfxics_CopyFolder(struct mapitest *mt)
{
- enum MAPISTATUS retval;
- struct mt_common_tf_ctx *context;
- mapi_object_t obj_htable;
- mapi_object_t obj_context;
- mapi_object_t sourcefolder;
- uint16_t version[3];
- bool ret = true;
- enum TransferStatus transferStatus;
- uint16_t progress;
- uint16_t totalSteps;
- DATA_BLOB transferdata;
+ enum MAPISTATUS retval;
+ struct mt_common_tf_ctx *context;
+ mapi_object_t obj_htable;
+ mapi_object_t obj_context;
+ mapi_object_t sourcefolder;
+ uint16_t version[3];
+ bool ret = true;
+ enum TransferStatus transferStatus;
+ uint16_t progress;
+ uint16_t totalSteps;
+ DATA_BLOB transferdata;
+ struct fx_parser_context *parser;
/* Logon */
if (! mapitest_common_setup(mt, &obj_htable, NULL)) {
ret = false;
goto cleanup;
}
+ parser = fxparser_init(mt->mem_ctx, NULL);
+ fxparser_parse(parser, &transferdata);
+ talloc_free(parser);
// TODO: verify that the buffer is as expected
cleanup:
/* Cleanup and release */
This function:
-# Log on private message store
- -# Creates a test folder
+ -# Cremapidump_fx_bufferates a test folder
-# Setup source
-# Get data
*/
_PUBLIC_ bool mapitest_oxcfxics_CopyMessages(struct mapitest *mt)
{
- enum MAPISTATUS retval;
- struct mt_common_tf_ctx *context;
- mapi_object_t obj_htable;
- mapi_object_t obj_context;
- mapi_object_t sourcefolder;
- mapi_id_array_t mids;
- int i;
- bool ret = true;
- enum TransferStatus transferStatus;
- uint16_t progress;
- uint16_t totalSteps;
- DATA_BLOB transferdata;
+ enum MAPISTATUS retval;
+ struct mt_common_tf_ctx *context;
+ mapi_object_t obj_htable;
+ mapi_object_t obj_context;
+ mapi_object_t sourcefolder;
+ mapi_id_array_t mids;
+ int i;
+ bool ret = true;
+ enum TransferStatus transferStatus;
+ uint16_t progress;
+ uint16_t totalSteps;
+ DATA_BLOB transferdata;
+ struct fx_parser_context *parser;
/* Logon */
if (! mapitest_common_setup(mt, &obj_htable, NULL)) {
ret = false;
goto cleanup;
}
+ parser = fxparser_init(mt->mem_ctx, NULL);
+ fxparser_parse(parser, &transferdata);
+ talloc_free(parser);
// TODO: verify that the buffer is as expected
cleanup:
/* Cleanup and release */
*/
_PUBLIC_ bool mapitest_oxcfxics_CopyTo(struct mapitest *mt)
{
- enum MAPISTATUS retval;
- struct mt_common_tf_ctx *context;
- mapi_object_t obj_htable;
- mapi_object_t obj_context;
- mapi_object_t sourcefolder;
- mapi_id_array_t mids;
- struct SPropTagArray *propsToExclude;
- int i;
- bool ret = true;
- enum TransferStatus transferStatus;
- uint16_t progress;
- uint16_t totalSteps;
- DATA_BLOB transferdata;
+ enum MAPISTATUS retval;
+ struct mt_common_tf_ctx *context;
+ mapi_object_t obj_htable;
+ mapi_object_t obj_context;
+ mapi_object_t sourcefolder;
+ mapi_id_array_t mids;
+ struct SPropTagArray *propsToExclude;
+ int i;
+ bool ret = true;
+ enum TransferStatus transferStatus;
+ uint16_t progress;
+ uint16_t totalSteps;
+ DATA_BLOB transferdata;
+ struct fx_parser_context *parser;
/* Logon */
if (! mapitest_common_setup(mt, &obj_htable, NULL)) {
ret = false;
goto cleanup;
}
+ parser = fxparser_init(mt->mem_ctx, NULL);
+ fxparser_parse(parser, &transferdata);
+ talloc_free(parser);
// TODO: verify that the buffer is as expected
cleanup:
/* Cleanup and release */
*/
_PUBLIC_ bool mapitest_oxcfxics_CopyProperties(struct mapitest *mt)
{
- enum MAPISTATUS retval;
- struct mt_common_tf_ctx *context;
- mapi_object_t obj_htable;
- mapi_object_t obj_context;
- mapi_object_t sourcefolder;
- struct SPropTagArray *props;
- bool ret = true;
- enum TransferStatus transferStatus;
- uint16_t progress;
- uint16_t totalSteps;
- DATA_BLOB transferdata;
-
+ enum MAPISTATUS retval;
+ struct mt_common_tf_ctx *context;
+ mapi_object_t obj_htable;
+ mapi_object_t obj_context;
+ mapi_object_t sourcefolder;
+ struct SPropTagArray *props;
+ bool ret = true;
+ enum TransferStatus transferStatus;
+ uint16_t progress;
+ uint16_t totalSteps;
+ DATA_BLOB transferdata;
+ struct fx_parser_context *parser;
/* Logon */
if (! mapitest_common_setup(mt, &obj_htable, NULL)) {
return false;
goto cleanup;
}
- props = set_SPropTagArray(mt->mem_ctx, 0x1, PR_DISPLAY_NAME);
+ props = set_SPropTagArray(mt->mem_ctx, 0x3, PR_DISPLAY_NAME, PR_FOLDER_TYPE, PR_NTSD_MODIFICATION_TIME);
retval = FXCopyProperties(&(context->obj_test_folder), 0 /* level */, 0 /*copyflags */, FastTransfer_Unicode, props, &obj_context);
mapitest_print_retval_clean(mt, "FXCopyProperties", retval);
if (retval != MAPI_E_SUCCESS) {
ret = false;
goto cleanup;
}
+ parser = fxparser_init(mt->mem_ctx, NULL);
+ fxparser_parse(parser, &transferdata);
+ talloc_free(parser);
// TODO: verify that the buffer is as expected
cleanup:
/* Cleanup and release */
ret = false;
goto cleanup;
}
+ /* 0x0400 is mfEverRead - the message has been read at least once. We see this on Exchange 2010 */
for (i = 0; i < 10; ++i) {
- if (*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i].lpProps[1])) != 0x0) {
+ if ((*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i].lpProps[1])) & ~0x0400) != 0x0) {
mapitest_print(mt, "* %-35s: unexpected flag at %i 0x%x\n", "QueryRows", i,
(*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i].lpProps[1]))));
ret = false;
goto cleanup;
}
for (i = 0; i < 10; i+=2) {
- if (*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i].lpProps[1])) != MSGFLAG_READ) {
+ if ((*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i].lpProps[1])) & ~0x0400) != MSGFLAG_READ) {
mapitest_print(mt, "* %-35s: unexpected flag (0) at %i 0x%x\n", "QueryRows", i,
(*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i].lpProps[1]))));
ret = false;
goto cleanup;
}
- if (*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i+1].lpProps[1])) != 0x0) {
+ if ((*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i+1].lpProps[1])) & ~0x0400) != 0x0) {
mapitest_print(mt, "* %-35s: unexpected flag (1) at %i 0x%x\n", "QueryRows", i,
(*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i+1].lpProps[1]))));
ret = false;
goto cleanup;
}
for (i = 0; i < 10; ++i) {
- if (*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i].lpProps[1])) != 0x0) {
- mapitest_print(mt, "* %-35s: unexpected flag at %i 0x%x\n", "QueryRows", i,
+ if ((*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i].lpProps[1])) & ~0x0400) != 0x0) {
+ mapitest_print(mt, "* %-35s: unexpected flag (3) at %i 0x%x\n", "QueryRows", i,
(*(const uint32_t *)get_SPropValue_data(&(SRowSet.aRow[i].lpProps[1]))));
ret = false;
goto cleanup;
subject = talloc_asprintf(mt->mem_ctx, "Reference: %s", "subject");
dept = talloc_asprintf(mt->mem_ctx, "Reference: %s", "dept");
set_SPropValue_proptag(&lpProp[0], PR_DISPLAY_NAME, (const void *)name);
- set_SPropValue_proptag(&lpProp[1], PR_CONVERSATION_TOPIC, (const void *)subject);
+ set_SPropValue_proptag(&lpProp[1], PR_SUBJECT, (const void *)subject);
set_SPropValue_proptag(&lpProp[2], PR_DEPARTMENT_NAME, (const void *)dept);
retval = SetProps(&obj_ref_message, lpProp, 3);
mapitest_print_retval(mt, "SetProps");
}
/* Step 4: Double check with GetProps */
- SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC,
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3, PR_DISPLAY_NAME, PR_SUBJECT,
PR_DEPARTMENT_NAME);
retval = GetProps(&obj_ref_message, SPropTagArray, &lpProps, &cValues);
MAPIFreeBuffer(SPropTagArray);
ret = false;
goto cleanup;
}
+
retval = SaveChangesMessage(&obj_ref_folder, &obj_target_message, KeepOpenReadWrite);
- mapitest_print_retval_clean(mt, "SaveChangesMessage", retval);
+ mapitest_print_retval_clean(mt, "5A. SaveChangesMessage", retval);
if (retval != MAPI_E_SUCCESS) {
ret = false;
goto cleanup;
}
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_SUBJECT);
+ retval = DeleteProps(&obj_target_message, SPropTagArray);
+ MAPIFreeBuffer(SPropTagArray);
+ mapitest_print_retval_clean(mt, "5B. DeleteProps - PR_SUBJECT", retval);
+
targ_name = talloc_asprintf(mt->mem_ctx, "Target: %s", "display name");
targ_dept = talloc_asprintf(mt->mem_ctx, "Target: %s", "department");
set_SPropValue_proptag(&lpProp[0], PR_DISPLAY_NAME, (const void *)targ_name);
}
/* Step 8: Double check with GetProps */
- SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC);
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_SUBJECT);
retval = GetProps(&obj_ref_message, SPropTagArray, &lpProps, &cValues);
MAPIFreeBuffer(SPropTagArray);
if (lpProps[0].value.lpszA) {
goto cleanup;
}
}
- SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC, PR_DEPARTMENT_NAME);
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3, PR_DISPLAY_NAME, PR_SUBJECT, PR_DEPARTMENT_NAME);
retval = GetProps(&obj_target_message, SPropTagArray, &lpProps, &cValues);
MAPIFreeBuffer(SPropTagArray);
/* this one shouldn't be overwritten */
}
/* Step 10: Double check with GetProps */
- SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC);
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_SUBJECT);
retval = GetProps(&obj_ref_message, SPropTagArray, &lpProps, &cValues);
MAPIFreeBuffer(SPropTagArray);
if (lpProps[0].value.lpszA) {
goto cleanup;
}
}
- SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC, PR_DEPARTMENT_NAME);
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3, PR_DISPLAY_NAME, PR_SUBJECT, PR_DEPARTMENT_NAME);
retval = GetProps(&obj_target_message, SPropTagArray, &lpProps, &cValues);
MAPIFreeBuffer(SPropTagArray);
/* this one should now be overwritten */
}
}
- /* Step 11: Move properties, no overwrite */
+ /* Step 11: Move properties, with overwrite */
exclude = set_SPropTagArray(mt->mem_ctx, 0x0);
- retval = CopyTo(&obj_ref_message, &obj_target_message, exclude, CopyFlagsNoOverwrite|CopyFlagsMove,
+ retval = CopyTo(&obj_ref_message, &obj_target_message, exclude, CopyFlagsMove,
&problem_count, &problems);
MAPIFreeBuffer(exclude);
MAPIFreeBuffer(problems);
- mapitest_print_retval(mt, "* Step 11 - CopyTo (move)");
+ mapitest_print_retval_clean(mt, "* Step 11 - CopyTo (move)", retval);
if (retval != MAPI_E_SUCCESS) {
ret = false;
goto cleanup;
}
/* Step 12: Double check with GetProps */
- SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC);
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x2, PR_DISPLAY_NAME, PR_SUBJECT);
retval = GetProps(&obj_ref_message, SPropTagArray, &lpProps, &cValues);
MAPIFreeBuffer(SPropTagArray);
if (cValues == 2) {
ret = false;
goto cleanup;
}
- SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3, PR_DISPLAY_NAME, PR_CONVERSATION_TOPIC, PR_DEPARTMENT_NAME);
+ SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x3, PR_DISPLAY_NAME, PR_SUBJECT, PR_DEPARTMENT_NAME);
retval = GetProps(&obj_target_message, SPropTagArray, &lpProps, &cValues);
MAPIFreeBuffer(SPropTagArray);
if (lpProps[0].value.lpszA) {
}
}
if (lpProps[2].value.lpszA) {
- if (!strncmp(targ_dept, lpProps[2].value.lpszA, strlen(lpProps[2].value.lpszA))) {
+ if (!strncmp(dept, lpProps[2].value.lpszA, strlen(lpProps[2].value.lpszA))) {
mapitest_print(mt, "* Step 12D - Check: Reference props move - [SUCCESS] (%s)\n",
lpProps[2].value.lpszA);
} else {
ret = false;
goto cleanup;
}
- SaveChangesAttachment(&obj_target_message, &obj_targ_attach, KeepOpenReadWrite);
- mapitest_print_retval(mt, "SaveChangesAttachment");
+ retval = SaveChangesAttachment(&obj_target_message, &obj_targ_attach, KeepOpenReadWrite);
+ mapitest_print_retval_clean(mt, "SaveChangesAttachment", retval);
/* Step 15: Copy props from reference email attachment to target email attachment */
exclude = set_SPropTagArray(mt->mem_ctx, 0x0);
ret = false;
goto cleanup;
}
+ retval = SaveChangesAttachment(&obj_target_message, &obj_targ_attach, KeepOpenReadWrite);
+ mapitest_print_retval_clean(mt, "SaveChangesAttachment 2", retval);
/* Step 16: Check properties on both attachments are correct */
SPropTagArray = set_SPropTagArray(mt->mem_ctx, 0x1, PR_ATTACH_FILENAME);
mapitest_print(mt, "* Step 16B - Check: Reference attachment props - [SUCCESS] (%s)\n",
lpProps[0].value.lpszA);
} else {
- mapitest_print(mt, "* Step 16B - Check: Reference attachment props [FAILURE] (%s)\n",
- lpProps[0].value.lpszA);
+ mapitest_print(mt, "* Step 16B - Check: Reference attachment props [FAILURE] (%s, %s)\n",
+ lpProps[0].value.lpszA, MT_MAIL_ATTACH);
ret = false;
goto cleanup;
}
context = mt->priv;
+ retval = SetSpooler(&(context->obj_store));
+
/* Perform the TransportNewMail operation */
for (i = 0; i<10; ++i) {
- retval = TransportNewMail(&(context->obj_test_folder), &(context->obj_test_msg[i]), "IPM.Note", 0x8);
+ retval = TransportNewMail(&(context->obj_store), &(context->obj_test_folder), &(context->obj_test_msg[i]),
+ "IPM.Note", 0x00000008);
mapitest_print_retval_clean(mt, "TransportNewMail", retval);
if (retval != MAPI_E_SUCCESS) {
ret = false;