Merge trunk changes (from r2196 up to 2259) into branch
authorJulien Kerihuel <j.kerihuel@openchange.org>
Fri, 12 Nov 2010 23:46:52 +0000 (23:46 +0000)
committerJulien Kerihuel <j.kerihuel@openchange.org>
Fri, 12 Nov 2010 23:46:52 +0000 (23:46 +0000)
Fix a bug in OpenProfile - use mapi_context instead of session for memory allocation pointer and remove session checks

44 files changed:
Makefile
VERSION
configure.ac
doc/howto.txt
exchange.idl
libmapi/IMAPIFolder.c
libmapi/IMAPIProp.c
libmapi/IMessage.c
libmapi/IMsgStore.c
libmapi/IProfAdmin.c
libmapi/conf/mapi-properties
libmapi/conf/mparse.pl
libmapi/fxparser.c [new file with mode: 0644]
libmapi/fxparser.h [new file with mode: 0644]
libmapi/libmapi.h
libmapi/libmapi_private.h
libmapi/mapi_nameid.c
libmapi/mapidefs.h
libmapi/mapidump.c
libmapi/property.c
libocpf/lex.h
libocpf/lex.l
libocpf/ocpf.y
libocpf/ocpf_api.c
libocpf/ocpf_bison.supp [new file with mode: 0644]
libocpf/ocpf_write.c
mapiproxy/dcesrv_mapiproxy_proto.h
mapiproxy/dcesrv_mapiproxy_unused.c
mapiproxy/documentation/mapiproxy-documentation.doxy
mapiproxy/libmapistore/mapistore_namedprops.c
mapiproxy/servers/default/emsmdb/dcesrv_exchange_emsmdb.c
ndr_mapi.c
script/installsamba4.sh
testprogs/check_fasttransfer.c [new file with mode: 0644]
utils/exchange2mbox.c
utils/mapitest/mapitest.h
utils/mapitest/mapitest_stat.c
utils/mapitest/mapitest_suite.c
utils/mapitest/module.c
utils/mapitest/modules/module_nspi.c
utils/mapitest/modules/module_oxcfxics.c
utils/mapitest/modules/module_oxcmsg.c
utils/mapitest/modules/module_oxcprpt.c
utils/mapitest/modules/module_oxomsg.c

index 295d285f68b80f59ec297b573acd51bb8b820bb1..9847fa7ca96230f01f9586cc02dd99f57098d7d9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -293,6 +293,7 @@ libmapi.$(SHLIBEXT).$(PACKAGE_VERSION):             \
        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                       \
@@ -1493,6 +1494,32 @@ bin/schemaIDGUID: utils/schemaIDGUID.o
        @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
diff --git a/VERSION b/VERSION
index 53888e4599802a2892240b071c5fb694230c1638..90bdd4347b3bc6766a810b275bfaf0eb0e243485 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -26,7 +26,7 @@ OPENCHANGE_VERSION_IS_SVN_SNAPSHOT=yes
 # e.g. OPENCHANGE_VERSION_RELEASE_NICKNAME=Nicky Nickname   #
 #  ->  "0.7 (Nicky Nickname)"                               #
 #############################################################
-OPENCHANGE_VERSION_RELEASE_NICKNAME=Nomad
+OPENCHANGE_VERSION_RELEASE_NICKNAME=Transporter
 
 
 #############################################################
@@ -35,4 +35,4 @@ OPENCHANGE_VERSION_RELEASE_NICKNAME=Nomad
 # 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
index 11e34d95abd6815d834b3e1d43707a2baa48b9b0..7938055b4f99938a27a86c65ff0a9e7b33776938 100644 (file)
@@ -2,7 +2,7 @@
 # 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])
@@ -550,6 +550,8 @@ if test x"$enable_libpopt" = x"yes"; then
        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)
 
index 3c33cd84d1a8b311b1efef7e578b59aba375d523..ce32f624a612228c4a7096edb0e27546d6df671a 100644 (file)
@@ -349,9 +349,12 @@ directory:
 # ./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>
 
 
index c85996c6e0f68fc28b6112852991543144b4a878..0ff040167960c4583e766d2aa5a6b1b76517f7bd 100644 (file)
@@ -1499,7 +1499,6 @@ System Attendant Private Interface
        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
@@ -4320,7 +4319,7 @@ System Attendant Private Interface
 
        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;
@@ -4347,7 +4346,7 @@ System Attendant Private Interface
 
        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;
@@ -4444,6 +4443,36 @@ System Attendant Private Interface
                [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
+               );
 }
 
 [
index a85b28d0ec773b44f234015bfd35d49c74e6d24f..94bbaab9a6d4ee26106d5b43c2c3e5da632c8e3a 100644 (file)
@@ -666,7 +666,7 @@ _PUBLIC_ enum MAPISTATUS CreateFolder(mapi_object_t *obj_parent,
                break;
        case MAPI_FOLDER_UNICODE:
                request.FolderName.lpszW = name;
-               size += strlen(name) * 2 + 2;
+               size += get_utf8_utf16_conv_length(name);
                break;
        }
 
@@ -678,7 +678,7 @@ _PUBLIC_ enum MAPISTATUS CreateFolder(mapi_object_t *obj_parent,
                        break;
                case MAPI_FOLDER_UNICODE:
                        request.FolderComment.lpszW = comment;
-                       size += strlen(comment) * 2 + 2;
+                       size +=  get_utf8_utf16_conv_length(comment);
                        break;
                }
        } else {
@@ -983,7 +983,7 @@ _PUBLIC_ enum MAPISTATUS MoveFolder(mapi_object_t *obj_folder,
                size += strlen(NewFolderName) + 1;
        } else {
                request.NewFolderName.lpszW = NewFolderName;
-               size += strlen(NewFolderName) * 2 + 2;
+               size += get_utf8_utf16_conv_length(NewFolderName);
        }
 
 
@@ -1099,7 +1099,7 @@ _PUBLIC_ enum MAPISTATUS CopyFolder(mapi_object_t *obj_folder,
                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 */
index d6238a06069b38598dbd117a6cb0f06d09745c00..591800b400c4e2357b4fc169b421646c08bfcbc7 100644 (file)
@@ -1003,7 +1003,7 @@ _PUBLIC_ enum MAPISTATUS GetIDsFromNames(mapi_object_t *obj,
                        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:
index 25102baf26d9885279fb116436f97c4bc376e40a..54c840ec98a8dea13f5d867ca515f18228d3fafe 100644 (file)
@@ -722,9 +722,8 @@ _PUBLIC_ enum MAPISTATUS ModifyRecipients(mapi_object_t *obj_message,
         * 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,
@@ -741,7 +740,9 @@ _PUBLIC_ enum MAPISTATUS ModifyRecipients(mapi_object_t *obj_message,
                                                     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);
@@ -798,7 +799,7 @@ _PUBLIC_ enum MAPISTATUS ModifyRecipients(mapi_object_t *obj_message,
                        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;
@@ -812,7 +813,7 @@ _PUBLIC_ enum MAPISTATUS ModifyRecipients(mapi_object_t *obj_message,
                        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;
@@ -826,7 +827,7 @@ _PUBLIC_ enum MAPISTATUS ModifyRecipients(mapi_object_t *obj_message,
                        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;
@@ -841,7 +842,7 @@ _PUBLIC_ enum MAPISTATUS ModifyRecipients(mapi_object_t *obj_message,
                        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;
index 0d688dc51596627041b4a22fb5b849864a96338d..5074676ad9d06bd8d017a2fc3a4cefb951b4212b 100644 (file)
@@ -874,6 +874,7 @@ _PUBLIC_ enum MAPISTATUS GetOutboxFolder(mapi_object_t *obj_store,
 /**
    \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
@@ -890,7 +891,8 @@ _PUBLIC_ enum MAPISTATUS GetOutboxFolder(mapi_object_t *obj_store,
 
    \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;
@@ -905,6 +907,7 @@ _PUBLIC_ enum MAPISTATUS TransportNewMail(mapi_object_t *obj_folder, mapi_object
        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);
@@ -941,7 +944,7 @@ _PUBLIC_ enum MAPISTATUS TransportNewMail(mapi_object_t *obj_folder, mapi_object
        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);
index 0dda4260f82ff47b7235ad0dc5e7a247b3196e3a..19f46d3dcea5dbc44d06d843e919cc3fe3e158e8 100644 (file)
@@ -705,10 +705,9 @@ _PUBLIC_ enum MAPISTATUS OpenProfile(struct mapi_context *mapi_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);
index 6443d90a9f028e8f0cbf9b99885ebd5a7f5bcebb..ae1d10125b02f4465b82bde86d6093fd1187fae7 100644 (file)
 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
index 8795ec2bb59b201c9ed9b25d45efcb179428c457..13d7a33cf6faf7db8ad88c36a25b07eeb96bc9de 100755 (executable)
@@ -564,6 +564,7 @@ sub mapicodes_interface($)
     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 "}";
diff --git a/libmapi/fxparser.c b/libmapi/fxparser.c
new file mode 100644 (file)
index 0000000..8f305ac
--- /dev/null
@@ -0,0 +1,493 @@
+/*
+   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;
+       }
+}
diff --git a/libmapi/fxparser.h b/libmapi/fxparser.h
new file mode 100644 (file)
index 0000000..b5436b6
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+   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
index e6e87fc806f7cfce6f5aa185df3231145044fa53..413bbecddf38c3ebf617223846cc4ec2cacdd6a5 100644 (file)
@@ -404,7 +404,7 @@ enum MAPISTATUS             GetTransportFolder(mapi_object_t *, mapi_id_t *);
 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);
@@ -472,6 +472,20 @@ enum MAPISTATUS            GetFIDFromEntryID(uint16_t, uint8_t *, uint64_t, uint64_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
index 7b493faeb0ac7c83af8a80ea7a7cda0a0bdfbdd3..9b1c6511af0da1ea33805849b1ddb1c83126a2a5 100644 (file)
@@ -106,7 +106,7 @@ void                        mapi_object_table_init(TALLOC_CTX *, mapi_object_t *);
 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 *);
 
index 538922b0e3e9ae8a29cc1e16767527faa20ee64f..01085c32aa06b0c947b078f596994e5259bedb6d 100644 (file)
@@ -112,7 +112,7 @@ _PUBLIC_ enum MAPISTATUS mapi_nameid_OOM_add(struct mapi_nameid *mapi_nameid,
                                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++;
@@ -177,7 +177,7 @@ _PUBLIC_ enum MAPISTATUS mapi_nameid_lid_add(struct mapi_nameid *mapi_nameid,
                                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++;
@@ -244,7 +244,7 @@ _PUBLIC_ enum MAPISTATUS mapi_nameid_string_add(struct mapi_nameid *mapi_nameid,
                                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++;
@@ -353,7 +353,7 @@ _PUBLIC_ enum MAPISTATUS mapi_nameid_custom_string_add(struct mapi_nameid *mapi_
        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;
@@ -408,7 +408,7 @@ _PUBLIC_ enum MAPISTATUS mapi_nameid_canonical_add(struct mapi_nameid *mapi_name
                                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++;
index 86eff81ad695235134b9c3856d49d34a12d33376..00e27c8901768bf5eeaa837a4eaca4b6387ea77b 100644 (file)
 #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
index 5abf1444ae36a5a56628df7ba60e433a949eeb6e..1b3b21ba3bc1ab6d294329fea336e3feecba0359 100644 (file)
@@ -64,6 +64,15 @@ _PUBLIC_ void mapidump_SPropValue(struct SPropValue lpProp, const char *sep)
                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));
@@ -75,7 +84,17 @@ _PUBLIC_ void mapidump_SPropValue(struct SPropValue lpProp, const char *sep)
        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);
@@ -84,14 +103,25 @@ _PUBLIC_ void mapidump_SPropValue(struct SPropValue lpProp, const char *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);
@@ -990,7 +1020,6 @@ _PUBLIC_ void mapidump_freebusy_event(struct Binary_r *bin, uint32_t month, uint
                                }
                        }
                }
-               
        }       
 }
 
index 8c4f2e5062f4b667ab7c94e7a907441fc38811c7..011969e5c5b962924b4926a5c4f7de64bb257429 100644 (file)
@@ -183,7 +183,9 @@ _PUBLIC_ const void *get_SPropValue_SRow_data(struct SRow *aRow,
   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;
@@ -197,6 +199,8 @@ enum MAPITAGS *get_MAPITAGS_SRow(TALLOC_CTX *mem_ctx, struct SRow *aRow)
                }
        }
        mapitags[idx] = 0;
+       *actual_count = idx;
+
        return mapitags;
 }
 
@@ -319,6 +323,8 @@ _PUBLIC_ const void *get_SPropValue_data(struct SPropValue *lpProps)
                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:
@@ -451,7 +457,7 @@ _PUBLIC_ uint32_t get_mapi_property_size(struct mapi_SPropValue *lpProp)
        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:
@@ -500,7 +506,7 @@ _PUBLIC_ uint32_t cast_mapi_SPropValue(TALLOC_CTX *mem_ctx,
        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;
@@ -634,7 +640,7 @@ _PUBLIC_ uint32_t cast_SPropValue(TALLOC_CTX *mem_ctx,
        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;
@@ -765,7 +771,7 @@ _PUBLIC_ uint32_t cast_SPropValue(TALLOC_CTX *mem_ctx,
 /**
    \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
index a76890d58c9ffee2f4fc103f7d5ee9b86d6e5e22..597d20019fed57d5ac13737c7f449006eed60bc9 100644 (file)
@@ -20,7 +20,7 @@
 #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;
 
index e799473d8b0a73544e8cf3ce7baa97d596647400..983b27ad599dd08a045e997a12f2cef57e56fd6b 100644 (file)
@@ -79,6 +79,7 @@ PT_STRING8    { return kw_PT_STRING8; }
 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; }
@@ -260,6 +261,17 @@ B\"true\"|-?B\"false\" { char *y = yytext + 1;
                           }
                           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;
@@ -269,7 +281,7 @@ T[0-9]{4}-[0-9]{2}-[0-9]{2}[ ][0-9]{2}\:[0-9]{2}\:[0-9]{2} {
                        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;
                        }
@@ -278,7 +290,7 @@ T[0-9]{4}-[0-9]{2}-[0-9]{2}[ ][0-9]{2}\:[0-9]{2}\:[0-9]{2} {
                        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;
                        
@@ -289,7 +301,7 @@ S0x[0-9A-Fa-f]+|-S[0-9]+ {
                           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;
                         }
@@ -300,7 +312,7 @@ L0x[0-9A-Fa-f]+|-?[0-9]+ {
                          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;
                        }
@@ -309,7 +321,7 @@ D0x[0-9A-Fa-f]+             {
                          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;
 
@@ -325,11 +337,11 @@ D0x[0-9A-Fa-f]+           {
                }
 .                      { 
                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;
 
@@ -344,6 +356,6 @@ void error_message(struct ocpf_context *ctx, const char *format, ...)
 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
index ff9d0e3c5c5ebf3a1cde2584b6b591d6f161213e..180500e1723d9edc53574c298982ac5f8c0139b3 100644 (file)
@@ -40,6 +40,7 @@ void yyerror(struct ocpf_context *, void *, char *);
        uint16_t                        s;
        uint32_t                        l;
        uint64_t                        d;
+       double                          dbl;
        char                            *name;
        char                            *nameW;
        char                            *date;
@@ -55,6 +56,7 @@ void yyerror(struct ocpf_context *, void *, char *);
 %token <s> SHORT
 %token <l> INTEGER
 %token <d> I8
+%token <dbl> DOUBLE
 %token <name> IDENTIFIER
 %token <name> STRING
 %token <nameW> UNICODE
@@ -81,6 +83,7 @@ void yyerror(struct ocpf_context *, void *, char *);
 %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
@@ -123,7 +126,7 @@ Type                :
                          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;
                        }
                }
@@ -136,7 +139,7 @@ Folder              :
                                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
@@ -145,7 +148,7 @@ Folder              :
                                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
@@ -154,7 +157,7 @@ Folder              :
                                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");
                        }
                }
                ;
@@ -226,6 +229,7 @@ propvalue   : STRING
                | 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);
@@ -390,7 +394,7 @@ binary_contents: | binary_contents binary_content
 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) {
@@ -426,7 +430,6 @@ mvbin_content       : OBRACE binary_contents EBRACE COMMA
                                                                                               ctx->bin.cb);
                        ctx->lpProp.MVbin.cValues += 1;
 
-                       talloc_free(ctx->bin.lpb);
                        ctx->bin.cb = 0;
                }
                ;
@@ -500,6 +503,11 @@ proptype   : kw_PT_STRING8
                        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));
index 13f65233e4727c22cd0cdaded26a7190daf26b0a..d591157a401920830bcb6cb69f8905bfa4d0ca93 100644 (file)
@@ -140,6 +140,9 @@ int ocpf_set_propvalue(TALLOC_CTX *mem_ctx,
        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;
@@ -595,6 +598,7 @@ int ocpf_add_filetime(const char *date, struct FILETIME *ft)
        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;
diff --git a/libocpf/ocpf_bison.supp b/libocpf/ocpf_bison.supp
new file mode 100644 (file)
index 0000000..3468e69
--- /dev/null
@@ -0,0 +1,19 @@
+{
+   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
+}
index 38b0a38f0d236f5cdd586b3ac8ad7e520cc92a6f..b1bfbaeab2e7dd3d5ec5f24e045bb53e110242d9 100644 (file)
@@ -369,6 +369,10 @@ static char *ocpf_write_property(struct ocpf_context *ctx, bool *found, uint32_t
                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;
index b11127e678cd388eb5d286438eccb2596a8059e8..c9a3da0897320ec554f3d19e48ad00af9fa50a80 100644 (file)
@@ -64,6 +64,7 @@ NTSTATUS dcerpc_server_exchange_mta_qadmin_init(void);
 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 */
@@ -147,8 +148,14 @@ void dcesrv_EcRNetGetDCName(struct dcesrv_call_state *, TALLOC_CTX *,struct EcRN
 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__ */
index cf79deb11d7b3540b50539c36bb4582ce375cbd6..96913f61af2c9143162945be93412be04177eea9 100644 (file)
@@ -772,6 +772,42 @@ enum MAPISTATUS dcesrv_EcDoRpcExt2(struct dcesrv_call_state  *dce_call, TALLOC_C
        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
 */
index 13675a2f5a933278ac37fdf9947de3e3ccc69826..62b9689bc477004064aa16d65482114d82cda293 100644 (file)
@@ -1190,9 +1190,9 @@ Samba does. It only extends existing users from the SAM database and
 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
index 07baf869c7be06adf4003ebd3057e3167a350d5e..91f38d83b7aa22e3ff1debf14ee3fd7257d3a017 100644 (file)
@@ -143,7 +143,7 @@ _PUBLIC_ int mapistore_namedprops_get_mapped_id(void *ldb_ctx,
        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);
index bd9551cab2250f966f0aa7128b5f453aa6a39653..e5b3d7d71808deb5f03c31dd5ba43d2b87a81761 100644 (file)
@@ -148,10 +148,18 @@ static enum MAPISTATUS dcesrv_EcDoConnect(struct dcesrv_call_state *dce_call,
        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];
@@ -243,57 +251,31 @@ static enum MAPISTATUS dcesrv_EcDoDisconnect(struct dcesrv_call_state *dce_call,
 }
 
 
-/**
-   \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++) {
@@ -672,8 +654,51 @@ static enum MAPISTATUS dcesrv_EcDoRpc(struct dcesrv_call_state *dce_call,
        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;
@@ -860,6 +885,153 @@ static enum MAPISTATUS dcesrv_EcDoConnectEx(struct dcesrv_call_state *dce_call,
        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
@@ -923,6 +1095,18 @@ static NTSTATUS dcesrv_exchange_emsmdb_dispatch(struct dcesrv_call_state *dce_ca
                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;
index 9dff2ab0b1ea7ac7d541d46da2f245cc8f84046b..c58bc2e10e824e675979f08528b38842aef7e8f1 100644 (file)
@@ -1346,24 +1346,24 @@ _PUBLIC_ void ndr_print_EcDoConnectEx(struct ndr_print *ndr, const char *name, i
                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++) {
@@ -1388,7 +1388,12 @@ _PUBLIC_ void ndr_print_EcDoConnectEx(struct ndr_print *ndr, const char *name, i
                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);
@@ -1493,14 +1498,18 @@ _PUBLIC_ void ndr_print_EcDoRpcExt2(struct ndr_print *ndr, const char *name, int
                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);
index 883086331c5d82d4c430ac33506f2466687113b8..ecb29837bd1b59dd34306c7ddf2401f1b45bd541 100755 (executable)
@@ -12,18 +12,22 @@ else
 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,'/')"`
@@ -111,7 +115,7 @@ checkout() {
     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"
@@ -248,23 +252,23 @@ packages() {
 
        ./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
@@ -279,11 +283,11 @@ compile() {
     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
diff --git a/testprogs/check_fasttransfer.c b/testprogs/check_fasttransfer.c
new file mode 100644 (file)
index 0000000..025ddb6
--- /dev/null
@@ -0,0 +1,460 @@
+/*
+   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;
+}
index e5277c7293bd5137cecb84c034ea85d097ac1623..7881cca5155b7a2ccac1b755b7a0dfee73ad55f1 100644 (file)
@@ -313,6 +313,7 @@ static bool message2mbox(TALLOC_CTX *mem_ctx, FILE *fp,
        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;
@@ -352,6 +353,7 @@ static bool message2mbox(TALLOC_CTX *mem_ctx, FILE *fp,
        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);
 
@@ -407,6 +409,12 @@ static bool message2mbox(TALLOC_CTX *mem_ctx, FILE *fp,
                        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) {
@@ -747,7 +755,7 @@ int main(int argc, const char *argv[])
                                             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,
@@ -768,7 +776,11 @@ int main(int argc, const char *argv[])
                                                                  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) {
index 95691263459641edd69c91304efbd98e93bdd114..20669e1548b1dbbe8c83357d975c6dac05c22bd9 100644 (file)
@@ -49,10 +49,19 @@ enum TestApplicabilityFlags {
        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"
 
@@ -85,7 +94,7 @@ struct mapitest_unit {
        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) */
 };
 
 /**
@@ -98,12 +107,13 @@ struct mapitest_unit {
        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 */
 };
 
 /**
@@ -198,8 +208,8 @@ struct mt_common_tf_ctx
 #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      '#'
@@ -218,9 +228,8 @@ struct mt_common_tf_ctx
 #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"
 
index ca9bf5707f2526ef320545338e3437d2dca13b8c..62788a284a63e5c35bcb95b5d167d9040a6ec9c2 100644 (file)
@@ -21,6 +21,8 @@
 
 #include "utils/mapitest/mapitest.h"
 
+#include <assert.h>
+
 /**
        \file
        mapitest statistics functions
@@ -60,6 +62,7 @@ _PUBLIC_ struct mapitest_stat *mapitest_stat_init(TALLOC_CTX *mem_ctx)
        stat->success = 0;
        stat->failure = 0;
        stat->skipped = 0;
+       stat->x_fail = 0;
        stat->failure_info = NULL;
        stat->skip_info = NULL;
        stat->enabled = false;
@@ -79,20 +82,31 @@ _PUBLIC_ struct mapitest_stat *mapitest_stat_init(TALLOC_CTX *mem_ctx)
  */
 _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 *);
        }
 
@@ -161,6 +175,7 @@ _PUBLIC_ int32_t mapitest_stat_dump(struct mapitest *mt)
        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) {
@@ -168,7 +183,7 @@ _PUBLIC_ int32_t mapitest_stat_dump(struct mapitest *mt)
                        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);
                                }
                        }
                }
@@ -182,9 +197,10 @@ _PUBLIC_ int32_t mapitest_stat_dump(struct mapitest *mt)
                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);
                                }
                        }
                }
@@ -196,6 +212,7 @@ _PUBLIC_ int32_t mapitest_stat_dump(struct mapitest *mt)
        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;
index def19bac9971806dc7cecd456e92360f4e491dda..e3985c9ff1ef5f1839e5af5c34d1f8e2ef2841b1 100644 (file)
@@ -208,6 +208,39 @@ static bool mapitest_suite_test_is_applicable(struct mapitest *mt, struct mapite
        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
    
@@ -223,24 +256,12 @@ _PUBLIC_ bool mapitest_suite_run_test(struct mapitest *mt,
 {
        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;
                }
        }
@@ -343,6 +364,14 @@ _PUBLIC_ bool mapitest_run_test(struct mapitest *mt, const char *name)
        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
@@ -351,35 +380,18 @@ _PUBLIC_ bool mapitest_run_test(struct mapitest *mt, const char *name)
 
    \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;
 }
index 2f62f2197e1870ec9693a620c6104b4a1e07e92e..c15214d40ea6ae8a2dbda9e3098ae791a8b5b0d8 100644 (file)
@@ -478,7 +478,7 @@ _PUBLIC_ uint32_t module_lzxpress_init(struct mapitest *mt)
 
        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);
 
index ccdc53d378276f78fbf0bed22ab322dc75714f77..d457f02d049140f2ec37afc994b5f7906eb55dc4 100644 (file)
@@ -50,14 +50,14 @@ _PUBLIC_ bool mapitest_nspi_UpdateStat(struct mapitest *mt)
        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;
        }
@@ -110,8 +110,8 @@ _PUBLIC_ bool mapitest_nspi_QueryRows(struct mapitest *mt)
        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;
@@ -121,8 +121,8 @@ _PUBLIC_ bool mapitest_nspi_QueryRows(struct mapitest *mt)
        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;
@@ -149,33 +149,48 @@ _PUBLIC_ bool mapitest_nspi_SeekEntries(struct mapitest *mt)
        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;
 }
 
 
@@ -196,6 +211,7 @@ _PUBLIC_ bool mapitest_nspi_GetMatches(struct mapitest *mt)
        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;
@@ -222,14 +238,13 @@ _PUBLIC_ bool mapitest_nspi_GetMatches(struct mapitest *mt)
        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;
 }
 
 
@@ -251,6 +266,7 @@ _PUBLIC_ bool mapitest_nspi_ResortRestriction(struct mapitest *mt)
        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;
@@ -287,8 +303,8 @@ _PUBLIC_ bool mapitest_nspi_ResortRestriction(struct mapitest *mt)
        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;
@@ -296,19 +312,16 @@ _PUBLIC_ bool mapitest_nspi_ResortRestriction(struct mapitest *mt)
 
        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;
 }
 
 
@@ -341,13 +354,13 @@ _PUBLIC_ bool mapitest_nspi_DNToMId(struct mapitest *mt)
        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;
 }
 
 
@@ -450,7 +463,7 @@ _PUBLIC_ bool mapitest_nspi_GetProps(struct mapitest *mt)
        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;
@@ -459,18 +472,18 @@ _PUBLIC_ bool mapitest_nspi_GetProps(struct mapitest *mt)
        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;
 }
 
 
@@ -516,8 +529,8 @@ _PUBLIC_ bool mapitest_nspi_CompareMIds(struct mapitest *mt)
        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;
@@ -532,9 +545,9 @@ _PUBLIC_ bool mapitest_nspi_CompareMIds(struct mapitest *mt)
        }
 
        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;
        }
@@ -566,6 +579,8 @@ _PUBLIC_ bool mapitest_nspi_ModProps(struct mapitest *mt)
        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;
@@ -591,8 +606,8 @@ _PUBLIC_ bool mapitest_nspi_ModProps(struct mapitest *mt)
        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;
@@ -601,31 +616,84 @@ _PUBLIC_ bool mapitest_nspi_ModProps(struct mapitest *mt)
        /* 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;
 }
 
 
@@ -649,9 +717,9 @@ _PUBLIC_ bool mapitest_nspi_GetSpecialTable(struct mapitest *mt)
        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;
        }
@@ -659,14 +727,14 @@ _PUBLIC_ bool mapitest_nspi_GetSpecialTable(struct mapitest *mt)
        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;
 }
 
 
@@ -691,14 +759,15 @@ _PUBLIC_ bool mapitest_nspi_GetTemplateInfo(struct mapitest *mt)
        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;
+       }
 }
 
 
@@ -723,11 +792,14 @@ _PUBLIC_ bool mapitest_nspi_ModLinkAtt(struct mapitest *mt)
        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;
+       }
 }
 
 
@@ -753,7 +825,7 @@ _PUBLIC_ bool mapitest_nspi_QueryColumns(struct mapitest *mt)
 
        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;
@@ -761,7 +833,7 @@ _PUBLIC_ bool mapitest_nspi_QueryColumns(struct mapitest *mt)
 
        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);
@@ -792,16 +864,16 @@ _PUBLIC_ bool mapitest_nspi_GetNamesFromIDs(struct mapitest *mt)
        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;
 }
 
 
@@ -827,7 +899,7 @@ _PUBLIC_ bool mapitest_nspi_GetIDsFromNames(struct mapitest *mt)
        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 ) {
@@ -838,17 +910,16 @@ _PUBLIC_ bool mapitest_nspi_GetIDsFromNames(struct mapitest *mt)
 
        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;
 }
 
 
@@ -895,8 +966,8 @@ _PUBLIC_ bool mapitest_nspi_ResolveNames(struct mapitest *mt)
        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);
@@ -909,15 +980,14 @@ _PUBLIC_ bool mapitest_nspi_ResolveNames(struct mapitest *mt)
        /* 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;
 }
@@ -959,7 +1029,7 @@ _PUBLIC_ bool mapitest_nspi_GetGALTable(struct mapitest *mt)
        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;
index bfe6fad743d0c6d82695fa8bcc590d550250a511..54aec1dc04d16375440c7a7e4824ac7b97c7d613 100644 (file)
@@ -165,17 +165,18 @@ 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)) {
@@ -230,6 +231,9 @@ _PUBLIC_ bool mapitest_oxcfxics_CopyFolder(struct mapitest *mt)
                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 */
@@ -246,24 +250,25 @@ cleanup:
 
    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)) {
@@ -323,6 +328,9 @@ _PUBLIC_ bool mapitest_oxcfxics_CopyMessages(struct mapitest *mt)
                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 */
@@ -345,19 +353,20 @@ cleanup:
  */
 _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)) {
@@ -418,6 +427,9 @@ _PUBLIC_ bool mapitest_oxcfxics_CopyTo(struct mapitest *mt)
                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 */
@@ -440,18 +452,18 @@ cleanup:
  */
 _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;
@@ -472,7 +484,7 @@ _PUBLIC_ bool mapitest_oxcfxics_CopyProperties(struct mapitest *mt)
                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) {
@@ -496,6 +508,9 @@ _PUBLIC_ bool mapitest_oxcfxics_CopyProperties(struct mapitest *mt)
                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 */
index c0fdf2add564dc27c31c6e8b945f25ddebb8538e..e03297287e03a990318f9354cea961ba9877ce05 100644 (file)
@@ -1110,8 +1110,9 @@ _PUBLIC_ bool mapitest_oxcmsg_SetReadFlags(struct mapitest *mt)
                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;
@@ -1137,13 +1138,13 @@ _PUBLIC_ bool mapitest_oxcmsg_SetReadFlags(struct mapitest *mt)
                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;
@@ -1160,8 +1161,8 @@ _PUBLIC_ bool mapitest_oxcmsg_SetReadFlags(struct mapitest *mt)
                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;
index bc6d70ebf113048383efba288dbd88652d32a835..5d220cec35d95e9374bbfa543ed666ec6414b7b2 100644 (file)
@@ -1468,7 +1468,7 @@ _PUBLIC_ bool mapitest_oxcprpt_CopyTo(struct mapitest *mt)
        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");
@@ -1478,7 +1478,7 @@ _PUBLIC_ bool mapitest_oxcprpt_CopyTo(struct mapitest *mt)
        }
 
        /* 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);
@@ -1523,13 +1523,19 @@ _PUBLIC_ bool mapitest_oxcprpt_CopyTo(struct mapitest *mt)
                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);
@@ -1584,7 +1590,7 @@ _PUBLIC_ bool mapitest_oxcprpt_CopyTo(struct mapitest *mt)
        }
 
        /* 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) {
@@ -1609,7 +1615,7 @@ _PUBLIC_ bool mapitest_oxcprpt_CopyTo(struct mapitest *mt)
                        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 */
@@ -1661,7 +1667,7 @@ _PUBLIC_ bool mapitest_oxcprpt_CopyTo(struct mapitest *mt)
        }
 
        /* 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) {
@@ -1686,7 +1692,7 @@ _PUBLIC_ bool mapitest_oxcprpt_CopyTo(struct mapitest *mt)
                        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 */
@@ -1726,20 +1732,20 @@ _PUBLIC_ bool mapitest_oxcprpt_CopyTo(struct mapitest *mt)
                }
        }
 
-       /* 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) {
@@ -1749,7 +1755,7 @@ _PUBLIC_ bool mapitest_oxcprpt_CopyTo(struct mapitest *mt)
                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) {
@@ -1775,7 +1781,7 @@ _PUBLIC_ bool mapitest_oxcprpt_CopyTo(struct mapitest *mt)
                }
        }
        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 {
@@ -1827,8 +1833,8 @@ _PUBLIC_ bool mapitest_oxcprpt_CopyTo(struct mapitest *mt)
                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);
@@ -1840,6 +1846,8 @@ _PUBLIC_ bool mapitest_oxcprpt_CopyTo(struct mapitest *mt)
                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);
@@ -1855,8 +1863,8 @@ _PUBLIC_ bool mapitest_oxcprpt_CopyTo(struct mapitest *mt)
                        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;
                }
index 6714125f10740bee5c53dd2d315b7efceecd56b3..b82f81e60696fb843d10692f8b68610d7da03096 100644 (file)
@@ -567,9 +567,12 @@ _PUBLIC_ bool mapitest_oxomsg_TransportNewMail(struct mapitest *mt)
 
        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;